libeufin

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

TalerMessage.kt (15015B)


      1 /*
      2  * This file is part of LibEuFin.
      3  * Copyright (C) 2024, 2025, 2026 Taler Systems S.A.
      4  *
      5  * LibEuFin is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU Affero General Public License as
      7  * published by the Free Software Foundation; either version 3, or
      8  * (at your option) any later version.
      9  *
     10  * LibEuFin is distributed in the hope that it will be useful, but
     11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
     12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Affero General
     13  * Public License for more details.
     14  *
     15  * You should have received a copy of the GNU Affero General Public
     16  * License along with LibEuFin; see the file COPYING.  If not, see
     17  * <http://www.gnu.org/licenses/>
     18  */
     19 
     20 package tech.libeufin.common
     21 
     22 import io.github.smiley4.schemakenerator.core.annotations.Description
     23 import kotlinx.serialization.SerialName
     24 import kotlinx.serialization.Serializable
     25 
     26 enum class IncomingType {
     27     reserve,
     28     kyc,
     29     map
     30 }
     31 
     32 @Description("State of a wire transfer")
     33 enum class TransferStatusState {
     34     pending,
     35     transient_failure,
     36     permanent_failure,
     37     success
     38 }
     39 
     40 /** Response GET /taler-wire-gateway/config */
     41 @Serializable
     42 @Description("Wire gateway configuration response")
     43 data class WireGatewayConfig(
     44     @Description("Currency supported by the gateway")
     45     val currency: String,
     46     @Description("Whether account check is supported")
     47     val support_account_check: Boolean
     48 ) {
     49     @Description("API name identifier")
     50     val name: String = "taler-wire-gateway"
     51     @Description("API version string")
     52     val version: String = WIRE_GATEWAY_API_VERSION
     53 }
     54 
     55 /** Request POST /taler-wire-gateway/transfer */
     56 @Serializable
     57 @Description("Wire transfer request")
     58 data class TransferRequest(
     59     @Description("Unique identifier for this request")
     60     val request_uid: HashCode,
     61     @Description("Amount to transfer")
     62     val amount: TalerAmount,
     63     @Description("Base URL of the exchange")
     64     val exchange_base_url: BaseURL,
     65     @Description("Wire transfer identifier")
     66     val wtid: ShortHashCode,
     67     @Description("Payto URI of the credit account")
     68     val credit_account: Payto,
     69     @Description("Optional transfer metadata")
     70     val metadata: String? = null,
     71 ) {
     72     init {
     73         if (metadata != null && !METADATA_REGEX.matches(metadata))
     74             throw badRequest("metadata '$metadata' is malformed, must match [a-zA-Z0-9-.+:]{1,40}")
     75     }
     76     
     77     companion object {
     78         private val METADATA_REGEX = Regex("^[a-zA-Z0-9-.:]{1,40}$")
     79     }
     80 }
     81 
     82 /** Response POST /taler-wire-gateway/transfer */
     83 @Serializable
     84 @Description("Wire transfer response")
     85 data class TransferResponse(
     86     @Description("Timestamp of the transfer")
     87     val timestamp: TalerTimestamp,
     88     @Description("Database row identifier")
     89     val row_id: Long
     90 )
     91 
     92 /** Request GET /taler-wire-gateway/transfers */
     93 @Serializable
     94 @Description("List of wire transfers")
     95 data class TransferList(
     96     @Description("List of transfer statuses")
     97     val transfers: List<TransferListStatus>,
     98     @Description("Payto URI of the debit account")
     99     val debit_account: String
    100 )
    101 
    102 @Serializable
    103 @Description("Transfer status in a list response")
    104 data class TransferListStatus(
    105     @Description("Database row identifier")
    106     val row_id: Long,
    107     @Description("Current transfer status")
    108     val status: TransferStatusState,
    109     @Description("Transfer amount")
    110     val amount: TalerAmount,
    111     @Description("Payto URI of the credit account")
    112     val credit_account: String,
    113     @Description("Timestamp of the transfer")
    114     val timestamp: TalerTimestamp
    115 )
    116 
    117 /** Request GET /taler-wire-gateway/transfers/{ROW_iD} */
    118 @Serializable
    119 @Description("Detailed status of a single transfer")
    120 data class TransferStatus(
    121     @Description("Current transfer status")
    122     val status: TransferStatusState,
    123     @Description("Optional status message")
    124     val status_msg: String? = null,
    125     @Description("Transfer amount")
    126     val amount: TalerAmount,
    127     @Description("URL of the originating exchange")
    128     val origin_exchange_url: String,
    129     @Description("Optional transfer metadata")
    130     val metadata: String? = null,
    131     @Description("Wire transfer identifier")
    132     val wtid: ShortHashCode,
    133     @Description("Payto URI of the credit account")
    134     val credit_account: String,
    135     @Description("Timestamp of the transfer")
    136     val timestamp: TalerTimestamp
    137 )
    138 
    139 /** Request POST /taler-wire-gateway/admin/add-incoming */
    140 @Serializable
    141 @Description("Request to add an incoming transaction")
    142 data class AddIncomingRequest(
    143     @Description("Amount of the incoming transaction")
    144     val amount: TalerAmount,
    145     @Description("Reserve public key")
    146     val reserve_pub: EddsaPublicKey,
    147     @Description("Payto URI of the debit account")
    148     val debit_account: Payto
    149 )
    150 
    151 /** Response POST /taler-wire-gateway/admin/add-incoming */
    152 @Serializable
    153 @Description("Response to adding an incoming transaction")
    154 data class AddIncomingResponse(
    155     @Description("Timestamp of the transaction")
    156     val timestamp: TalerTimestamp,
    157     @Description("Database row identifier")
    158     val row_id: Long
    159 )
    160 
    161 /** Request POST /taler-wire-gateway/admin/add-kycauth */
    162 @Serializable
    163 @Description("Request to add a KYC auth transaction")
    164 data class AddKycauthRequest(
    165     @Description("Amount of the KYC auth transaction")
    166     val amount: TalerAmount,
    167     @Description("Account public key for KYC")
    168     val account_pub: EddsaPublicKey,
    169     @Description("Payto URI of the debit account")
    170     val debit_account: Payto
    171 )
    172 
    173 /** Request POST /taler-wire-gateway/admin/add-mapped */
    174 @Serializable
    175 data class AddMappedRequest(
    176     val amount: TalerAmount,
    177     val authorization_pub: EddsaPublicKey,
    178     val debit_account: Payto
    179 )
    180 
    181 /** Response GET /taler-wire-gateway/history/incoming */
    182 @Serializable
    183 @Description("History of incoming transactions")
    184 data class IncomingHistory(
    185     @Description("List of incoming transactions")
    186     val incoming_transactions: List<IncomingBankTransaction>,
    187     @Description("Payto URI of the credit account")
    188     val credit_account: String
    189 )
    190 
    191 /** Inner response GET /taler-wire-gateway/history/incoming */
    192 @Serializable
    193 @Description("Incoming bank transaction details")
    194 sealed interface IncomingBankTransaction {
    195     val row_id: Long
    196     val date: TalerTimestamp
    197     val amount: TalerAmount
    198     val debit_account: String
    199     val credit_fee: TalerAmount?
    200 }
    201 
    202 @Serializable
    203 @SerialName("KYCAUTH")
    204 @Description("Incoming KYC authentication transaction")
    205 data class IncomingKycAuthTransaction(
    206     @Description("Database row identifier")
    207     override val row_id: Long,
    208     @Description("Timestamp of the transaction")
    209     override val date: TalerTimestamp,
    210     @Description("Transaction amount")
    211     override val amount: TalerAmount,
    212     @Description("Optional credit fee")
    213     override val credit_fee: TalerAmount? = null,
    214     @Description("Payto URI of the debit account")
    215     override val debit_account: String,
    216     @Description("Account public key for KYC")
    217     val account_pub: EddsaPublicKey,
    218     @Description("Optional authorization public key")
    219     val authorization_pub: EddsaPublicKey? = null,
    220     @Description("Optional authorization signature")
    221     val authorization_sig: EddsaSignature? = null,
    222 ) : IncomingBankTransaction
    223 
    224 @Serializable
    225 @SerialName("RESERVE")
    226 @Description("Incoming reserve transaction")
    227 data class IncomingReserveTransaction(
    228     @Description("Database row identifier")
    229     override val row_id: Long,
    230     @Description("Timestamp of the transaction")
    231     override val date: TalerTimestamp,
    232     @Description("Transaction amount")
    233     override val amount: TalerAmount,
    234     @Description("Optional credit fee")
    235     override val credit_fee: TalerAmount? = null,
    236     @Description("Payto URI of the debit account")
    237     override val debit_account: String,
    238     @Description("Reserve public key")
    239     val reserve_pub: EddsaPublicKey,
    240     @Description("Optional authorization public key")
    241     val authorization_pub: EddsaPublicKey? = null,
    242     @Description("Optional authorization signature")
    243     val authorization_sig: EddsaSignature? = null,
    244 ) : IncomingBankTransaction
    245 
    246 @Serializable
    247 @SerialName("WAD")
    248 @Description("Incoming WAD transaction")
    249 data class IncomingWadTransaction(
    250     @Description("Database row identifier")
    251     override val row_id: Long,
    252     @Description("Timestamp of the transaction")
    253     override val date: TalerTimestamp,
    254     @Description("Transaction amount")
    255     override val amount: TalerAmount,
    256     @Description("Optional credit fee")
    257     override val credit_fee: TalerAmount? = null,
    258     @Description("Payto URI of the debit account")
    259     override val debit_account: String,
    260     @Description("URL of the originating exchange")
    261     val origin_exchange_url: String,
    262     @Description("WAD identifier")
    263     val wad_id: String // TODO 24 bytes Base32
    264 ) : IncomingBankTransaction
    265 
    266 /** Response GET /taler-wire-gateway/history/outgoing */
    267 @Serializable
    268 @Description("History of outgoing transactions")
    269 data class OutgoingHistory(
    270     @Description("List of outgoing transactions")
    271     val outgoing_transactions: List<OutgoingTransaction>,
    272     @Description("Payto URI of the debit account")
    273     val debit_account: String
    274 )
    275 
    276 /** Inner response GET /taler-wire-gateway/history/outgoing */
    277 @Serializable
    278 @Description("Single outgoing transaction details")
    279 data class OutgoingTransaction(
    280     @Description("Database row identifier")
    281     val row_id: Long, // DB row ID of the payment.
    282     @Description("Timestamp of the transaction")
    283     val date: TalerTimestamp,
    284     @Description("Transaction amount")
    285     val amount: TalerAmount,
    286     @Description("Payto URI of the credit account")
    287     val credit_account: String,
    288     @Description("Wire transfer identifier")
    289     val wtid: ShortHashCode,
    290     @Description("Base URL of the exchange")
    291     val exchange_base_url: String,
    292     @Description("Optional transfer metadata")
    293     val metadata: String? = null,
    294     @Description("Optional debit fee")
    295     val debit_fee: TalerAmount? = null
    296 )
    297 
    298 /** Response GET /taler-wire-gateway/account/check */
    299 @Serializable
    300 @Description("Account information response")
    301 class AccountInfo()
    302 
    303 /** Response GET /taler-prepared-transfer/config */
    304 @Serializable
    305 @Description("Prepared transfer configuration")
    306 data class PreparedTransferConfig(
    307     @Description("Currency supported")
    308     val currency: String,
    309     @Description("List of supported subject formats")
    310     val supported_formats: List<SubjectFormat>
    311 ) {
    312     @Description("API name identifier")
    313     val name: String = "taler-prepared-transfer"
    314     @Description("API version string")
    315     val version: String = WIRE_TRANSFER_API_VERSION
    316 }
    317 
    318 
    319 /** Inner response GET /taler-prepared-transfer/registration */
    320 @Serializable
    321 @Description("Transfer subject information")
    322 sealed interface TransferSubject {
    323     @Serializable
    324     @SerialName("SIMPLE")
    325     @Description("Simple text transfer subject")
    326     data class Simple(
    327         @Description("Plain text transfer subject")
    328         val subject: String,
    329         @Description("Credit amount for the transfer")
    330         val credit_amount: TalerAmount
    331     ) : TransferSubject
    332 
    333     @Serializable
    334     @SerialName("URI")
    335     @Description("URI-based transfer subject")
    336     data class Uri(
    337         @Description("Taler URI for the transfer")
    338         val uri: String,
    339         @Description("Credit amount for the transfer")
    340         val credit_amount: TalerAmount
    341     ) : TransferSubject
    342 
    343     @Serializable
    344     @SerialName("CH_QR_BILL")
    345     @Description("Swiss QR bill transfer subject")
    346     data class QrBill(
    347         @Description("QR reference number for the bill")
    348         val qr_reference_number: String,
    349         @Description("Credit amount for the transfer")
    350         val credit_amount: TalerAmount,
    351     ) : TransferSubject
    352 }
    353 
    354 @Serializable
    355 @Description("Supported transfer subject format")
    356 enum class SubjectFormat {
    357     SIMPLE,
    358     URI,
    359     CH_QR_BILL
    360 }
    361 
    362 @Serializable
    363 @Description("Public key algorithm")
    364 enum class PublicKeyAlg {
    365     EdDSA
    366 }
    367 
    368 @Serializable
    369 @Description("Type of wire transfer")
    370 enum class TransferType {
    371     reserve,
    372     kyc
    373 }
    374 
    375 @Serializable
    376 @Description("Request to generate a transfer subject")
    377 data class SubjectRequest(
    378     @Description("Credit amount for the transfer")
    379     val credit_amount: TalerAmount,
    380     @Description("Type of transfer")
    381     val type: TransferType,
    382     @Description("Public key algorithm")
    383     val alg: PublicKeyAlg,
    384     @Description("Account public key")
    385     val account_pub: EddsaPublicKey,
    386     @Description("Authorization public key")
    387     val authorization_pub: EddsaPublicKey,
    388     @Description("Authorization signature")
    389     val authorization_sig: EddsaSignature,
    390     @Description("Whether subject is recurrent")
    391     val recurrent: Boolean
    392 )
    393 
    394 @Serializable
    395 @Description("Result of subject generation")
    396 data class SubjectResult(
    397     @Description("List of generated transfer subjects")
    398     val subjects: List<TransferSubject>,
    399     @Description("Expiration timestamp of the subjects")
    400     val expiration: TalerTimestamp
    401 )
    402 
    403 @Serializable
    404 @Description("Request to unregister a subject")
    405 data class Unregistration(
    406     @Description("Timestamp of the unregistration")
    407     val timestamp: String,
    408     @Description("Authorization public key")
    409     val authorization_pub: EddsaPublicKey,
    410     @Description("Authorization signature")
    411     val authorization_sig: EddsaSignature
    412 )
    413 
    414 /** Response GET /taler-revenue/config */
    415 @Serializable
    416 @Description("Revenue API configuration response")
    417 data class RevenueConfig(
    418     @Description("Currency supported by the API")
    419     val currency: String
    420 ) {
    421     @Description("API name identifier")
    422     val name: String = "taler-revenue"
    423     @Description("API version string")
    424     val version: String = REVENUE_API_VERSION
    425 }
    426 
    427 /** Request GET /taler-revenue/history */
    428 @Serializable
    429 @Description("History of revenue incoming transactions")
    430 data class RevenueIncomingHistory(
    431     @Description("List of incoming revenue transactions")
    432     val incoming_transactions: List<RevenueIncomingBankTransaction>,
    433     @Description("Payto URI of the credit account")
    434     val credit_account: String
    435 )
    436 
    437 /** Inner request GET /taler-revenue/history */
    438 @Serializable
    439 @Description("Single revenue incoming bank transaction")
    440 data class RevenueIncomingBankTransaction(
    441     @Description("Database row identifier")
    442     val row_id: Long,
    443     @Description("Timestamp of the transaction")
    444     val date: TalerTimestamp,
    445     @Description("Transaction amount")
    446     val amount: TalerAmount,
    447     @Description("Optional credit fee")
    448     val credit_fee: TalerAmount? = null,
    449     @Description("Payto URI of the debit account")
    450     val debit_account: String,
    451     @Description("Transaction subject line")
    452     val subject: String
    453 )
    454 
    455 /** Response GET /taler-observability/config */
    456 @Serializable
    457 @Description("Observability API configuration response")
    458 class TalerObservabilityConfig() {
    459     @Description("API name identifier")
    460     val name: String = "taler-observability"
    461     @Description("API version string")
    462     val version: String = OBSERVABILITY_API_VERSION
    463 }