db.go (8986B)
1 // This file is part of taler-cashless2ecash. 2 // Copyright (C) 2024 Joel Häberli 3 // 4 // taler-cashless2ecash is free software: you can redistribute it and/or modify it 5 // under the terms of the GNU Affero General Public License as published 6 // by the Free Software Foundation, either version 3 of the License, 7 // or (at your option) any later version. 8 // 9 // taler-cashless2ecash is distributed in the hope that it will be useful, but 10 // WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 // Affero General Public License for more details. 13 // 14 // You should have received a copy of the GNU Affero General Public License 15 // along with this program. If not, see <http://www.gnu.org/licenses/>. 16 // 17 // SPDX-License-Identifier: AGPL3.0-or-later 18 19 package db 20 21 import ( 22 internal_utils "c2ec/internal/utils" 23 "context" 24 "time" 25 ) 26 27 var DB C2ECDatabase 28 29 type Provider struct { 30 ProviderId int64 `db:"provider_id"` 31 Name string `db:"name"` 32 PaytoTargetType string `db:"payto_target_type"` 33 BackendBaseURL string `db:"backend_base_url"` 34 BackendCredentials string `db:"backend_credentials"` 35 } 36 37 type Terminal struct { 38 TerminalId int64 `db:"terminal_id"` 39 AccessToken string `db:"access_token"` 40 Active bool `db:"active"` 41 Description string `db:"description"` 42 ProviderId int64 `db:"provider_id"` 43 } 44 45 type Withdrawal struct { 46 WithdrawalRowId uint64 `db:"withdrawal_row_id"` 47 ConfirmedRowId *uint64 `db:"confirmed_row_id"` 48 RequestUid string `db:"request_uid"` 49 Wopid []byte `db:"wopid"` 50 ReservePubKey []byte `db:"reserve_pub_key"` 51 RegistrationTs int64 `db:"registration_ts"` 52 Amount *internal_utils.TalerAmountCurrency `db:"amount" scan:"follow"` 53 SuggestedAmount *internal_utils.TalerAmountCurrency `db:"suggested_amount" scan:"follow"` 54 TerminalFees *internal_utils.TalerAmountCurrency `db:"terminal_fees" scan:"follow"` 55 WithdrawalStatus internal_utils.WithdrawalOperationStatus `db:"withdrawal_status"` 56 TerminalId int `db:"terminal_id"` 57 ProviderTransactionId *string `db:"provider_transaction_id"` 58 LastRetryTs *int64 `db:"last_retry_ts"` 59 RetryCounter int32 `db:"retry_counter"` 60 CompletionProof []byte `db:"completion_proof"` 61 } 62 63 type Transfer struct { 64 RowId int `db:"row_id"` 65 TransferredRowId *int `db:"transferred_row_id"` 66 RequestUid []byte `db:"request_uid"` 67 Amount *internal_utils.TalerAmountCurrency `db:"amount"` 68 ExchangeBaseUrl string `db:"exchange_base_url"` 69 Wtid string `db:"wtid"` 70 CreditAccount string `db:"credit_account"` 71 TransferTs int64 `db:"transfer_ts"` 72 Status int16 `db:"transfer_status"` 73 Retries int16 `db:"retries"` 74 } 75 76 type Notification struct { 77 Channel string 78 Payload string 79 } 80 81 // C2ECDatabase defines the operations which a 82 // C2EC compliant database interface must implement 83 // in order to be bound to the c2ec API. 84 type C2ECDatabase interface { 85 // A terminal sets up a withdrawal 86 // with this query. 87 // This initiates the withdrawal. 88 SetupWithdrawal( 89 wopid []byte, 90 suggestedAmount internal_utils.Amount, 91 amount internal_utils.Amount, 92 terminalId int, 93 providerTransactionId string, 94 terminalFees internal_utils.Amount, 95 requestUid string, 96 ) error 97 98 // Registers a reserve public key 99 // belonging to the respective wopid. 100 RegisterWithdrawalParameters( 101 wopid []byte, 102 resPubKey internal_utils.EddsaPublicKey, 103 ) error 104 105 // Get the withdrawal associated with the given request uid. 106 GetWithdrawalByRequestUid(requestUid string) (*Withdrawal, error) 107 108 // Get the withdrawal associated with the given withdrawal identifier. 109 GetWithdrawalById(withdrawalId int) (*Withdrawal, error) 110 111 // Get the withdrawal associated with the given wopid. 112 GetWithdrawalByWopid(wopid []byte) (*Withdrawal, error) 113 114 // Get the withdrawal associated with the provider specific transaction id. 115 GetWithdrawalByProviderTransactionId(tid string) (*Withdrawal, error) 116 117 // When the terminal receives the notification of the 118 // Provider, that the payment went through, this will 119 // save the provider specific transaction id in the database 120 NotifyPayment( 121 wopid []byte, 122 providerTransactionId string, 123 terminalId int, 124 fees internal_utils.Amount, 125 ) error 126 127 // Returns all withdrawals which can be attested by 128 // a provider backend. This means that the provider 129 // specific transaction id was set and the status is 130 // 'selected'. The attestor can then attest and finalise 131 // the payments. 132 GetWithdrawalsForConfirmation() ([]*Withdrawal, error) 133 134 // When an confirmation (or fail message) could be 135 // retrieved by the provider, the withdrawal can 136 // be finalised storing the correct final state 137 // and the proof of completion of the provider. 138 FinaliseWithdrawal( 139 withdrawalId int, 140 confirmOrAbort internal_utils.WithdrawalOperationStatus, 141 completionProof []byte, 142 ) error 143 144 // Set retry will set the last_retry_ts field 145 // on the database. A trigger will then start 146 // the retry process. The timestamp must be a 147 // unix timestamp 148 SetLastRetry(withdrawalId int, lastRetryTsUnix int64) error 149 150 // Sets the retry counter for the given withdrawal. 151 SetRetryCounter(withdrawalId int, retryCounter int) error 152 153 // The wire gateway allows the exchange to retrieve transactions 154 // starting at a certain starting point up until a certain delta 155 // if the delta is negative, previous transactions relative to the 156 // starting point are considered. When start is negative, the latest 157 // id shall be used as starting point. 158 GetConfirmedWithdrawals(start int, delta int, since time.Time) ([]*Withdrawal, error) 159 160 // Get the provider of a terminal by the terminals id 161 GetProviderByTerminal(terminalId int) (*Provider, error) 162 163 // Get a provider entry by its name 164 GetTerminalProviderByName(name string) (*Provider, error) 165 166 // Get a provider entry by its name 167 GetTerminalProviderByPaytoTargetType(paytoTargetType string) (*Provider, error) 168 169 // Get a terminal entry by its identifier 170 GetTerminalById(id int) (*Terminal, error) 171 172 // Returns the transfer for the given hashcode. 173 GetTransferById(requestUid []byte) (*Transfer, error) 174 175 // Inserts a new transfer into the database. 176 AddTransfer( 177 requestUid []byte, 178 amount *internal_utils.Amount, 179 exchangeBaseUrl string, 180 wtid string, 181 credit_account string, 182 ts time.Time, 183 ) error 184 185 // Updates the transfer, if retries is changed, the transfer will be 186 // triggered again. 187 UpdateTransfer( 188 rowId int, 189 requestUid []byte, 190 timestamp int64, 191 status int16, 192 retries int16, 193 ) error 194 195 // The wire gateway allows the exchange to retrieve transactions 196 // starting at a certain starting point up until a certain delta 197 // if the delta is negative, previous transactions relative to the 198 // starting point are considered. When start is negative, the latest 199 // id shall be used as starting point. 200 GetTransfers(start int, delta int, since time.Time) ([]*Transfer, error) 201 202 // Load all transfers asscociated with the same credit_account. 203 // The query is used to control that the current limitation of 204 // only allowing full refunds (partial refunds are currently not supported) 205 // is not harmed. It is assumed that the credit_account is unique, which currently 206 // is the case, because it depends on the WOPID of the respective 207 // withdrawal. This query is part of the limitation to only allow 208 // full refunds and not partial refunds. It might be possible to 209 // remove this API when partial refunds are implemented. 210 GetTransfersByCreditAccount(creditAccount string) ([]*Transfer, error) 211 212 // Returns the transfer entries in the given state. 213 // This can be used for retry operations. 214 GetTransfersByState(status int) ([]*Transfer, error) 215 216 // A listener can listen for notifications ont the specified 217 // channel. Returns a listen function, which must be called 218 // by the caller to start listening on the channel. The returned 219 // listen function will return an error if it fails, and takes 220 // a context as argument which allows the underneath implementation 221 // to control the execution context of the listener. 222 NewListener( 223 channel string, 224 out chan *Notification, 225 ) (func(context.Context) error, error) 226 }