libeufin

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

TalerMessage.kt (8443B)


      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 kotlinx.serialization.SerialName
     23 import kotlinx.serialization.Serializable
     24 
     25 enum class IncomingType {
     26     reserve,
     27     kyc,
     28     map
     29 }
     30 
     31 enum class TransferStatusState {
     32     pending,
     33     transient_failure,
     34     permanent_failure,
     35     success
     36 }
     37 
     38 /** Response GET /taler-wire-gateway/config */
     39 @Serializable
     40 data class WireGatewayConfig(
     41     val currency: String,
     42     val support_account_check: Boolean
     43 ) {
     44     val name: String = "taler-wire-gateway"
     45     val version: String = WIRE_GATEWAY_API_VERSION
     46 }
     47 
     48 /** Request POST /taler-wire-gateway/transfer */
     49 @Serializable
     50 data class TransferRequest(
     51     val request_uid: HashCode,
     52     val amount: TalerAmount,
     53     val exchange_base_url: BaseURL,
     54     val wtid: ShortHashCode,
     55     val credit_account: Payto,
     56     val metadata: String? = null,
     57 ) {
     58     init {
     59         if (metadata != null && !METADATA_REGEX.matches(metadata))
     60             throw badRequest("metadata '$metadata' is malformed, must match [a-zA-Z0-9-.+:]{1,40}")
     61     }
     62     
     63     companion object {
     64         private val METADATA_REGEX = Regex("^[a-zA-Z0-9-.:]{1,40}$")
     65     }
     66 }
     67 
     68 /** Response POST /taler-wire-gateway/transfer */
     69 @Serializable
     70 data class TransferResponse(
     71     val timestamp: TalerTimestamp,
     72     val row_id: Long
     73 )
     74 
     75 /** Request GET /taler-wire-gateway/transfers */
     76 @Serializable
     77 data class TransferList(
     78     val transfers: List<TransferListStatus>,
     79     val debit_account: String
     80 )
     81 
     82 @Serializable
     83 data class TransferListStatus(
     84     val row_id: Long,
     85     val status: TransferStatusState,
     86     val amount: TalerAmount,
     87     val credit_account: String,
     88     val timestamp: TalerTimestamp
     89 )
     90 
     91 /** Request GET /taler-wire-gateway/transfers/{ROW_iD} */
     92 @Serializable
     93 data class TransferStatus(
     94     val status: TransferStatusState,
     95     val status_msg: String? = null,
     96     val amount: TalerAmount,
     97     val origin_exchange_url: String,
     98     val metadata: String? = null,
     99     val wtid: ShortHashCode,
    100     val credit_account: String,
    101     val timestamp: TalerTimestamp
    102 )
    103 
    104 /** Request POST /taler-wire-gateway/admin/add-incoming */
    105 @Serializable
    106 data class AddIncomingRequest(
    107     val amount: TalerAmount,
    108     val reserve_pub: EddsaPublicKey,
    109     val debit_account: Payto
    110 )
    111 
    112 /** Response POST /taler-wire-gateway/admin/add-incoming */
    113 @Serializable
    114 data class AddIncomingResponse(
    115     val timestamp: TalerTimestamp,
    116     val row_id: Long
    117 )
    118 
    119 /** Request POST /taler-wire-gateway/admin/add-kycauth */
    120 @Serializable
    121 data class AddKycauthRequest(
    122     val amount: TalerAmount,
    123     val account_pub: EddsaPublicKey,
    124     val debit_account: Payto
    125 )
    126 
    127 /** Request POST /taler-wire-gateway/admin/add-mapped */
    128 @Serializable
    129 data class AddMappedRequest(
    130     val amount: TalerAmount,
    131     val authorization_pub: EddsaPublicKey,
    132     val debit_account: Payto
    133 )
    134 
    135 /** Response GET /taler-wire-gateway/history/incoming */
    136 @Serializable
    137 data class IncomingHistory(
    138     val incoming_transactions: List<IncomingBankTransaction>,
    139     val credit_account: String
    140 )
    141 
    142 /** Inner response GET /taler-wire-gateway/history/incoming */
    143 @Serializable
    144 sealed interface IncomingBankTransaction {
    145     val row_id: Long
    146     val date: TalerTimestamp
    147     val amount: TalerAmount
    148     val debit_account: String
    149     val credit_fee: TalerAmount?
    150 }
    151 
    152 @Serializable
    153 @SerialName("KYCAUTH")
    154 data class IncomingKycAuthTransaction(
    155     override val row_id: Long,
    156     override val date: TalerTimestamp,
    157     override val amount: TalerAmount,
    158     override val credit_fee: TalerAmount? = null,
    159     override val debit_account: String,
    160     val account_pub: EddsaPublicKey,
    161     val authorization_pub: EddsaPublicKey? = null,
    162     val authorization_sig: EddsaSignature? = null,
    163 ) : IncomingBankTransaction
    164 
    165 @Serializable
    166 @SerialName("RESERVE")
    167 data class IncomingReserveTransaction(
    168     override val row_id: Long,
    169     override val date: TalerTimestamp,
    170     override val amount: TalerAmount,
    171     override val credit_fee: TalerAmount? = null,
    172     override val debit_account: String,
    173     val reserve_pub: EddsaPublicKey,
    174     val authorization_pub: EddsaPublicKey? = null,
    175     val authorization_sig: EddsaSignature? = null,
    176 ) : IncomingBankTransaction
    177 
    178 @Serializable
    179 @SerialName("WAD")
    180 data class IncomingWadTransaction(
    181     override val row_id: Long,
    182     override val date: TalerTimestamp,
    183     override val amount: TalerAmount,
    184     override val credit_fee: TalerAmount? = null,
    185     override val debit_account: String,
    186     val origin_exchange_url: String,
    187     val wad_id: String // TODO 24 bytes Base32
    188 ) : IncomingBankTransaction
    189 
    190 /** Response GET /taler-wire-gateway/history/outgoing */
    191 @Serializable
    192 data class OutgoingHistory(
    193     val outgoing_transactions: List<OutgoingTransaction>,
    194     val debit_account: String
    195 )
    196 
    197 /** Inner response GET /taler-wire-gateway/history/outgoing */
    198 @Serializable
    199 data class OutgoingTransaction(
    200     val row_id: Long, // DB row ID of the payment.
    201     val date: TalerTimestamp,
    202     val amount: TalerAmount,
    203     val credit_account: String,
    204     val wtid: ShortHashCode,
    205     val exchange_base_url: String,
    206     val metadata: String? = null,
    207     val debit_fee: TalerAmount? = null
    208 )
    209 
    210 /** Response GET /taler-wire-gateway/account/check */
    211 @Serializable
    212 class AccountInfo()
    213 
    214 /** Response GET /taler-prepared-transfer/config */
    215 @Serializable
    216 data class PreparedTransferConfig(
    217     val currency: String,
    218     val supported_formats: List<SubjectFormat>
    219 ) {
    220     val name: String = "taler-prepared-transfer"
    221     val version: String = WIRE_TRANSFER_API_VERSION
    222 }
    223 
    224 
    225 /** Inner response GET /taler-prepared-transfer/registration */
    226 @Serializable
    227 sealed interface TransferSubject {
    228     @Serializable
    229     @SerialName("SIMPLE")
    230     data class Simple(
    231         val subject: String,
    232         val credit_amount: TalerAmount
    233     ) : TransferSubject
    234 
    235     @Serializable
    236     @SerialName("URI")
    237     data class Uri(
    238         val uri: String,
    239         val credit_amount: TalerAmount
    240     ) : TransferSubject
    241 
    242     @Serializable
    243     @SerialName("CH_QR_BILL")
    244     data class QrBill(
    245         val qr_reference_number: String,
    246         val credit_amount: TalerAmount,
    247     ) : TransferSubject
    248 }
    249 
    250 @Serializable
    251 enum class SubjectFormat {
    252     SIMPLE,
    253     URI,
    254     CH_QR_BILL
    255 }
    256 
    257 @Serializable
    258 enum class PublicKeyAlg {
    259     EdDSA
    260 }
    261 
    262 @Serializable
    263 enum class TransferType {
    264     reserve,
    265     kyc
    266 }
    267 
    268 @Serializable
    269 data class SubjectRequest(
    270     val credit_amount: TalerAmount,
    271     val type: TransferType,
    272     val alg: PublicKeyAlg,
    273     val account_pub: EddsaPublicKey,
    274     val authorization_pub: EddsaPublicKey,
    275     val authorization_sig: EddsaSignature,
    276     val recurrent: Boolean
    277 )
    278 
    279 @Serializable
    280 data class SubjectResult(
    281     val subjects: List<TransferSubject>,
    282     val expiration: TalerTimestamp
    283 )
    284 
    285 @Serializable
    286 data class Unregistration(
    287     val timestamp: String,
    288     val authorization_pub: EddsaPublicKey,
    289     val authorization_sig: EddsaSignature
    290 )
    291 
    292 /** Response GET /taler-revenue/config */
    293 @Serializable
    294 data class RevenueConfig(
    295     val currency: String
    296 ) {
    297     val name: String = "taler-revenue"
    298     val version: String = REVENUE_API_VERSION
    299 }
    300 
    301 /** Request GET /taler-revenue/history */
    302 @Serializable
    303 data class RevenueIncomingHistory(
    304     val incoming_transactions: List<RevenueIncomingBankTransaction>,
    305     val credit_account: String
    306 )
    307 
    308 /** Inner request GET /taler-revenue/history */
    309 @Serializable
    310 data class RevenueIncomingBankTransaction(
    311     val row_id: Long,
    312     val date: TalerTimestamp,
    313     val amount: TalerAmount,
    314     val credit_fee: TalerAmount? = null,
    315     val debit_account: String,
    316     val subject: String
    317 )
    318 
    319 /** Response GET /taler-observability/config */
    320 @Serializable
    321 class TalerObservabilityConfig() {
    322     val name: String = "taler-observability"
    323     val version: String = OBSERVABILITY_API_VERSION
    324 }