cashless2ecash

cashless2ecash: pay with cards for digital cash (experimental)
Log | Files | Refs | README

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 }