github.com/diadata-org/diadata@v1.4.593/pkg/model/relDB.go (about)

     1  package models
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/jackc/pgx/v4/pgxpool"
     9  
    10  	"github.com/diadata-org/diadata/pkg/dia"
    11  	"github.com/diadata-org/diadata/pkg/dia/helpers/db"
    12  
    13  	"github.com/go-redis/redis"
    14  )
    15  
    16  // RelDatastore is a (persistent) relational database with an additional redis caching layer
    17  type RelDatastore interface {
    18  
    19  	// --- Assets methods ---
    20  	// --------- Persistent ---------
    21  	SetAsset(asset dia.Asset) error
    22  	GetAsset(address, blockchain string) (dia.Asset, error)
    23  	GetAssetByID(ID string) (dia.Asset, error)
    24  	GetAssetsBySymbolName(symbol, name string) ([]dia.Asset, error)
    25  	GetAllAssets(blockchain string) ([]dia.Asset, error)
    26  	GetFiatAssetBySymbol(symbol string) (asset dia.Asset, err error)
    27  	GetAssetID(asset dia.Asset) (string, error)
    28  	GetPage(pageNumber uint32) ([]dia.Asset, bool, error)
    29  	Count() (uint32, error)
    30  	SetAssetVolume24H(asset dia.Asset, volume float64, timestamp time.Time) error
    31  	GetLastAssetVolume24H(asset dia.Asset) (float64, error)
    32  	GetAssetsWithVOL(starttime time.Time, numAssets int64, skip int64, onlycex bool, substring string) ([]dia.AssetVolume, error)
    33  	GetAssetSource(asset dia.Asset, onlycex bool) ([]string, error)
    34  	GetAssetsWithVolByBlockchain(starttime time.Time, endtime time.Time, blockchain string) ([]dia.AssetVolume, error)
    35  
    36  	// --------------- asset methods for exchanges ---------------
    37  	SetExchangePair(exchange string, pair dia.ExchangePair, cache bool) error
    38  	GetExchangePair(exchange string, foreignname string, caseSensitive bool) (exchangepair dia.ExchangePair, err error)
    39  	GetExchangePairSeparator(exchange string) (string, error)
    40  	GetPairsForExchange(exchange dia.Exchange, filterVerified bool, verified bool) ([]dia.ExchangePair, error)
    41  	GetPairsForAsset(asset dia.Asset, filterVerified bool, verified bool) ([]dia.ExchangePair, error)
    42  	GetExchangepairsByAsset(asset dia.Asset, exchange string, basetoken bool) ([]dia.ExchangePair, error)
    43  	GetExchangePairSymbols(exchange string) ([]dia.ExchangePair, error)
    44  	GetNumPairs(exchange dia.Exchange) (int, error)
    45  	SetExchangeSymbol(exchange string, symbol string) error
    46  	GetExchangeSymbol(exchange string, symbol string) (dia.Asset, error)
    47  	GetExchangeSymbols(exchange string, substring string) ([]string, error)
    48  	GetUnverifiedExchangeSymbols(exchange string) ([]string, error)
    49  	VerifyExchangeSymbol(exchange string, symbol string, assetID string) (bool, error)
    50  	GetExchangeSymbolAssetID(exchange string, symbol string) (string, bool, error)
    51  	GetAllExchangeAssets(verified bool) ([]dia.Asset, error)
    52  
    53  	// ----------------- Historical quotations methods -------------------
    54  	SetHistoricalQuotation(quotation AssetQuotation) error
    55  	GetHistoricalQuotations(asset dia.Asset, starttime time.Time, endtime time.Time) ([]AssetQuotation, error)
    56  	GetLastHistoricalQuotationTimestamp(asset dia.Asset) (time.Time, error)
    57  
    58  	// ----------------- exchange methods -------------------
    59  	SetExchange(exchange dia.Exchange) error
    60  	GetExchange(name string) (dia.Exchange, error)
    61  	GetAllExchanges() ([]dia.Exchange, error)
    62  	GetExchangeNames() ([]string, error)
    63  
    64  	// ----------------- pool methods -------------------
    65  	SetPool(pool dia.Pool) error
    66  	SetScraperIndex(exchange string, scraperType string, indexType string, index int64) error
    67  	GetScraperIndex(exchange string, scraperType string) (string, int64, error)
    68  	GetAllDEXPoolsCount() (map[string]int, error)
    69  	GetPoolByAddress(blockchain string, address string) (pool dia.Pool, err error)
    70  	GetAllPoolAddrsExchange(exchange string, liquiThreshold float64) ([]string, error)
    71  	GetAllPoolsExchange(exchange string, liquiThreshold float64) ([]dia.Pool, error)
    72  	GetPoolsByAsset(asset dia.Asset, liquidityThreshold float64, liquidityThresholdUSD float64) ([]dia.Pool, error)
    73  
    74  	// ----------------- blockchain methods -------------------
    75  	SetBlockchain(blockchain dia.BlockChain) error
    76  	GetBlockchain(name string) (dia.BlockChain, error)
    77  	GetAllAssetsBlockchains() ([]string, error)
    78  	GetAllBlockchains(fullAsset bool) ([]dia.BlockChain, error)
    79  
    80  	// ------ Caching ------
    81  	SetAssetCache(asset dia.Asset) error
    82  	GetAssetCache(blockchain string, address string) (dia.Asset, error)
    83  	SetExchangePairCache(exchange string, pair dia.ExchangePair) error
    84  	GetExchangePairCache(exchange string, foreignName string) (dia.ExchangePair, error)
    85  	CountCache() (uint32, error)
    86  
    87  	// General methods
    88  	GetKeys(table string) ([]string, error)
    89  
    90  	// Scraper config and state
    91  	GetScraperState(ctx context.Context, scraperName string, state ScraperState) error
    92  	SetScraperState(ctx context.Context, scraperName string, state ScraperState) error
    93  	GetScraperConfig(ctx context.Context, scraperName string, config ScraperConfig) error
    94  	SetScraperConfig(ctx context.Context, scraperName string, config ScraperConfig) error
    95  
    96  	// Blockchain data
    97  	SetBlockData(dia.BlockData) error
    98  	GetBlockData(blockchain string, blocknumber int64) (dia.BlockData, error)
    99  	GetLastBlockBlockscraper(blockchain string) (int64, error)
   100  
   101  	//Oracle builder
   102  	SetKeyPair(publickey string, privatekey string) error
   103  	GetKeyPairID(publickey string) string
   104  	GetFeederAccessByID(id string) (owner string)
   105  	GetFeederByID(id string) (owner string)
   106  	SetOracleConfig(ctx context.Context, customerId, address, feederID, owner, feederAddress, symbols, feedSelection, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, mandatoryFrequency, name string, draft, billable bool) error
   107  	SetFeederConfig(feederid, oracleconfigid string) error
   108  	GetFeederID(address string) (feederId string)
   109  	GetFeederLimit(owner string) (limit int)
   110  	GetTotalOracles(customerid string) (total int)
   111  	GetOracleConfig(address, chainid string) (oracleconfig dia.OracleConfig, err error)
   112  	ChangeOracleState(feederID string, active bool) (err error)
   113  	DeleteOracle(feederID string) (err error)
   114  	GetOraclesByOwner(owner string) (oracleconfigs []dia.OracleConfig, err error)
   115  	GetOraclesByCustomer(customerId string) (oracleconfigs []dia.OracleConfig, err error)
   116  
   117  	GetAllFeeders(bool, bool) (oracleconfigs []dia.OracleConfig, err error)
   118  	GetFeederResources() (addresses []string, err error)
   119  	GetOracleUpdates(address string, chainid string, offset int) ([]dia.OracleUpdate, error)
   120  	GetOracleUpdateCount(address string, chainid string, symbol string) (int64, error)
   121  	UpdateFeederAddressCheckSum(oracleaddress string) error
   122  	GetExpiredFeeders() (oracleconfigs []dia.OracleConfig, err error)
   123  	GetFeeder(feederID string) (oracleconfig dia.OracleConfig, err error)
   124  
   125  	GetDayWiseUpdates(address string, chainid string) ([]dia.FeedUpdates, float64, float64, error)
   126  	GetOracleLastUpdate(address, chainid, symbol string) (time.Time, string, error)
   127  	GetOracleUpdatesByTimeRange(address, chainid, symbol string, offset int, startTime, endTime time.Time) ([]dia.OracleUpdate, error)
   128  
   129  	// Asset List methods
   130  	SetAssetList(asset dia.AssetList) error
   131  	GetAssetListBySymbol(symbol string, listname string) ([]dia.AssetList, error)
   132  	DeleteAssetList(sheetName string) error
   133  
   134  	CreateCustomer(email string, name string, customerPlan int, paymentStatus string, paymentSource string, numberOfDataFeeds int, walletPublicKeys []string) error
   135  	AddWalletKeys(owner, username, accessLevel string, publicKey []string, customerId string) error
   136  
   137  	GetTempWalletRequest(ctx context.Context, publicKey, customerId string) (keyId int, accessLevel, username string, err error)
   138  	DeleteTempWalletRequest(ctx context.Context, keyId string) (err error)
   139  
   140  	AddTempWalletKeys(owner, username, accessLevel string, publicKey []string) error
   141  
   142  	UpdateAccessLevel(username, accessLevel, publicKey string) error
   143  	RemoveWalletKeys(publicKey []string) error
   144  	GetCustomerIDByWalletPublicKey(publicKey string) (int, error)
   145  	GetCustomerByPublicKey(publicKey string) (*Customer, error)
   146  	GetPendingPublicKeyByCustomer(ctx context.Context, customerId string) (pk []PublicKey, err error)
   147  
   148  	GetPendingInvites(ctx context.Context, publicKey string) (pk []PublicKey, err error)
   149  
   150  	UpdateCustomerPlan(ctx context.Context, customerID int, customerPlan int, paymentSource string, lastPayment string, payerAddress string) error
   151  	GetAccessLevel(publicKey string) (string, error)
   152  
   153  	GetAllChains() (chainconfigs []dia.ChainConfig, err error)
   154  	GetTotalGasSpend(address string, chainid string) (float64, error)
   155  	GetBalanceRemaining(address string, chainid string) (float64, error)
   156  	GetLastOracleUpdate(address string, chainid string) ([]dia.OracleUpdate, error)
   157  	GetLastPaymentByEndUser(endUser string) (LoopPaymentTransferProcessed, error)
   158  
   159  	GetPlan(ctx context.Context, planID int) (*Plan, error)
   160  	GetLastPaymentByAgreementID(agreementID string) (*LoopPaymentTransferProcessed, error)
   161  	InsertLoopPaymentTransferProcessed(ctx context.Context, record LoopPaymentTransferProcessed) error
   162  	InsertLoopPaymentResponse(ctx context.Context, response LoopPaymentResponse) error
   163  	GetLoopPaymentResponseByAgreementID(ctx context.Context, agreementID string) (*LoopPaymentResponse, error)
   164  	GetLoopPaymentResponseByCustomerID(ctx context.Context, customerID string) (*LoopPaymentResponse, error)
   165  	ChangeEcosystemConfig(oracleAddress string, enable bool) (err error)
   166  }
   167  
   168  const (
   169  
   170  	// postgres tables
   171  	assetTable               = "asset"
   172  	assetIdent               = "assetIdent"
   173  	exchangepairTable        = "exchangepair"
   174  	exchangesymbolTable      = "exchangesymbol"
   175  	poolTable                = "pool"
   176  	poolassetTable           = "poolasset"
   177  	scraperCronjobStateTable = "scraper_cronjob_state"
   178  	exchangeTable            = "exchange"
   179  	chainconfigTable         = "chainconfig"
   180  	blockchainTable          = "blockchain"
   181  	assetVolumeTable         = "assetvolume"
   182  	historicalQuotationTable = "historicalquotation"
   183  	pollingTable             = "polling"
   184  	swapRelationTable        = "swap_relation"
   185  	// cache keys
   186  	keyAssetCache        = "dia_asset_"
   187  	keyExchangePairCache = "dia_exchangepair_"
   188  
   189  	blockdataTable      = "blockdata"
   190  	scrapersTable       = "scrapers"
   191  	keypairTable        = "keypair"
   192  	oracleconfigTable   = "oracleconfig"
   193  	feederconfigTable   = "feederconfig"
   194  	feederaccessTable   = "feederaccess"
   195  	feederResourceTable = "feederresource"
   196  	feederupdatesTable  = "feederupdates"
   197  
   198  	// time format for blockchain genesis dates
   199  	// timeFormatBlockchain = "2006-01-02"
   200  )
   201  
   202  // RelDB is a relative database with redis caching layer.
   203  type RelDB struct {
   204  	URI            string
   205  	postgresClient *pgxpool.Pool
   206  	redisClient    *redis.Client
   207  	redisPipe      redis.Pipeliner
   208  	pagesize       uint32
   209  }
   210  
   211  // NewRelDataStore returns a datastore with postgres client and redis cache.
   212  func NewRelDataStore() (*RelDB, error) {
   213  	log.Info("NewRelDataStore: Initialised")
   214  	return NewRelDataStoreWithOptions(true, true)
   215  }
   216  
   217  // NewPostgresDataStore returns a datastore with postgres client and without redis caching layer.
   218  func NewPostgresDataStore() (*RelDB, error) {
   219  	return NewRelDataStoreWithOptions(true, false)
   220  }
   221  
   222  // NewCachingLayer returns a datastore with redis caching layer and without postgres client.
   223  func NewCachingLayer() (*RelDB, error) {
   224  	return NewRelDataStoreWithOptions(false, true)
   225  }
   226  
   227  // NewRelDataStoreWithOptions returns a postgres datastore and/or redis caching layer.
   228  func NewRelDataStoreWithOptions(withPostgres bool, withRedis bool) (*RelDB, error) {
   229  	var (
   230  		postgresClient *pgxpool.Pool
   231  		redisClient    *redis.Client
   232  		redisPipe      redis.Pipeliner
   233  		url            string
   234  	)
   235  
   236  	if withPostgres {
   237  		url = db.GetPostgresURL()
   238  		postgresClient = db.PostgresDatabase()
   239  	}
   240  	if withRedis {
   241  		redisClient = db.GetRedisClient()
   242  		redisPipe = redisClient.TxPipeline()
   243  	}
   244  	return &RelDB{url, postgresClient, redisClient, redisPipe, 32}, nil
   245  }
   246  
   247  // GetKeys returns a slice of strings holding the names of the keys of @table in postgres
   248  func (rdb *RelDB) GetKeys(table string) (keys []string, err error) {
   249  	query := fmt.Sprintf("SELECT column_name from information_schema.columns WHERE table_name='%s'", table)
   250  	rows, err := rdb.postgresClient.Query(context.Background(), query)
   251  	if err != nil {
   252  		return
   253  	}
   254  	defer rows.Close()
   255  
   256  	for rows.Next() {
   257  		val, err := rows.Values()
   258  		if err != nil {
   259  			return keys, err
   260  		}
   261  		keys = append(keys, val[0].(string))
   262  	}
   263  	return
   264  }