summaryrefslogtreecommitdiff
path: root/c2ec/db.go
blob: 66074153fcc51c46bf2cfe56cbc03062d7871d46 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package main

import (
	"context"
)

const PROVIDER_TABLE_NAME = "c2ec.provider"
const PROVIDER_FIELD_NAME_ID = "provider_id"
const PROVIDER_FIELD_NAME_NAME = "name"
const PROVIDER_FIELD_NAME_PAYTO_TARGET_TYPE = "payto_target_type"
const PROVIDER_FIELD_NAME_BACKEND_URL = "backend_base_url"
const PROVIDER_FIELD_NAME_BACKEND_CREDENTIALS = "backend_credentials"

const TERMINAL_TABLE_NAME = "c2ec.terminal"
const TERMINAL_FIELD_NAME_ID = "terminal_id"
const TERMINAL_FIELD_NAME_ACCESS_TOKEN = "access_token"
const TERMINAL_FIELD_NAME_ACTIVE = "active"
const TERMINAL_FIELD_NAME_DESCRIPTION = "description"
const TERMINAL_FIELD_NAME_PROVIDER_ID = "provider_id"

const WITHDRAWAL_TABLE_NAME = "c2ec.withdrawal"
const WITHDRAWAL_FIELD_NAME_ID = "withdrawal_id"
const WITHDRAWAL_FIELD_NAME_WOPID = "wopid"
const WITHDRAWAL_FIELD_NAME_RESPUBKEY = "reserve_pub_key"
const WITHDRAWAL_FIELD_NAME_TS = "registration_ts"
const WITHDRAWAL_FIELD_NAME_AMOUNT = "amount"
const WITHDRAWAL_FIELD_NAME_FEES = "fees"
const WITHDRAWAL_FIELD_NAME_STATUS = "withdrawal_status"
const WITHDRAWAL_FIELD_NAME_TERMINAL_ID = "terminal_id"
const WITHDRAWAL_FIELD_NAME_TRANSACTION_ID = "provider_transaction_id"
const WITHDRAWAL_FIELD_NAME_LAST_RETRY = "last_retry_ts"
const WITHDRAWAL_FIELD_NAME_RETRY_COUNTER = "retry_counter"
const WITHDRAWAL_FIELD_NAME_COMPLETION_PROOF = "completion_proof"

const TRANSFER_TABLE_NAME = "c2ec.transfer"
const TRANSFER_FIELD_NAME_ID = "request_uid"
const TRANSFER_FIELD_NAME_ROW_ID = "row_id"
const TRANSFER_FIELD_NAME_AMOUNT = "amount"
const TRANSFER_FIELD_NAME_EXCHANGE_BASE_URL = "exchange_base_url"
const TRANSFER_FIELD_NAME_WTID = "wtid"
const TRANSFER_FIELD_NAME_CREDIT_ACCOUNT = "credit_account"

type Provider struct {
	ProviderId         int64  `db:"provider_id"`
	Name               string `db:"name"`
	PaytoTargetType    string `db:"payto_target_type"`
	BackendBaseURL     string `db:"backend_base_url"`
	BackendCredentials string `db:"backend_credentials"`
}

type Terminal struct {
	TerminalId  int64  `db:"terminal_id"`
	AccessToken string `db:"access_token"`
	Active      bool   `db:"active"`
	Description string `db:"description"`
	ProviderId  int64  `db:"provider_id"`
}

type Withdrawal struct {
	WithdrawalId          uint64                    `db:"withdrawal_id"`
	Wopid                 []byte                    `db:"wopid"`
	ReservePubKey         []byte                    `db:"reserve_pub_key"`
	RegistrationTs        int64                     `db:"registration_ts"`
	Amount                *TalerAmountCurrency      `db:"amount" scan:"follow"`
	Fees                  *TalerAmountCurrency      `db:"fees" scan:"follow"`
	WithdrawalStatus      WithdrawalOperationStatus `db:"withdrawal_status"`
	TerminalId            *int64                    `db:"terminal_id"`
	ProviderTransactionId *string                   `db:"provider_transaction_id"`
	LastRetryTs           *int64                    `db:"last_retry_ts"`
	RetryCounter          int32                     `db:"retry_counter"`
	CompletionProof       []byte                    `db:"completion_proof"`
}

type TalerAmountCurrency struct {
	Val  int64  `db:"val"`
	Frac int32  `db:"frac"`
	Curr string `db:"curr"`
}

type Transfer struct {
	RowId           int                  `db:"row_id"`
	RequestUid      HashCode             `db:"request_uid"`
	Amount          *TalerAmountCurrency `db:"amount"`
	ExchangeBaseUrl string               `db:"exchange_base_url"`
	Wtid            string               `db:"wtid"`
	CreditAccount   string               `db:"credit_account"`
	TransactionTs   int64                `db:"transaction_ts"`
}

type Notification struct {
	Channel string
	Payload string
}

// C2ECDatabase defines the operations which a
// C2EC compliant database interface must implement
// in order to be bound to the c2ec API.
type C2ECDatabase interface {
	// Registers a wopid and reserve public key.
	// This initiates the withdrawal.
	RegisterWithdrawal(
		wopid []byte,
		resPubKey EddsaPublicKey,
	) error

	// Get the withdrawal associated with the given withdrawal identifier.
	GetWithdrawalById(withdrawalId int) (*Withdrawal, error)

	// Get the withdrawal associated with the given wopid.
	GetWithdrawalByWopid(wopid []byte) (*Withdrawal, error)

	// Get the withdrawal associated with the provider specific transaction id.
	GetWithdrawalByProviderTransactionId(tid string) (*Withdrawal, error)

	// When the terminal receives the notification of the
	// Provider, that the payment went through, this will
	// save the provider specific transaction id in the database
	NotifyPayment(
		wopid []byte,
		providerTransactionId string,
		terminalId int,
		amount Amount,
		fees Amount,
	) error

	// Returns all withdrawals which can be attested by
	// a provider backend. This means that the provider
	// specific transaction id was set and the status is
	// 'selected'. The attestor can then attest and finalise
	// the payments.
	GetAttestableWithdrawals() ([]*Withdrawal, error)

	// When an attestation (or fail message) could be
	// retrieved by the provider, the withdrawal can
	// be finalised storing the correct final state
	// and the proof of completion of the provider.
	FinaliseWithdrawal(
		withdrawalId int,
		confirmOrAbort WithdrawalOperationStatus,
		completionProof []byte,
	) error

	// Set retry will set the last_retry_ts field
	// on the database. A trigger will then start
	// the retry process. The timestamp must be a
	// unix timestamp
	SetLastRetry(withdrawalId int, lastRetryTsUnix int64) error

	// Sets the retry counter for the given withdrawal.
	SetRetryCounter(withdrawalId int, retryCounter int) error

	// The wire gateway allows the exchange to retrieve transactions
	// starting at a certain starting point up until a certain delta
	// if the delta is negative, previous transactions relative to the
	// starting point are considered. When start is negative, the latest
	// id shall be used as starting point.
	GetConfirmedWithdrawals(start int, delta int) ([]*Withdrawal, error)

	// Get the provider of a terminal by the terminals id
	GetProviderByTerminal(terminalId int) (*Provider, error)

	// Get a provider entry by its name
	GetTerminalProviderByName(name string) (*Provider, error)

	// Get a provider entry by its name
	GetTerminalProviderByPaytoTargetType(paytoTargetType string) (*Provider, error)

	// Get a terminal entry by its identifier
	GetTerminalById(id int) (*Terminal, error)

	// Returns the transfer for the given hashcode.
	GetTransferById(requestUid HashCode) (*Transfer, error)

	// Inserts a new transfer into the database.
	AddTransfer(
		requestUid HashCode,
		amount *Amount,
		exchangeBaseUrl string,
		wtid string,
		credit_account string,
	) error

	// The wire gateway allows the exchange to retrieve transactions
	// starting at a certain starting point up until a certain delta
	// if the delta is negative, previous transactions relative to the
	// starting point are considered. When start is negative, the latest
	// id shall be used as starting point.
	GetTransfers(start int, delta int) ([]*Transfer, error)

	// This will listen for notifications on the
	// channel withdrawal notifications are sent.
	// Results will be written to the out channel.
	// Errors will be propagated through the errs
	// channel. Supply a context with timeout if
	// you want to use time limitations.
	ListenForWithdrawalStatusChange(
		ctx context.Context,
		wopid WithdrawalIdentifier,
		out chan WithdrawalOperationStatus,
		errs chan error,
	)

	// A listener can listen for the specified channel.
	// It will send received notifications through the channel
	// supplied. The specific implementation must convert the
	// database specific message to the generic Notification
	// type in order to decouple the database implementation
	// from the rest of the logic.
	Listen(ctx context.Context, channel string) (chan *Notification, chan error, error)
}