-
Notifications
You must be signed in to change notification settings - Fork 129
/
relDB.go
231 lines (200 loc) · 9.82 KB
/
relDB.go
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
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
package models
import (
"context"
"fmt"
"time"
"github.com/jackc/pgx/v4/pgxpool"
"github.com/diadata-org/diadata/pkg/dia"
"github.com/diadata-org/diadata/pkg/dia/helpers/db"
"github.com/go-redis/redis"
)
// RelDatastore is a (persistent) relational database with an additional redis caching layer
type RelDatastore interface {
// --- Assets methods ---
// --------- Persistent ---------
SetAsset(asset dia.Asset) error
GetAsset(address, blockchain string) (dia.Asset, error)
GetAssetByID(ID string) (dia.Asset, error)
GetAssetsBySymbolName(symbol, name string) ([]dia.Asset, error)
GetAllAssets(blockchain string) ([]dia.Asset, error)
GetFiatAssetBySymbol(symbol string) (asset dia.Asset, err error)
IdentifyAsset(asset dia.Asset) ([]dia.Asset, error)
GetAssetID(asset dia.Asset) (string, error)
GetPage(pageNumber uint32) ([]dia.Asset, bool, error)
Count() (uint32, error)
SetAssetVolume24H(asset dia.Asset, volume float64, timestamp time.Time) error
GetAssetVolume24H(asset dia.Asset) (float64, error)
GetAssetsWithVOL(numAssets int64, skip int64, onlycex bool, substring string) ([]dia.AssetVolume, error)
GetAssetSource(asset dia.Asset, onlycex bool) ([]string, error)
GetAssetsWithVOLRange(starttime time.Time, endtime time.Time) ([]dia.AssetVolume, error)
SetAggregatedVolume(aggVol dia.AggregatedVolume) error
GetAggregatedVolumes(asset dia.Asset, starttime time.Time, endtime time.Time) ([]dia.AggregatedVolume, error)
GetAggVolumesByExchange(asset dia.Asset, starttime time.Time, endtime time.Time) ([]dia.ExchangeVolumesList, error)
GetAggVolumesByPair(asset dia.Asset, starttime time.Time, endtime time.Time) ([]dia.PairVolumesList, error)
SetTradesDistribution(tradesDist dia.TradesDistribution) error
GetTradesDistribution(asset dia.Asset, starttime time.Time, endtime time.Time) ([]dia.TradesDistribution, error)
// --------------- asset methods for exchanges ---------------
SetExchangePair(exchange string, pair dia.ExchangePair, cache bool) error
GetExchangePair(exchange string, foreignname string) (exchangepair dia.ExchangePair, err error)
GetExchangePairSymbols(exchange string) ([]dia.ExchangePair, error)
GetNumPairs(exchange dia.Exchange) (int, error)
SetExchangeSymbol(exchange string, symbol string) error
GetExchangeSymbols(exchange string, substring string) ([]string, error)
GetUnverifiedExchangeSymbols(exchange string) ([]string, error)
VerifyExchangeSymbol(exchange string, symbol string, assetID string) (bool, error)
GetExchangeSymbolAssetID(exchange string, symbol string) (string, bool, error)
// ----------------- exchange methods -------------------
SetExchange(exchange dia.Exchange) error
GetExchange(name string) (dia.Exchange, error)
GetAllExchanges() ([]dia.Exchange, error)
GetExchangeNames() ([]string, error)
// ----------------- pool methods -------------------
SetPool(pool dia.Pool) error
GetPoolByAddress(blockchain string, address string) (pool dia.Pool, err error)
GetAllPoolAddrsExchange(exchange string) ([]string, error)
// ----------------- blockchain methods -------------------
SetBlockchain(blockchain dia.BlockChain) error
GetBlockchain(name string) (dia.BlockChain, error)
GetAllAssetsBlockchains() ([]string, error)
GetAllBlockchains(fullAsset bool) ([]dia.BlockChain, error)
// ------ Caching ------
SetAssetCache(asset dia.Asset) error
GetAssetCache(assetID string) (dia.Asset, error)
SetExchangePairCache(exchange string, pair dia.ExchangePair) error
GetExchangePairCache(exchange string, foreignName string) (dia.ExchangePair, error)
CountCache() (uint32, error)
// ---------------- NFT methods -------------------
// NFT class methods
SetNFTClass(nftClass dia.NFTClass) error
GetAllNFTClasses(blockchain string) ([]dia.NFTClass, error)
GetNFTClasses(limit, offset uint64) ([]dia.NFTClass, error)
GetNFTClass(address string, blockchain string) (dia.NFTClass, error)
GetNFTClassID(address string, blockchain string) (string, error)
GetNFTClassByID(id string) (dia.NFTClass, error)
GetNFTClassesByNameSymbol(searchstring string) ([]dia.NFTClass, error)
UpdateNFTClassCategory(nftclassID string, category string) (bool, error)
GetNFTCategories() ([]string, error)
// NFT methods
SetNFT(nft dia.NFT) error
GetNFT(address string, blockchain string, tokenID string) (dia.NFT, error)
GetNFTID(address string, blockchain string, tokenID string) (string, error)
// NFT trading and bidding methods
SetNFTTrade(trade dia.NFTTrade) error
SetNFTTradeToTable(trade dia.NFTTrade, table string) error
GetNFTTrades(address string, blockchain string, tokenID string, starttime time.Time, endtime time.Time) ([]dia.NFTTrade, error)
GetNFTTradesCollection(address string, blockchain string, starttime time.Time, endtime time.Time) ([]dia.NFTTrade, error)
GetNFTOffers(address string, blockchain string, tokenID string) ([]dia.NFTOffer, error)
GetNFTBids(address string, blockchain string, tokenID string) ([]dia.NFTBid, error)
GetNFTFloor(nftclass dia.NFTClass, timestamp time.Time, floorWindowSeconds time.Duration, noBundles bool) (float64, error)
GetNFTFloorLevel(nftclass dia.NFTClass, timestamp time.Time, floorWindowSeconds time.Duration, currencies []dia.Asset, level float64, noBundles bool) (float64, error)
GetNFTFloorRecursive(nftClass dia.NFTClass, timestamp time.Time, floorWindowSeconds time.Duration, stepBackLimit int, noBundles bool) (float64, error)
GetNFTFloorRange(nftClass dia.NFTClass, starttime time.Time, endtime time.Time, floorWindowSeconds time.Duration, stepBackLimit int, noBundles bool) ([]float64, error)
GetLastBlockheightTopshot(upperBound time.Time) (uint64, error)
SetNFTBid(bid dia.NFTBid) error
GetLastNFTBid(address string, blockchain string, tokenID string, blockNumber uint64, blockPosition uint) (dia.NFTBid, error)
GetLastBlockNFTBid(nftclass dia.NFTClass) (uint64, error)
GetLastBlockNFTOffer(nftclass dia.NFTClass) (uint64, error)
GetLastBlockNFTTrade(nftclass dia.NFTClass) (uint64, error)
SetNFTOffer(offer dia.NFTOffer) error
GetLastNFTOffer(address string, blockchain string, tokenID string, blockNumber uint64, blockPosition uint) (offer dia.NFTOffer, err error)
// NFT stats
GetTopNFTsEth(numCollections int, offset int64, exchanges []string, starttime time.Time, endtime time.Time) ([]struct {
Name string
Address string
Blockchain string
Volume float64
}, error)
GetNumNFTTrades(address string, blockchain string, exchange string, starttime time.Time, endtime time.Time) (int, error)
GetNFTVolume(address string, blockchain string, exchange string, starttime time.Time, endtime time.Time) (float64, error)
// General methods
GetKeys(table string) ([]string, error)
// Scraper config and state
GetScraperState(ctx context.Context, scraperName string, state ScraperState) error
SetScraperState(ctx context.Context, scraperName string, state ScraperState) error
GetScraperConfig(ctx context.Context, scraperName string, config ScraperConfig) error
SetScraperConfig(ctx context.Context, scraperName string, config ScraperConfig) error
// Blockchain data
SetBlockData(dia.BlockData) error
GetBlockData(blockchain string, blocknumber int64) (dia.BlockData, error)
GetLastBlockBlockscraper(blockchain string) (int64, error)
}
const (
// postgres tables
assetTable = "asset"
assetIdent = "assetIdent"
exchangepairTable = "exchangepair"
exchangesymbolTable = "exchangesymbol"
poolTable = "pool"
poolassetTable = "poolasset"
exchangeTable = "exchange"
chainconfigTable = "chainconfig"
blockchainTable = "blockchain"
assetVolumeTable = "assetvolume"
aggregatedVolumeTable = "aggregatedvolume"
tradesDistributionTable = "tradesdistribution"
// cache keys
keyAssetCache = "dia_asset_"
keyExchangePairCache = "dia_exchangepair_"
blockdataTable = "blockdata"
nftcategoryTable = "nftcategory"
nftclassTable = "nftclass"
nftTable = "nft"
NfttradeCurrTable = "nfttradecurrent"
NfttradeSumeriaTable = "nfttradesumeria"
nftbidTable = "nftbid"
nftofferTable = "nftoffer"
scrapersTable = "scrapers"
// time format for blockchain genesis dates
// timeFormatBlockchain = "2006-01-02"
)
// RelDB is a relative database with redis caching layer.
type RelDB struct {
URI string
postgresClient *pgxpool.Pool
redisClient *redis.Client
pagesize uint32
}
// NewRelDataStore returns a datastore with postgres client and redis cache.
func NewRelDataStore() (*RelDB, error) {
log.Info("NewRelDataStore: Initialised")
return NewRelDataStoreWithOptions(true, true)
}
// NewPostgresDataStore returns a datastore with postgres client and without redis caching layer.
func NewPostgresDataStore() (*RelDB, error) {
return NewRelDataStoreWithOptions(true, false)
}
// NewCachingLayer returns a datastore with redis caching layer and without postgres client.
func NewCachingLayer() (*RelDB, error) {
return NewRelDataStoreWithOptions(false, true)
}
// NewRelDataStoreWithOptions returns a postgres datastore and/or redis caching layer.
func NewRelDataStoreWithOptions(withPostgres bool, withRedis bool) (*RelDB, error) {
var postgresClient *pgxpool.Pool
var redisClient *redis.Client
var url string
if withPostgres {
url = db.GetPostgresURL()
postgresClient = db.PostgresDatabase()
}
if withRedis {
redisClient = db.GetRedisClient()
}
return &RelDB{url, postgresClient, redisClient, 32}, nil
}
// GetKeys returns a slice of strings holding the names of the keys of @table in postgres
func (rdb *RelDB) GetKeys(table string) (keys []string, err error) {
query := fmt.Sprintf("SELECT column_name from information_schema.columns WHERE table_name='%s'", table)
rows, err := rdb.postgresClient.Query(context.Background(), query)
if err != nil {
return
}
defer rows.Close()
for rows.Next() {
val, err := rows.Values()
if err != nil {
return keys, err
}
keys = append(keys, val[0].(string))
}
return
}