github.com/diadata-org/diadata@v1.4.593/pkg/model/exchanges.go (about) 1 package models 2 3 import ( 4 // "encoding/json" 5 "context" 6 "database/sql" 7 "encoding/json" 8 "fmt" 9 "sort" 10 "time" 11 12 "github.com/diadata-org/diadata/pkg/dia" 13 ) 14 15 // GetActiveExchangesAndPairs returns all exchanges the asset with @address and @blockchain was 16 // traded on in the given time-range as keys of a map. The map's values are the underlying pairs. 17 // Additionally, a map is returned where keys are exchange/pair identifier and values are the number 18 // of trades in the respective time-range. 19 // The pair has to have at least @numTrades trades in the given time-range in order to get returned. 20 func (datastore *DB) GetActiveExchangesAndPairs( 21 address string, 22 blockchain string, 23 numTradesThreshold int64, 24 starttime time.Time, 25 endtime time.Time, 26 ) (map[string][]dia.Pair, map[string]int64, error) { 27 exchangepairmap := make(map[string][]dia.Pair) 28 pairCountTradesMap := make(map[string]int64) 29 30 query := ` 31 SELECT count(*) 32 FROM %s 33 WHERE time>%d AND time<=%d 34 AND quotetokenaddress='%s' AND quotetokenblockchain='%s' 35 AND verified='true' 36 GROUP BY "exchange","pair","basetokenaddress","basetokenblockchain" 37 ` 38 39 q := fmt.Sprintf(query, influxDbTradesTable, starttime.UnixNano(), endtime.UnixNano(), address, blockchain) 40 res, err := queryInfluxDB(datastore.influxClient, q) 41 if err != nil { 42 return exchangepairmap, pairCountTradesMap, err 43 } 44 45 if len(res) > 0 && len(res[0].Series) > 0 { 46 for _, row := range res[0].Series { 47 48 if len(row.Values[0]) > 1 { 49 numTrades, err := row.Values[0][1].(json.Number).Int64() 50 if err != nil { 51 log.Warn("parse number of trades: ", err) 52 } 53 54 exchange := row.Tags["exchange"] 55 // Only include pair if it has more than @numTradesThreshold trades. 56 if numTrades >= numTradesThreshold { 57 pair := dia.Pair{ 58 QuoteToken: dia.Asset{Blockchain: blockchain, Address: address}, 59 BaseToken: dia.Asset{Blockchain: row.Tags["basetokenblockchain"], Address: row.Tags["basetokenaddress"]}, 60 } 61 exchangepairmap[exchange] = append(exchangepairmap[exchange], pair) 62 pairCountTradesMap[pair.PairExchangeIdentifier(exchange)] = numTrades 63 } 64 } 65 } 66 } 67 68 return exchangepairmap, pairCountTradesMap, nil 69 70 } 71 72 func (rdb *RelDB) GetExchangesForSymbol(symbol string) (exchanges []string, err error) { 73 74 query := fmt.Sprintf("select distinct(exchange) from %s where symbol=$1", exchangesymbolTable) 75 rows, err := rdb.postgresClient.Query(context.Background(), query, symbol) 76 if err != nil { 77 return 78 } 79 for rows.Next() { 80 exchange := "" 81 err = rows.Scan(&exchange) 82 if err != nil { 83 return []string{}, err 84 } 85 exchanges = append(exchanges, exchange) 86 } 87 return 88 } 89 90 // SetAvailablePairs stores @pairs in redis 91 // TO DO: Setter and getter should act on RelDB 92 func (datastore *DB) SetAvailablePairs(exchange string, pairs []dia.ExchangePair) error { 93 key := "dia_available_pairs_" + exchange 94 var p dia.Pairs = pairs 95 return datastore.redisClient.Set(key, &p, 0).Err() 96 } 97 98 // GetAvailablePairs a slice of all pairs available in the exchange in the internal redis db 99 func (datastore *DB) GetAvailablePairs(exchange string) ([]dia.ExchangePair, error) { 100 key := "dia_available_pairs_" + exchange 101 p := dia.Pairs{} 102 err := datastore.redisClient.Get(key).Scan(&p) 103 if err != nil { 104 log.Errorf("Error: %v on GetAvailablePairs %v\n", err, exchange) 105 return nil, err 106 } 107 return p, nil 108 } 109 110 func (rdb *RelDB) SetExchange(exchange dia.Exchange) (err error) { 111 fields := fmt.Sprintf("INSERT INTO %s (name,centralized,bridge,contract,blockchain,rest_api,ws_api,pairs_api,watchdog_delay,scraper_active) VALUES ", exchangeTable) 112 values := "($1,$2,$3,NULLIF($4,''),$5,NULLIF($6,''),NULLIF($7,''),NULLIF($8,''),$9,$10)" 113 conflict := " ON CONFLICT (name) DO UPDATE SET contract=NULLIF($4,''),rest_api=$6,ws_api=$7,pairs_api=$8,watchdog_delay=$9,scraper_active=$10" 114 115 query := fields + values + conflict 116 _, err = rdb.postgresClient.Exec(context.Background(), query, 117 exchange.Name, 118 exchange.Centralized, 119 exchange.Bridge, 120 exchange.Contract, 121 exchange.BlockChain.Name, 122 exchange.RestAPI, 123 exchange.WsAPI, 124 exchange.PairsAPI, 125 exchange.WatchdogDelay, 126 exchange.ScraperActive, 127 ) 128 if err != nil { 129 return err 130 } 131 return nil 132 } 133 134 func (rdb *RelDB) GetExchange(name string) (exchange dia.Exchange, err error) { 135 query := fmt.Sprintf(` 136 SELECT centralized,bridge,contract,blockchain,rest_api,ws_api,pairs_api,watchdog_delay,scraper_active 137 FROM %s 138 WHERE name=$1`, 139 exchangeTable, 140 ) 141 var ( 142 contract sql.NullString 143 blockchainName sql.NullString 144 restAPI sql.NullString 145 wsAPI sql.NullString 146 pairsAPI sql.NullString 147 ) 148 err = rdb.postgresClient.QueryRow(context.Background(), query, name).Scan( 149 &exchange.Centralized, 150 &exchange.Bridge, 151 &contract, 152 &blockchainName, 153 &restAPI, 154 &wsAPI, 155 &pairsAPI, 156 &exchange.WatchdogDelay, 157 &exchange.ScraperActive, 158 ) 159 if err != nil { 160 return 161 } 162 if contract.Valid { 163 exchange.Contract = contract.String 164 } 165 if blockchainName.Valid { 166 exchange.BlockChain.Name = blockchainName.String 167 } 168 if restAPI.Valid { 169 exchange.RestAPI = restAPI.String 170 } 171 if wsAPI.Valid { 172 exchange.WsAPI = wsAPI.String 173 } 174 if pairsAPI.Valid { 175 exchange.PairsAPI = pairsAPI.String 176 } 177 exchange.Name = name 178 return 179 } 180 181 // GetAllExchanges returns all exchanges existent in the exchange table. 182 func (rdb *RelDB) GetAllExchanges() (exchanges []dia.Exchange, err error) { 183 query := fmt.Sprintf(` 184 SELECT name,centralized,bridge,contract,blockchain,rest_api,ws_api,pairs_api,watchdog_delay,scraper_active 185 FROM %s`, 186 exchangeTable, 187 ) 188 rows, err := rdb.postgresClient.Query(context.Background(), query) 189 if err != nil { 190 return []dia.Exchange{}, err 191 } 192 defer rows.Close() 193 194 for rows.Next() { 195 var exchange dia.Exchange 196 var contract sql.NullString 197 var blockchainName sql.NullString 198 var restAPI sql.NullString 199 var wsAPI sql.NullString 200 var pairsAPI sql.NullString 201 err := rows.Scan( 202 &exchange.Name, 203 &exchange.Centralized, 204 &exchange.Bridge, 205 &contract, 206 &blockchainName, 207 &restAPI, 208 &wsAPI, 209 &pairsAPI, 210 &exchange.WatchdogDelay, 211 &exchange.ScraperActive, 212 ) 213 if err != nil { 214 return []dia.Exchange{}, err 215 } 216 if contract.Valid { 217 exchange.Contract = contract.String 218 } 219 if blockchainName.Valid { 220 exchange.BlockChain.Name = blockchainName.String 221 } 222 if restAPI.Valid { 223 exchange.RestAPI = restAPI.String 224 } 225 if wsAPI.Valid { 226 exchange.WsAPI = wsAPI.String 227 } 228 if pairsAPI.Valid { 229 exchange.PairsAPI = pairsAPI.String 230 } 231 exchanges = append(exchanges, exchange) 232 } 233 234 return exchanges, nil 235 } 236 237 // GetExchangeNames returns the names of all available exchanges. 238 func (rdb *RelDB) GetExchangeNames() (allExchanges []string, err error) { 239 exchanges, err := rdb.GetAllExchanges() 240 if err != nil { 241 return 242 } 243 for _, exchange := range exchanges { 244 allExchanges = append(allExchanges, exchange.Name) 245 } 246 sort.Strings(allExchanges) 247 return 248 } 249 250 func GetExchangeType(exchange dia.Exchange) string { 251 if exchange.Centralized { 252 return "CEX" 253 } else if exchange.Bridge { 254 return "Bridge" 255 } else { 256 return "DEX" 257 } 258 }