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

     1  package models
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"strconv"
    10  	"strings"
    11  	"time"
    12  
    13  	"github.com/diadata-org/diadata/pkg/dia"
    14  	"github.com/ethereum/go-ethereum/common"
    15  	"github.com/jackc/pgx/v4"
    16  )
    17  
    18  type Customer struct {
    19  	CustomerID          int       `json:"customer_id"`
    20  	Email               string    `json:"email"`
    21  	Name                string    `json:"name"`
    22  	AccountCreationDate time.Time `json:"account_creation_date"`
    23  	CustomerPlan        int       `json:"customer_plan"`
    24  	DeployedOracles     int       `json:"deployed_oracles"`
    25  	PaymentStatus       string    `json:"payment_status"`
    26  	// LastPayment         time.Time `json:"last_payment"`
    27  	PaymentSource     string      `json:"payment_source"`
    28  	NumberOfDataFeeds int         `json:"number_of_data_feeds"`
    29  	Active            bool        `json:"active"`
    30  	PublicKeys        []PublicKey `json:"public_keys"`
    31  	PayerAddress      string      `json:"payer_address"`
    32  }
    33  
    34  type Plan struct {
    35  	PlanID       int    `json:"plan_id"`
    36  	Name         string `json:"plan_name"`
    37  	Description  string `json:"plan_description"`
    38  	Price        int    `json:"plan_price"`
    39  	TotalFeeds   int    `json:"total_feeds"`
    40  	TotalOracles int    `json:"total_oracles"`
    41  }
    42  
    43  type PublicKey struct {
    44  	AccessLevel string `json:"access_level"`
    45  	PublicKey   string `json:"public_key"`
    46  	UserName    string `json:"username"`
    47  	CustomerId  string `json:"customer_id"`
    48  	Invitor     string `json:"invitor"`
    49  }
    50  
    51  func (rdb *RelDB) SetKeyPair(publickey string, privatekey string) error {
    52  	query := fmt.Sprintf(`INSERT INTO %s 
    53  	(publickey,privatekey) VALUES ($1,$2) 
    54  	 on conflict(publickey)  
    55  	do
    56  	update set publickey=EXCLUDED.publickey`, keypairTable)
    57  	exec, err := rdb.postgresClient.Exec(context.Background(), query, publickey, privatekey)
    58  
    59  	log.Infoln("exec", exec)
    60  	if err != nil {
    61  		return err
    62  	}
    63  	return nil
    64  }
    65  
    66  func (rdb *RelDB) GetKeyPairID(publicKey string) string {
    67  	query := fmt.Sprintf(`SELECT id from %s WHERE publickey=$1`, keypairTable)
    68  	rows := rdb.postgresClient.QueryRow(context.Background(), query, publicKey)
    69  	var keypairId string
    70  
    71  	err := rows.Scan(&keypairId)
    72  	if err != nil {
    73  		log.Error("Error getting results from db ", err)
    74  	}
    75  
    76  	return keypairId
    77  }
    78  
    79  func (rdb *RelDB) SetOracleConfig(ctx context.Context, customerId, address, feederID, owner, feederAddress, symbols, feedSelection, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, mandatoryFrequency, name string, draft, billable bool) error {
    80  	currentTime := time.Now()
    81  	query := fmt.Sprintf(`
    82  		INSERT INTO %s ( address,feeder_id,owner,symbols,chainID,
    83  						frequency,sleepseconds,deviationpermille,blockchainnode,
    84  						mandatory_frequency,feeder_address,createddate,lastupdate,feedSelection,
    85  						name,draft,customer_id,billable) 
    86  		VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18)
    87  		ON CONFLICT(feeder_id)  
    88  		DO UPDATE SET symbols=$4,frequency=$6,sleepseconds=$7,deviationpermille=$8,blockchainnode=$9,mandatory_frequency=$10,
    89  					  feeder_address=$11,lastupdate=$13,feedSelection=$14,name=$15,draft=$16,address=$1,billable=$18`,
    90  		oracleconfigTable,
    91  	)
    92  
    93  	_, err := rdb.postgresClient.Exec(ctx, query, address, feederID, owner, symbols, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, mandatoryFrequency, feederAddress, currentTime, currentTime, feedSelection, name, draft, customerId, billable)
    94  	if err != nil {
    95  		return err
    96  	}
    97  	return nil
    98  }
    99  
   100  func (rdb *RelDB) GetFeederID(address string) (feederId string) {
   101  	query := fmt.Sprintf(`SELECT id FROM %s WHERE owner=$1`, feederaccessTable)
   102  	log.Infoln("GetFeederID query", query)
   103  	log.Infoln("address", address)
   104  	var feederidint int
   105  	err := rdb.postgresClient.QueryRow(context.Background(), query, address).Scan(&feederidint)
   106  	if err != nil {
   107  		log.Error("Error getting results from db ", err)
   108  	}
   109  	feederId = strconv.Itoa(feederidint)
   110  
   111  	return
   112  }
   113  
   114  func (rdb *RelDB) SetFeederConfig(feederid, oracleconfigid string) error {
   115  	query := fmt.Sprintf(`
   116  		INSERT INTO %s (id, oracleconfig_id) 
   117  		VALUES ($1,$2) 
   118  		ON CONFLICT(id)  
   119  		DO UPDATE SET oracleconfig_id=EXCLUDED.oracleconfig_id`,
   120  		feederconfigTable,
   121  	)
   122  	_, err := rdb.postgresClient.Exec(context.Background(), query, feederid, oracleconfigid)
   123  	if err != nil {
   124  		return err
   125  	}
   126  	return nil
   127  }
   128  
   129  func (rdb *RelDB) GetFeederAccessByID(id string) (owner string) {
   130  	query := fmt.Sprintf(`SELECT owner FROM %s WHERE feeder_id=$1`, oracleconfigTable)
   131  	err := rdb.postgresClient.QueryRow(context.Background(), query, id).Scan(&owner)
   132  	if err != nil {
   133  		log.Error("Error getting results from db ", err)
   134  	}
   135  	return
   136  }
   137  
   138  func (rdb *RelDB) GetFeederByID(id string) (owner string) {
   139  	query := fmt.Sprintf(`SELECT owner from %s WHERE feeder_id=$1`, oracleconfigTable)
   140  	err := rdb.postgresClient.QueryRow(context.Background(), query, id).Scan(&owner)
   141  	if err != nil {
   142  		log.Error("Error getting results from db ", err)
   143  	}
   144  	return
   145  }
   146  func (rdb *RelDB) GetFeederLimit(owner string) (limit int) {
   147  	query := fmt.Sprintf(`SELECT total FROM %s WHERE owner=$1`, feederResourceTable)
   148  	err := rdb.postgresClient.QueryRow(context.Background(), query, owner).Scan(&limit)
   149  	if err != nil {
   150  		log.Error("Error getting results from db ", err)
   151  	}
   152  	return
   153  }
   154  
   155  func (rdb *RelDB) GetTotalOracles(customerId string) (total int) {
   156  	query := fmt.Sprintf(`SELECT count(*) FROM %s WHERE customer_id=$1 AND active=true`, oracleconfigTable)
   157  	err := rdb.postgresClient.QueryRow(context.Background(), query, customerId).Scan(&total)
   158  	if err != nil {
   159  		log.Error("Error getting results from db ", err)
   160  	}
   161  	return
   162  }
   163  
   164  func (rdb *RelDB) UpdateFeederAddressCheckSum(oracleaddress string) (err error) {
   165  
   166  	query := fmt.Sprintf(`
   167  	UPDATE %s 
   168  	SET address=$1
   169  	WHERE address=$2`, oracleconfigTable)
   170  
   171  	_, err = rdb.postgresClient.Exec(context.Background(), query, common.HexToAddress(oracleaddress).Hex(), oracleaddress)
   172  	if err != nil {
   173  		return
   174  	}
   175  
   176  	return
   177  }
   178  
   179  func (rdb *RelDB) GetExpiredFeeders() (oracleconfigs []dia.OracleConfig, err error) {
   180  
   181  	var (
   182  		rows           pgx.Rows
   183  		deviationFloat float64
   184  		query          string
   185  	)
   186  
   187  	//    AND t1.deleted = false
   188  
   189  	query = fmt.Sprintf(`
   190  	SELECT 
   191      t1.address,  t1.feeder_id, t1.deleted, t1.owner, t1.symbols, t1.chainID, 
   192      t1.frequency, t1.sleepseconds, t1.deviationpermille, t1.blockchainnode, t1.active, 
   193      t1.mandatory_frequency, t1.feeder_address, t1.createddate, 
   194      COALESCE(t1.lastupdate, '0001-01-01 00:00:00'::timestamp) AS lastupdate, 
   195      t1.expired, t1.expired_time,
   196      COALESCE(MAX(fu.update_time), '0001-01-01 00:00:00'::timestamp) AS max_update_time
   197  FROM %s AS t1
   198  LEFT JOIN %s AS fu 
   199  ON t1.address = fu.oracle_address
   200  GROUP BY  
   201      t1.address, t1.feeder_id, t1.deleted, t1.owner, t1.symbols, t1.chainID, 
   202      t1.frequency, t1.sleepseconds, t1.deviationpermille, t1.blockchainnode, t1.active, 
   203      t1.mandatory_frequency, t1.feeder_address, t1.createddate, 
   204      t1.lastupdate, t1.expired, t1.expired_time
   205  HAVING 
   206      EXTRACT(EPOCH FROM (NOW() - lastupdate)) / 86400 > 60
   207      AND t1.expired = false
   208  	`, oracleconfigTable, feederupdatesTable)
   209  
   210  	rows, err = rdb.postgresClient.Query(context.Background(), query)
   211  
   212  	if err != nil {
   213  		fmt.Println(err)
   214  
   215  		return
   216  	}
   217  	defer rows.Close()
   218  
   219  	for rows.Next() {
   220  		var (
   221  			oracleconfig     dia.OracleConfig
   222  			symbols          string
   223  			frequencynull    sql.NullString
   224  			sleepsecondsnull sql.NullString
   225  			feedSelection    sql.NullString
   226  		)
   227  		err := rows.Scan(&oracleconfig.Address, &oracleconfig.FeederID, &oracleconfig.Deleted, &oracleconfig.Owner, &symbols, &oracleconfig.ChainID,
   228  			&frequencynull, &sleepsecondsnull, &oracleconfig.DeviationPermille, &oracleconfig.BlockchainNode, &oracleconfig.Active,
   229  			&oracleconfig.MandatoryFrequency, &oracleconfig.FeederAddress, &oracleconfig.CreatedDate,
   230  			&oracleconfig.LastUpdate, &oracleconfig.Expired, &oracleconfig.ExpiredDate, &oracleconfig.LastOracleUpdate)
   231  		if err != nil {
   232  
   233  			log.Error("GetExpiredFeeders scan", err, oracleconfig.FeederID)
   234  		}
   235  
   236  		if frequencynull.Valid {
   237  			oracleconfig.Frequency = frequencynull.String
   238  
   239  		}
   240  
   241  		if feedSelection.Valid {
   242  			oracleconfig.FeederSelection = feedSelection.String
   243  		}
   244  
   245  		if sleepsecondsnull.Valid {
   246  			oracleconfig.SleepSeconds = sleepsecondsnull.String
   247  
   248  		}
   249  
   250  		oracleconfig.Symbols = strings.Split(symbols, ",")
   251  		if oracleconfig.DeviationPermille != "" {
   252  			deviationFloat, err = strconv.ParseFloat(oracleconfig.DeviationPermille, 64)
   253  			if err != nil {
   254  				log.Error(err)
   255  
   256  			}
   257  			oracleconfig.DeviationPermille = fmt.Sprintf("%.2f", deviationFloat/10)
   258  		}
   259  
   260  		oracleconfigs = append(oracleconfigs, oracleconfig)
   261  	}
   262  	return
   263  
   264  }
   265  func (rdb *RelDB) GetFeeder(feederID string) (oracleconfig dia.OracleConfig, err error) {
   266  	var (
   267  		row            pgx.Row
   268  		deviationFloat float64
   269  		query          string
   270  	)
   271  
   272  	query = fmt.Sprintf(`
   273  	SELECT address, feeder_id, owner,symbols, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, active,mandatory_frequency, feeder_address, name, createddate, COALESCE(lastupdate, '0001-01-01 00:00:00'::timestamp),
   274  	deleted,feedselection,expired,expired_time, draft,customer_id
   275  	FROM %s  WHERE feeder_id=$1
   276  	`, oracleconfigTable)
   277  	row = rdb.postgresClient.QueryRow(context.Background(), query, feederID)
   278  
   279  	if err != nil {
   280  		return
   281  	}
   282  
   283  	var (
   284  		symbols          string
   285  		frequencynull    sql.NullString
   286  		sleepsecondsnull sql.NullString
   287  		feedSelection    sql.NullString
   288  		customerID       int
   289  	)
   290  	err = row.Scan(&oracleconfig.Address, &oracleconfig.FeederID, &oracleconfig.Owner, &symbols, &oracleconfig.ChainID, &frequencynull, &sleepsecondsnull, &oracleconfig.DeviationPermille, &oracleconfig.BlockchainNode, &oracleconfig.Active, &oracleconfig.MandatoryFrequency, &oracleconfig.FeederAddress, &oracleconfig.Name, &oracleconfig.CreatedDate, &oracleconfig.LastUpdate, &oracleconfig.Deleted,
   291  		&feedSelection, &oracleconfig.Expired, &oracleconfig.ExpiredDate, &oracleconfig.Draft, &customerID)
   292  	if err != nil {
   293  
   294  		log.Error("GetFeeder scan", err, oracleconfig.FeederID)
   295  	}
   296  
   297  	if frequencynull.Valid {
   298  		oracleconfig.Frequency = frequencynull.String
   299  
   300  	}
   301  
   302  	oracleconfig.CustomerID = strconv.Itoa(customerID)
   303  
   304  	if feedSelection.Valid {
   305  		oracleconfig.FeederSelection = feedSelection.String
   306  	}
   307  
   308  	if sleepsecondsnull.Valid {
   309  		oracleconfig.SleepSeconds = sleepsecondsnull.String
   310  
   311  	}
   312  
   313  	oracleconfig.Symbols = strings.Split(symbols, ",")
   314  	if oracleconfig.DeviationPermille != "" {
   315  		deviationFloat, err = strconv.ParseFloat(oracleconfig.DeviationPermille, 64)
   316  		if err != nil {
   317  			log.Error(err)
   318  
   319  		}
   320  		oracleconfig.DeviationPermille = fmt.Sprintf("%.2f", deviationFloat/10)
   321  	}
   322  
   323  	return
   324  }
   325  
   326  func (rdb *RelDB) GetAllFeeders(isDeleted bool, isExpired bool) (oracleconfigs []dia.OracleConfig, err error) {
   327  	var (
   328  		rows           pgx.Rows
   329  		deviationFloat float64
   330  		query          string
   331  	)
   332  
   333  	switch {
   334  
   335  	case isDeleted:
   336  		{
   337  			query = fmt.Sprintf(`
   338  	SELECT address, feeder_id, owner,symbols, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, active,mandatory_frequency, feeder_address, createddate, COALESCE(lastupdate, '0001-01-01 00:00:00'::timestamp),deleted,feedselection,expired,expired_time
   339  	FROM %s  WHERE mandatory_frequency  IS NOT NULL   and deleted=$1
   340  	`, oracleconfigTable)
   341  			rows, err = rdb.postgresClient.Query(context.Background(), query, isDeleted)
   342  
   343  		}
   344  
   345  	case isExpired:
   346  		{
   347  			query = fmt.Sprintf(`
   348  	SELECT address, feeder_id, owner,symbols, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, active,mandatory_frequency, feeder_address, createddate, COALESCE(lastupdate, '0001-01-01 00:00:00'::timestamp),deleted,feedselection,expired,expired_time
   349  	FROM %s  WHERE mandatory_frequency  IS NOT NULL   and expired=$1
   350  	`, oracleconfigTable)
   351  			rows, err = rdb.postgresClient.Query(context.Background(), query, isExpired)
   352  		}
   353  
   354  	case isExpired && isDeleted:
   355  		{
   356  			query = fmt.Sprintf(`
   357  	SELECT address, feeder_id, owner,symbols, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, active,mandatory_frequency, feeder_address, createddate, COALESCE(lastupdate, '0001-01-01 00:00:00'::timestamp),deleted,feedselection,expired,expired_time
   358  	FROM %s  WHERE mandatory_frequency  IS NOT NULL   and expired=$1 and deleted=$2
   359  	`, oracleconfigTable)
   360  			rows, err = rdb.postgresClient.Query(context.Background(), query, isExpired, isDeleted)
   361  		}
   362  	case !isExpired && !isDeleted:
   363  		{
   364  			query = fmt.Sprintf(`
   365  	SELECT address, feeder_id, owner,symbols, chainID, frequency, sleepseconds, deviationpermille, blockchainnode, active,mandatory_frequency, feeder_address, createddate, COALESCE(lastupdate, '0001-01-01 00:00:00'::timestamp),deleted,feedselection,expired,expired_time
   366  	FROM %s  WHERE mandatory_frequency  IS NOT NULL 
   367  	`, oracleconfigTable)
   368  			rows, err = rdb.postgresClient.Query(context.Background(), query)
   369  
   370  		}
   371  
   372  	}
   373  
   374  	if err != nil {
   375  		return
   376  	}
   377  	defer rows.Close()
   378  
   379  	for rows.Next() {
   380  		var (
   381  			oracleconfig     dia.OracleConfig
   382  			symbols          string
   383  			frequencynull    sql.NullString
   384  			sleepsecondsnull sql.NullString
   385  			feedSelection    sql.NullString
   386  		)
   387  		err := rows.Scan(&oracleconfig.Address, &oracleconfig.FeederID, &oracleconfig.Owner, &symbols, &oracleconfig.ChainID, &frequencynull, &sleepsecondsnull, &oracleconfig.DeviationPermille, &oracleconfig.BlockchainNode, &oracleconfig.Active, &oracleconfig.MandatoryFrequency, &oracleconfig.FeederAddress, &oracleconfig.CreatedDate, &oracleconfig.LastUpdate, &oracleconfig.Deleted, &feedSelection, &oracleconfig.Expired, &oracleconfig.ExpiredDate)
   388  		if err != nil {
   389  
   390  			log.Error("GetAllFeeders scan", err, oracleconfig.FeederID)
   391  		}
   392  
   393  		if frequencynull.Valid {
   394  			oracleconfig.Frequency = frequencynull.String
   395  
   396  		}
   397  
   398  		if feedSelection.Valid {
   399  			oracleconfig.FeederSelection = feedSelection.String
   400  		}
   401  
   402  		if sleepsecondsnull.Valid {
   403  			oracleconfig.SleepSeconds = sleepsecondsnull.String
   404  
   405  		}
   406  
   407  		oracleconfig.Symbols = strings.Split(symbols, ",")
   408  		if oracleconfig.DeviationPermille != "" {
   409  			deviationFloat, err = strconv.ParseFloat(oracleconfig.DeviationPermille, 64)
   410  			if err != nil {
   411  				log.Error(err)
   412  
   413  			}
   414  			oracleconfig.DeviationPermille = fmt.Sprintf("%.2f", deviationFloat/10)
   415  		}
   416  
   417  		oracleconfigs = append(oracleconfigs, oracleconfig)
   418  	}
   419  	return
   420  }
   421  func (rdb *RelDB) GetFeederResources() (addresses []string, err error) {
   422  	var (
   423  		rows pgx.Rows
   424  	)
   425  	query := fmt.Sprintf(`
   426  	SELECT owner
   427  	FROM %s`, feederResourceTable)
   428  	rows, err = rdb.postgresClient.Query(context.Background(), query)
   429  	if err != nil {
   430  		return
   431  	}
   432  	defer rows.Close()
   433  
   434  	for rows.Next() {
   435  		var (
   436  			address string
   437  		)
   438  		err := rows.Scan(&address)
   439  		if err != nil {
   440  			log.Error(err)
   441  		}
   442  		addresses = append(addresses, address)
   443  	}
   444  	return
   445  
   446  }
   447  
   448  func (rdb *RelDB) GetOraclesByCustomer(customerId string) (oracleconfigs []dia.OracleConfig, err error) {
   449  	var (
   450  		rows           pgx.Rows
   451  		deviationFloat float64
   452  	)
   453  
   454  	/*
   455  	 `SELECT address, chainid,  COALESCE(latest.scraped_block, 0) AS latest_scraped_block FROM oracleconfig
   456  	  LEFT JOIN (SELECT oracle_address, chain_id, MAX(update_block) AS scraped_block FROM feederupdates GROUP BY oracle_address,chain_id) latest ON (oracleconfig.address = latest.oracle_address and oracleconfig.chainid = latest.chain_id) WHERE  oracleconfig.chainid = '%s'`
   457  
   458  
   459  	*/
   460  
   461  	query := fmt.Sprintf(`
   462  	SELECT 
   463      	t1.name,t1.address,  t1.feeder_id,t1.deleted,  t1.owner,  t1.symbols,  t1.chainID, 
   464      	t1.frequency,  t1.sleepseconds,  t1.deviationpermille,  t1.blockchainnode,   t1.active, 
   465      	t1.mandatory_frequency,  t1.feeder_address,  t1.createddate,  t1.feedselection, 
   466      	COALESCE(t1.lastupdate, '0001-01-01 00:00:00'::timestamp) AS lastupdate, 
   467  		t1.expired, t1.expired_time,
   468      	COALESCE(MAX(fu.update_time), '0001-01-01 00:00:00'::timestamp) AS max_update_time,
   469  		t1.billable,
   470  		t1.draft,
   471  		t1.ecosystem
   472  	FROM %s AS t1
   473  	LEFT JOIN %s AS fu 
   474      ON t1.address = fu.oracle_address 
   475      AND t1.chainID = fu.chain_id
   476  	WHERE t1.customer_id = $1 
   477  	GROUP BY  
   478  		t1.name,t1.address,  t1.feeder_id, t1.deleted, t1.owner,  t1.symbols,  t1.chainID, 
   479     		t1.frequency,  t1.sleepseconds,  t1.deviationpermille,  t1.blockchainnode,  t1.active, 
   480  		t1.mandatory_frequency,  t1.feeder_address, t1.createddate, t1.feedselection, 
   481       	t1.lastupdate, t1.expired,t1.expired_time,t1.billable,t1.draft,t1.ecosystem;`, oracleconfigTable, feederupdatesTable)
   482  	rows, err = rdb.postgresClient.Query(context.Background(), query, customerId)
   483  	if err != nil {
   484  		return
   485  	}
   486  	defer rows.Close()
   487  
   488  	for rows.Next() {
   489  		var (
   490  			oracleconfig  dia.OracleConfig
   491  			symbols       string
   492  			feedSelection sql.NullString
   493  			name          sql.NullString
   494  		)
   495  
   496  		err := rows.Scan(&name, &oracleconfig.Address, &oracleconfig.FeederID, &oracleconfig.Deleted, &oracleconfig.Owner, &symbols,
   497  			&oracleconfig.ChainID, &oracleconfig.Frequency, &oracleconfig.SleepSeconds, &oracleconfig.DeviationPermille,
   498  			&oracleconfig.BlockchainNode, &oracleconfig.Active, &oracleconfig.MandatoryFrequency, &oracleconfig.FeederAddress,
   499  			&oracleconfig.CreatedDate, &feedSelection, &oracleconfig.LastUpdate, &oracleconfig.Expired, &oracleconfig.ExpiredDate, &oracleconfig.LastOracleUpdate, &oracleconfig.Billable,
   500  			&oracleconfig.Draft,
   501  			&oracleconfig.Ecosystem)
   502  		if err != nil {
   503  			log.Error(err)
   504  		}
   505  		if feedSelection.Valid {
   506  			oracleconfig.FeederSelection = feedSelection.String
   507  		}
   508  
   509  		oracleconfig.Symbols = strings.Split(symbols, ",")
   510  
   511  		if oracleconfig.DeviationPermille != "" {
   512  			deviationFloat, err = strconv.ParseFloat(oracleconfig.DeviationPermille, 64)
   513  			if err != nil {
   514  				log.Error(err)
   515  
   516  			}
   517  			oracleconfig.DeviationPermille = fmt.Sprintf("%.2f", deviationFloat/10)
   518  		}
   519  
   520  		if name.Valid {
   521  			oracleconfig.Name = name.String
   522  		}
   523  
   524  		lastupdate := oracleconfig.LastOracleUpdate
   525  
   526  		if oracleconfig.LastOracleUpdate.IsZero() {
   527  			lastupdate = oracleconfig.CreatedDate
   528  		}
   529  		oracleconfig.ExpiringDate = lastupdate.Add(time.Duration(60 * time.Hour * 24))
   530  		if oracleconfig.ExpiringDate.Before(time.Now()) {
   531  			oracleconfig.Expired = true
   532  		}
   533  
   534  		oracleconfigs = append(oracleconfigs, oracleconfig)
   535  	}
   536  	return
   537  }
   538  
   539  func (rdb *RelDB) GetOraclesByOwner(owner string) (oracleconfigs []dia.OracleConfig, err error) {
   540  	var (
   541  		rows           pgx.Rows
   542  		deviationFloat float64
   543  	)
   544  
   545  	/*
   546  	 `SELECT address, chainid,  COALESCE(latest.scraped_block, 0) AS latest_scraped_block FROM oracleconfig
   547  	  LEFT JOIN (SELECT oracle_address, chain_id, MAX(update_block) AS scraped_block FROM feederupdates GROUP BY oracle_address,chain_id) latest ON (oracleconfig.address = latest.oracle_address and oracleconfig.chainid = latest.chain_id) WHERE  oracleconfig.chainid = '%s'`
   548  
   549  
   550  	*/
   551  
   552  	query := fmt.Sprintf(`
   553  	SELECT 
   554      	t1.address,  t1.feeder_id,t1.deleted,  t1.owner,  t1.symbols,  t1.chainID, 
   555      	t1.frequency,  t1.sleepseconds,  t1.deviationpermille,  t1.blockchainnode,   t1.active, 
   556      	t1.mandatory_frequency,  t1.feeder_address,  t1.createddate,  t1.feedselection, 
   557      	COALESCE(t1.lastupdate, '0001-01-01 00:00:00'::timestamp) AS lastupdate, 
   558  		t1.expired, t1.expired_time,
   559      	COALESCE(MAX(fu.update_time), '0001-01-01 00:00:00'::timestamp) AS max_update_time
   560  	FROM %s AS t1
   561  	LEFT JOIN %s AS fu 
   562      ON t1.address = fu.oracle_address 
   563      AND t1.chainID = fu.chain_id
   564  	WHERE t1.owner = $1 
   565  	GROUP BY  
   566  		t1.address,  t1.feeder_id, t1.deleted, t1.owner,  t1.symbols,  t1.chainID, 
   567     		t1.frequency,  t1.sleepseconds,  t1.deviationpermille,  t1.blockchainnode,  t1.active, 
   568  		t1.mandatory_frequency,  t1.feeder_address, t1.createddate, t1.feedselection, 
   569       	t1.lastupdate, t1.expired,t1.expired_time;`, oracleconfigTable, feederupdatesTable)
   570  	rows, err = rdb.postgresClient.Query(context.Background(), query, owner)
   571  	if err != nil {
   572  		return
   573  	}
   574  	defer rows.Close()
   575  
   576  	for rows.Next() {
   577  		var (
   578  			oracleconfig  dia.OracleConfig
   579  			symbols       string
   580  			feedSelection sql.NullString
   581  		)
   582  
   583  		err := rows.Scan(&oracleconfig.Address, &oracleconfig.FeederID, &oracleconfig.Deleted, &oracleconfig.Owner, &symbols,
   584  			&oracleconfig.ChainID, &oracleconfig.Frequency, &oracleconfig.SleepSeconds, &oracleconfig.DeviationPermille,
   585  			&oracleconfig.BlockchainNode, &oracleconfig.Active, &oracleconfig.MandatoryFrequency, &oracleconfig.FeederAddress,
   586  			&oracleconfig.CreatedDate, &feedSelection, &oracleconfig.LastUpdate, &oracleconfig.Expired, &oracleconfig.ExpiredDate, &oracleconfig.LastOracleUpdate)
   587  		if err != nil {
   588  			log.Error(err)
   589  		}
   590  		if feedSelection.Valid {
   591  			oracleconfig.FeederSelection = feedSelection.String
   592  		}
   593  
   594  		oracleconfig.Symbols = strings.Split(symbols, ",")
   595  
   596  		if oracleconfig.DeviationPermille != "" {
   597  			deviationFloat, err = strconv.ParseFloat(oracleconfig.DeviationPermille, 64)
   598  			if err != nil {
   599  				log.Error(err)
   600  
   601  			}
   602  			oracleconfig.DeviationPermille = fmt.Sprintf("%.2f", deviationFloat/10)
   603  		}
   604  
   605  		lastupdate := oracleconfig.LastOracleUpdate
   606  
   607  		if oracleconfig.LastOracleUpdate.IsZero() {
   608  			lastupdate = oracleconfig.CreatedDate
   609  		}
   610  		oracleconfig.ExpiringDate = lastupdate.Add(time.Duration(60 * time.Hour * 24))
   611  		if oracleconfig.ExpiringDate.Before(time.Now()) {
   612  			oracleconfig.Expired = true
   613  		}
   614  
   615  		oracleconfigs = append(oracleconfigs, oracleconfig)
   616  	}
   617  	return
   618  }
   619  
   620  func (rdb *RelDB) GetOracleConfig(address, chainid string) (oracleconfig dia.OracleConfig, err error) {
   621  	var (
   622  		symbols       string
   623  		feedSelection sql.NullString
   624  	)
   625  	query := fmt.Sprintf(`
   626  	SELECT address, feeder_id, owner,feeder_address,symbols, chainid, feedSelection,deviationpermille, sleepseconds,frequency, blockchainnode, mandatory_frequency, deleted, draft
   627  	FROM %s 
   628  	WHERE address=$1 and chainid=$2`, oracleconfigTable)
   629  	fmt.Println(query)
   630  	err = rdb.postgresClient.QueryRow(context.Background(), query, address, chainid).Scan(&oracleconfig.Address, &oracleconfig.FeederID, &oracleconfig.Owner, &oracleconfig.FeederAddress, &symbols, &oracleconfig.ChainID, &feedSelection, &oracleconfig.DeviationPermille, &oracleconfig.SleepSeconds, &oracleconfig.Frequency, &oracleconfig.BlockchainNode, &oracleconfig.MandatoryFrequency, &oracleconfig.Deleted, &oracleconfig.Draft)
   631  	if err != nil {
   632  		return
   633  	}
   634  
   635  	if feedSelection.Valid {
   636  		oracleconfig.FeederSelection = feedSelection.String
   637  	}
   638  
   639  	oracleconfig.Symbols = strings.Split(symbols, " ")
   640  
   641  	return
   642  }
   643  
   644  func (rdb *RelDB) ChangeOracleState(feederID string, active bool) (err error) {
   645  	currentTime := time.Now()
   646  
   647  	query := fmt.Sprintf(`
   648  	UPDATE %s 
   649  	SET active=$1, lastupdate=$3
   650  	WHERE feeder_id=$2`, oracleconfigTable)
   651  	_, err = rdb.postgresClient.Exec(context.Background(), query, active, feederID, currentTime)
   652  	if err != nil {
   653  		return
   654  	}
   655  
   656  	return
   657  }
   658  
   659  func (rdb *RelDB) ChangeEcosystemConfig(feederId string, enable bool) (err error) {
   660  	currentTime := time.Now()
   661  
   662  	query := fmt.Sprintf(`
   663  	UPDATE %s 
   664  	SET ecosystem=$1, lastupdate=$3
   665  	WHERE feeder_id=$2`, oracleconfigTable)
   666  	_, err = rdb.postgresClient.Exec(context.Background(), query, enable, feederId, currentTime)
   667  	if err != nil {
   668  		return
   669  	}
   670  
   671  	return
   672  }
   673  
   674  func (rdb *RelDB) DeleteOracle(feederID string) (err error) {
   675  	currentTime := time.Now()
   676  	query := fmt.Sprintf(`
   677  	UPDATE %s 
   678  	SET deleted=$1,lastupdate=$3
   679  	WHERE feeder_id=$2`, oracleconfigTable)
   680  	_, err = rdb.postgresClient.Exec(context.Background(), query, true, feederID, currentTime)
   681  	if err != nil {
   682  		return
   683  	}
   684  
   685  	return
   686  }
   687  
   688  func (rdb *RelDB) ExpireOracle(feederID string) (err error) {
   689  	currentTime := time.Now()
   690  	query := fmt.Sprintf(`
   691  	UPDATE %s 
   692  	SET expired=$1, deleted=$2,lastupdate=$4
   693  	WHERE feeder_id=$3`, oracleconfigTable)
   694  	_, err = rdb.postgresClient.Exec(context.Background(), query, true, true, feederID, currentTime)
   695  	if err != nil {
   696  		return
   697  	}
   698  
   699  	return
   700  }
   701  
   702  func (rdb *RelDB) GetOracleUpdateCount(address, chainid, symbol string) (int64, error) {
   703  	query := fmt.Sprintf(`
   704  	SELECT  count(*) from %s
   705  	WHERE oracle_address=$1 and chain_id=$2
   706  	AND ($3 = '' OR asset_key = $3)
   707  	
   708  	`, feederupdatesTable)
   709  
   710  	var numUpdates sql.NullInt64
   711  	err := rdb.postgresClient.QueryRow(context.Background(), query, address, chainid, symbol).Scan(&numUpdates)
   712  	if numUpdates.Valid {
   713  		return numUpdates.Int64, nil
   714  	}
   715  	return 0, err
   716  
   717  }
   718  
   719  func (rdb *RelDB) GetOracleLastUpdate(address, chainid, symbol string) (time.Time, string, error) {
   720  	symbol = symbol + "/USD"
   721  	var (
   722  		updateTime sql.NullTime
   723  		price      string
   724  	)
   725  	query := fmt.Sprintf(`
   726  	SELECT update_time,asset_price
   727  	FROM %s fu
   728  	WHERE oracle_address = $1 AND chain_id = $2 and asset_key=$3 order by update_block desc LIMIT 1 
   729  	`, feederupdatesTable)
   730  
   731  	err := rdb.postgresClient.QueryRow(context.Background(), query, address, chainid, symbol).Scan(&updateTime, &price)
   732  	if err != nil {
   733  		return time.Time{}, "", err
   734  	}
   735  
   736  	return updateTime.Time, price, nil
   737  }
   738  func (rdb *RelDB) GetOracleUpdates(address string, chainid string, offset int) ([]dia.OracleUpdate, error) {
   739  	query := fmt.Sprintf(`
   740  	SELECT fu.oracle_address,
   741  		fu.transaction_hash,
   742  		fu.transaction_cost,
   743  		fu.asset_key,
   744  		fu.asset_price,
   745  		fu.update_block,
   746  		fu.update_from,
   747  		fu.from_balance,
   748  		fu.gas_cost,
   749  		fu.gas_used,
   750  		fu.chain_id,
   751  		fu.update_time,
   752  		oc.creation_block,
   753  		oc.creation_block_time
   754  
   755  
   756  	FROM %s fu
   757  	JOIN %s oc ON fu.oracle_address = oc.address AND fu.chain_id = oc.chainID 
   758  	WHERE fu.oracle_address = $1 AND fu.chain_id = $2 order by fu.update_block desc LIMIT 20 OFFSET %d
   759  	`, feederupdatesTable, oracleconfigTable, offset)
   760  
   761  	rows, err := rdb.postgresClient.Query(context.Background(), query, address, chainid)
   762  	if err != nil {
   763  		return nil, err
   764  	}
   765  	defer rows.Close()
   766  
   767  	var (
   768  		updates []dia.OracleUpdate
   769  	)
   770  
   771  	for rows.Next() {
   772  
   773  		var (
   774  			update            dia.OracleUpdate
   775  			updateTime        sql.NullTime
   776  			creationBlock     sql.NullInt64
   777  			creationBlockTime sql.NullTime
   778  		)
   779  		err := rows.Scan(
   780  			&update.OracleAddress,
   781  			&update.TransactionHash,
   782  			&update.TransactionCost,
   783  			&update.AssetKey,
   784  			&update.AssetPrice,
   785  			&update.UpdateBlock,
   786  			&update.UpdateFrom,
   787  			&update.FromBalance,
   788  			&update.GasCost,
   789  			&update.GasUsed,
   790  			&update.ChainID,
   791  			&updateTime,
   792  			&creationBlock,
   793  			&creationBlockTime,
   794  		)
   795  
   796  		if updateTime.Valid {
   797  			update.UpdateTime = updateTime.Time
   798  		}
   799  		if creationBlockTime.Valid {
   800  			update.CreationBlockTime = creationBlockTime.Time
   801  		}
   802  		if creationBlock.Valid {
   803  			update.CreationBlock = uint64(creationBlock.Int64)
   804  		}
   805  
   806  		if err != nil {
   807  			return nil, err
   808  		}
   809  
   810  		updates = append(updates, update)
   811  	}
   812  
   813  	if err := rows.Err(); err != nil {
   814  		return nil, err
   815  	}
   816  
   817  	return updates, nil
   818  }
   819  func (rdb *RelDB) GetOracleUpdatesByTimeRange(address, chainid, symbol string, offset int, startTime, endTime time.Time) ([]dia.OracleUpdate, error) {
   820  	query := ""
   821  	if offset == -1 {
   822  		query = fmt.Sprintf(`
   823  	SELECT fu.oracle_address,
   824  		fu.transaction_hash,
   825  		fu.transaction_cost,
   826  		fu.asset_key,
   827  		fu.asset_price,
   828  		fu.update_block,
   829  		fu.update_from,
   830  		fu.from_balance,
   831  		fu.gas_cost,
   832  		fu.gas_used,
   833  		fu.chain_id,
   834  		fu.update_time,
   835  		oc.creation_block,
   836  		oc.creation_block_time
   837  
   838  	FROM %s fu
   839  	JOIN %s oc ON fu.oracle_address = oc.address AND fu.chain_id = oc.chainID 
   840  	WHERE fu.oracle_address = $1 AND fu.chain_id = $2 
   841      AND ($3 = 0 OR $4 = 0 OR (fu.update_time < to_timestamp($3) AND fu.update_time > to_timestamp($4)))
   842  	AND ($5 = '' OR fu.asset_key = $5)  
   843  
   844  	order by fu.update_block desc 
   845  	`, feederupdatesTable, oracleconfigTable)
   846  
   847  	} else {
   848  		query = fmt.Sprintf(`
   849  	SELECT fu.oracle_address,
   850  		fu.transaction_hash,
   851  		fu.transaction_cost,
   852  		fu.asset_key,
   853  		fu.asset_price,
   854  		fu.update_block,
   855  		fu.update_from,
   856  		fu.from_balance,
   857  		fu.gas_cost,
   858  		fu.gas_used,
   859  		fu.chain_id,
   860  		fu.update_time,
   861  		oc.creation_block,
   862  		oc.creation_block_time
   863  
   864  	FROM %s fu
   865  	JOIN %s oc ON fu.oracle_address = oc.address AND fu.chain_id = oc.chainID 
   866  	WHERE fu.oracle_address = $1 AND fu.chain_id = $2 
   867      AND ($3 = 0 OR $4 = 0 OR (fu.update_time < to_timestamp($3) AND fu.update_time > to_timestamp($4)))
   868  	AND ($5 = '' OR fu.asset_key = $5)  
   869  
   870  	order by fu.update_block desc LIMIT 20 OFFSET %d
   871  	`, feederupdatesTable, oracleconfigTable, offset)
   872  
   873  	}
   874  
   875  	rows, err := rdb.postgresClient.Query(context.Background(), query, address, chainid, endTime.Unix(), startTime.Unix(), symbol)
   876  	if err != nil {
   877  		return nil, err
   878  	}
   879  	defer rows.Close()
   880  
   881  	var (
   882  		updates []dia.OracleUpdate
   883  	)
   884  
   885  	for rows.Next() {
   886  
   887  		var (
   888  			update            dia.OracleUpdate
   889  			updateTime        sql.NullTime
   890  			creationBlock     sql.NullInt64
   891  			creationBlockTime sql.NullTime
   892  		)
   893  		err := rows.Scan(
   894  			&update.OracleAddress,
   895  			&update.TransactionHash,
   896  			&update.TransactionCost,
   897  			&update.AssetKey,
   898  			&update.AssetPrice,
   899  			&update.UpdateBlock,
   900  			&update.UpdateFrom,
   901  			&update.FromBalance,
   902  			&update.GasCost,
   903  			&update.GasUsed,
   904  			&update.ChainID,
   905  			&updateTime,
   906  			&creationBlock,
   907  			&creationBlockTime,
   908  		)
   909  
   910  		if updateTime.Valid {
   911  			update.UpdateTime = updateTime.Time
   912  		}
   913  		if creationBlockTime.Valid {
   914  			update.CreationBlockTime = creationBlockTime.Time
   915  		}
   916  		if creationBlock.Valid {
   917  			update.CreationBlock = uint64(creationBlock.Int64)
   918  		}
   919  
   920  		if err != nil {
   921  			return nil, err
   922  		}
   923  
   924  		updates = append(updates, update)
   925  	}
   926  
   927  	if err := rows.Err(); err != nil {
   928  		return nil, err
   929  	}
   930  
   931  	return updates, nil
   932  }
   933  func (rdb *RelDB) GetLastOracleUpdate(address string, chainid string) ([]dia.OracleUpdate, error) {
   934  	query := fmt.Sprintf(`
   935  	SELECT fu.oracle_address,
   936  		fu.transaction_hash,
   937  		fu.transaction_cost,
   938  		fu.asset_key,
   939  		fu.asset_price,
   940  		fu.update_block,
   941  		fu.update_from,
   942  		fu.from_balance,
   943  		fu.gas_cost,
   944  		fu.gas_used,
   945  		fu.chain_id,
   946  		fu.update_time,
   947  		oc.creation_block,
   948  		oc.creation_block_time
   949  
   950  
   951  	FROM %s fu
   952  	JOIN %s oc ON fu.oracle_address = oc.address AND fu.chain_id = oc.chainID 
   953  	WHERE fu.oracle_address = $1 AND fu.chain_id = $2 order by fu.update_time desc LIMIT 1
   954  	`, feederupdatesTable, oracleconfigTable)
   955  
   956  	rows, err := rdb.postgresClient.Query(context.Background(), query, address, chainid)
   957  	if err != nil {
   958  		return nil, err
   959  	}
   960  	defer rows.Close()
   961  
   962  	var (
   963  		updates []dia.OracleUpdate
   964  	)
   965  
   966  	for rows.Next() {
   967  
   968  		var (
   969  			update            dia.OracleUpdate
   970  			updateTime        sql.NullTime
   971  			creationBlock     sql.NullInt64
   972  			creationBlockTime sql.NullTime
   973  		)
   974  		err := rows.Scan(
   975  			&update.OracleAddress,
   976  			&update.TransactionHash,
   977  			&update.TransactionCost,
   978  			&update.AssetKey,
   979  			&update.AssetPrice,
   980  			&update.UpdateBlock,
   981  			&update.UpdateFrom,
   982  			&update.FromBalance,
   983  			&update.GasCost,
   984  			&update.GasUsed,
   985  			&update.ChainID,
   986  			&updateTime,
   987  			&creationBlock,
   988  			&creationBlockTime,
   989  		)
   990  
   991  		if updateTime.Valid {
   992  			update.UpdateTime = updateTime.Time
   993  		}
   994  		if creationBlockTime.Valid {
   995  			update.CreationBlockTime = creationBlockTime.Time
   996  		}
   997  		if creationBlock.Valid {
   998  			update.CreationBlock = uint64(creationBlock.Int64)
   999  		}
  1000  
  1001  		if err != nil {
  1002  			return nil, err
  1003  		}
  1004  
  1005  		updates = append(updates, update)
  1006  	}
  1007  
  1008  	if err := rows.Err(); err != nil {
  1009  		return nil, err
  1010  	}
  1011  
  1012  	return updates, nil
  1013  }
  1014  func (rdb *RelDB) GetTotalGasSpend(address string, chainid string) (float64, error) {
  1015  	query := fmt.Sprintf(`
  1016  	SELECT 
  1017  		SUM(fu.gas_used) AS total_gas_used
  1018  	FROM %s fu
  1019  	WHERE fu.oracle_address = $1 AND fu.chain_id = $2
  1020  	`, feederupdatesTable)
  1021  
  1022  	rows, err := rdb.postgresClient.Query(context.Background(), query, address, chainid)
  1023  	if err != nil {
  1024  		fmt.Println("err", err)
  1025  		return 0.0, err
  1026  	}
  1027  	defer rows.Close()
  1028  
  1029  	var (
  1030  		gasUsed sql.NullFloat64
  1031  	)
  1032  
  1033  	for rows.Next() {
  1034  
  1035  		rows.Scan(
  1036  
  1037  			&gasUsed,
  1038  		)
  1039  
  1040  	}
  1041  
  1042  	if gasUsed.Valid {
  1043  		return gasUsed.Float64, nil
  1044  
  1045  	}
  1046  	return 0.0, nil
  1047  
  1048  }
  1049  
  1050  func (rdb *RelDB) GetBalanceRemaining(address string, chainid string) (float64, error) {
  1051  	query := fmt.Sprintf(`
  1052  	SELECT 
  1053  		from_balance,
  1054  		update_time
  1055  	FROM %s fu
  1056  	WHERE fu.oracle_address = $1 AND fu.chain_id = $2 ORDER BY update_time DESC LIMIT 1
  1057  	`, feederupdatesTable)
  1058  
  1059  	rows, err := rdb.postgresClient.Query(context.Background(), query, address, chainid)
  1060  	if err != nil {
  1061  		fmt.Println("err", err)
  1062  		return 0.0, err
  1063  	}
  1064  	defer rows.Close()
  1065  
  1066  	var (
  1067  		gasRemaining sql.NullFloat64
  1068  	)
  1069  
  1070  	for rows.Next() {
  1071  
  1072  		rows.Scan(
  1073  			&gasRemaining,
  1074  			nil,
  1075  		)
  1076  
  1077  	}
  1078  
  1079  	if gasRemaining.Valid {
  1080  		return gasRemaining.Float64, nil
  1081  
  1082  	}
  1083  	return 0.0, nil
  1084  
  1085  }
  1086  
  1087  func (rdb *RelDB) GetDayWiseUpdates(address string, chainid string) ([]dia.FeedUpdates, float64, float64, error) {
  1088  	query := fmt.Sprintf(`
  1089  	WITH Dates AS (
  1090  		SELECT generate_series(CURRENT_DATE - INTERVAL '29 days', CURRENT_DATE, INTERVAL '1 day')::DATE AS day
  1091  	),
  1092  	DailyUpdates AS (
  1093  		SELECT 
  1094  			d.day, 
  1095  			AVG(fu.gas_used) AS average_gas_used,
  1096  			SUM(fu.gas_used) AS total_gas_used,
  1097  			COUNT(fu.update_time) AS total_updates
  1098  		FROM Dates d
  1099  		LEFT JOIN %s fu ON DATE(fu.update_time) = d.day
  1100  			AND fu.oracle_address = $1 
  1101  			AND fu.chain_id = $2
  1102  		GROUP BY d.day
  1103  	)
  1104  	SELECT 
  1105  		day, 
  1106  		COALESCE(total_gas_used, 0) AS total_gas_used,
  1107  		COALESCE(total_updates, 0) AS total_updates,
  1108  		(SELECT AVG(total_updates::NUMERIC) FROM DailyUpdates) AS average_total_updates_per_day,
  1109  		(SELECT AVG(average_gas_used) FROM DailyUpdates) AS average_gas_used_per_day
  1110  	FROM DailyUpdates
  1111  	ORDER BY day DESC;
  1112  	`, feederupdatesTable)
  1113  
  1114  	rows, err := rdb.postgresClient.Query(context.Background(), query, address, chainid)
  1115  	if err != nil {
  1116  		fmt.Println("err", err)
  1117  		return nil, 0, 0, err
  1118  	}
  1119  	defer rows.Close()
  1120  
  1121  	var (
  1122  		avgGasUsed     sql.NullFloat64
  1123  		avgUpdateCount sql.NullFloat64
  1124  		stats          []dia.FeedUpdates
  1125  		updateTime     sql.NullTime
  1126  	)
  1127  
  1128  	for rows.Next() {
  1129  		du := dia.FeedUpdates{}
  1130  		rows.Scan(
  1131  			&updateTime,
  1132  			&du.GasUsed,
  1133  			&du.UpdateCount,
  1134  			&avgUpdateCount,
  1135  			&avgGasUsed,
  1136  		)
  1137  		if updateTime.Valid {
  1138  			du.Day = updateTime.Time
  1139  		}
  1140  
  1141  		stats = append(stats, du)
  1142  
  1143  	}
  1144  
  1145  	return stats, avgGasUsed.Float64, avgUpdateCount.Float64, nil
  1146  
  1147  }
  1148  
  1149  // dave oracleconfig in cache
  1150  func (datastore *DB) SetOracleConfigCache(oc dia.OracleConfig) error {
  1151  	key := oc.Address + "-" + oc.ChainID
  1152  
  1153  	if datastore.redisClient == nil {
  1154  		return nil
  1155  	}
  1156  
  1157  	data, _ := json.Marshal(oc)
  1158  
  1159  	err := datastore.redisClient.Set(key, data, TimeOutRedis).Err()
  1160  	if err != nil {
  1161  		log.Printf("Error: %v on SetOracleConfigCache %v\n", err, oc)
  1162  	}
  1163  
  1164  	return err
  1165  }
  1166  
  1167  func (datastore *DB) GetOracleConfigCache(key string) (dia.OracleConfig, error) {
  1168  	// key := oc.Address + oc.ChainID
  1169  	var oc dia.OracleConfig
  1170  	if datastore.redisClient == nil {
  1171  		return oc, errors.New("no redisclient")
  1172  	}
  1173  
  1174  	err := datastore.redisClient.Get(key).Scan(&oc)
  1175  	if err != nil {
  1176  		log.Printf("Error: %v on GetOracle--ConfigCache %v\n", err, oc)
  1177  		return oc, errors.New("no redisclient")
  1178  
  1179  	}
  1180  
  1181  	return oc, err
  1182  
  1183  }
  1184  
  1185  func (reldb *RelDB) AddWalletKeys(owner, username, accessLevel string, publicKey []string, customerId string) error {
  1186  	var err error
  1187  
  1188  	// customerID, err := reldb.GetCustomerIDByWalletPublicKey(owner)
  1189  	// if err != nil {
  1190  	// 	return err
  1191  	// }
  1192  
  1193  	tx, err := reldb.postgresClient.BeginTx(context.Background(), pgx.TxOptions{})
  1194  	if err != nil {
  1195  		return err
  1196  
  1197  	}
  1198  	defer tx.Rollback(context.Background())
  1199  
  1200  	for _, publicKey := range publicKey {
  1201  		_, err = tx.Exec(context.Background(), `
  1202  			INSERT INTO wallet_public_keys (customer_id, public_key, access_level,username)
  1203  			VALUES ($1, $2,$3,$4)
  1204  		`, customerId, publicKey, accessLevel, username)
  1205  		if err != nil {
  1206  			return err
  1207  		}
  1208  	}
  1209  
  1210  	err = tx.Commit(context.Background())
  1211  	if err != nil {
  1212  		return err
  1213  	}
  1214  
  1215  	return nil
  1216  }
  1217  
  1218  func (reldb *RelDB) AddTempWalletKeys(owner, username, accessLevel string, publicKey []string) error {
  1219  	var err error
  1220  
  1221  	customerID, err := reldb.GetCustomerIDByWalletPublicKey(owner)
  1222  	if err != nil {
  1223  		return err
  1224  	}
  1225  
  1226  	tx, err := reldb.postgresClient.BeginTx(context.Background(), pgx.TxOptions{})
  1227  	if err != nil {
  1228  		return err
  1229  
  1230  	}
  1231  	defer tx.Rollback(context.Background())
  1232  
  1233  	for _, publicKey := range publicKey {
  1234  		_, err = tx.Exec(context.Background(), `
  1235  			INSERT INTO wallet_public_keys_temp (customer_id, public_key, access_level,username,invitor)
  1236  			VALUES ($1, $2,$3,$4,$5)
  1237  		`, customerID, publicKey, accessLevel, username, owner)
  1238  		if err != nil {
  1239  			return err
  1240  		}
  1241  	}
  1242  
  1243  	err = tx.Commit(context.Background())
  1244  	if err != nil {
  1245  		return err
  1246  	}
  1247  
  1248  	return nil
  1249  
  1250  }
  1251  
  1252  func (reldb *RelDB) DeleteTempWalletRequest(ctx context.Context, keyId string) (err error) {
  1253  	query := `
  1254  	DELETE FROM wallet_public_keys_temp
  1255  	WHERE key_id = $1;
  1256  `
  1257  
  1258  	result, err := reldb.postgresClient.Exec(ctx, query, keyId)
  1259  	if err != nil {
  1260  		return fmt.Errorf("failed to execute delete query: %v", err)
  1261  	}
  1262  
  1263  	rowsAffected := result.RowsAffected()
  1264  
  1265  	if rowsAffected == 0 {
  1266  		return fmt.Errorf("no record found with key_id: %d", keyId)
  1267  	}
  1268  
  1269  	return nil
  1270  }
  1271  
  1272  func (reldb *RelDB) GetTempWalletRequest(ctx context.Context, publicKey, customerID string) (keyID int, accessLevel, username string, err error) {
  1273  	query := `
  1274  		SELECT key_id, access_level, username
  1275  		FROM wallet_public_keys_temp
  1276  		WHERE public_key = $1 AND customer_id = $2;
  1277  	`
  1278  
  1279  	err = reldb.postgresClient.QueryRow(ctx, query, publicKey, customerID).Scan(
  1280  		&keyID,
  1281  		&accessLevel,
  1282  		&username,
  1283  	)
  1284  
  1285  	if err != nil {
  1286  		if err == sql.ErrNoRows {
  1287  			err = fmt.Errorf("no wallet public key found for public_key: %s and username: %s", publicKey, username)
  1288  		}
  1289  	}
  1290  
  1291  	return
  1292  
  1293  }
  1294  
  1295  func (reldb *RelDB) UpdateAccessLevel(username, accessLevel, publicKey string) error {
  1296  	// Start building the SQL query
  1297  	query := "UPDATE wallet_public_keys SET"
  1298  	var fields []string
  1299  	var args []interface{}
  1300  	argID := 1
  1301  
  1302  	if accessLevel != "" {
  1303  		fields = append(fields, fmt.Sprintf(" access_level = $%d", argID))
  1304  		args = append(args, accessLevel)
  1305  		argID++
  1306  	}
  1307  
  1308  	username = strings.TrimSpace(username)
  1309  
  1310  	// Conditionally add username if it's not nil or empty
  1311  	if username != "" {
  1312  		fields = append(fields, fmt.Sprintf(" username = $%d", argID))
  1313  		args = append(args, username)
  1314  		argID++
  1315  	}
  1316  
  1317  	// If no fields are provided to update, return an error
  1318  	if len(fields) == 0 {
  1319  		return fmt.Errorf("no fields provided to update")
  1320  	}
  1321  
  1322  	// Add the WHERE clause to target the correct public_key
  1323  	query += strings.Join(fields, ",") + fmt.Sprintf(" WHERE public_key = $%d", argID)
  1324  	args = append(args, publicKey)
  1325  
  1326  	tx, err := reldb.postgresClient.BeginTx(context.Background(), pgx.TxOptions{})
  1327  	if err != nil {
  1328  		return err
  1329  
  1330  	}
  1331  
  1332  	_, err = tx.Exec(context.Background(), query, args...)
  1333  	if err != nil {
  1334  		return fmt.Errorf("failed to prepare statement: %w", err)
  1335  	}
  1336  
  1337  	err = tx.Commit(context.Background())
  1338  
  1339  	if err != nil {
  1340  		return fmt.Errorf("failed to execute update: %w", err)
  1341  	}
  1342  
  1343  	return nil
  1344  }
  1345  
  1346  func (reldb *RelDB) RemoveWalletKeys(publicKey []string) error {
  1347  	var err error
  1348  
  1349  	tx, err := reldb.postgresClient.BeginTx(context.Background(), pgx.TxOptions{})
  1350  	if err != nil {
  1351  		return err
  1352  
  1353  	}
  1354  	defer tx.Rollback(context.Background())
  1355  
  1356  	for _, publicKey := range publicKey {
  1357  		_, err = tx.Exec(context.Background(), `
  1358  		DELETE FROM wallet_public_keys 
  1359  		WHERE public_key = $1
  1360  		`, publicKey)
  1361  		if err != nil {
  1362  			return err
  1363  		}
  1364  	}
  1365  
  1366  	err = tx.Commit(context.Background())
  1367  	if err != nil {
  1368  		return err
  1369  	}
  1370  
  1371  	return nil
  1372  }
  1373  func (reldb *RelDB) GetCustomerIDByWalletPublicKey(publicKey string) (int, error) {
  1374  	var customerID int
  1375  	err := reldb.postgresClient.QueryRow(context.Background(), `
  1376  		SELECT customer_id
  1377  		FROM wallet_public_keys
  1378  		WHERE public_key = $1
  1379  	`, publicKey).Scan(&customerID)
  1380  	if err != nil {
  1381  		return 0, err
  1382  	}
  1383  	return customerID, nil
  1384  }
  1385  
  1386  func (reldb *RelDB) CreateCustomer(email string, name string, customerPlan int, paymentStatus string, paymentSource string, numberOfDataFeeds int, walletPublicKeys []string) error {
  1387  	tx, err := reldb.postgresClient.Begin(context.Background())
  1388  	if err != nil {
  1389  		return fmt.Errorf("unable to start a transaction: %v", err)
  1390  	}
  1391  	defer tx.Rollback(context.Background())
  1392  
  1393  	// Insert the new customer
  1394  	var customerID int
  1395  	insertCustomerQuery := `
  1396          INSERT INTO customers (email, customer_plan, payment_status, payment_source, number_of_data_feeds,name)
  1397          VALUES ($1, $2, $3, $4, $5,$6)
  1398          RETURNING customer_id`
  1399  
  1400  	err = tx.QueryRow(context.Background(), insertCustomerQuery, email, customerPlan, paymentStatus, paymentSource, numberOfDataFeeds, name).Scan(&customerID)
  1401  	if err != nil {
  1402  		return fmt.Errorf("unable to insert customer: %v", err)
  1403  	}
  1404  
  1405  	err = addWalletPublicKeys(tx, customerID, walletPublicKeys)
  1406  	if err != nil {
  1407  		return err
  1408  	}
  1409  
  1410  	err = tx.Commit(context.Background())
  1411  	if err != nil {
  1412  		return fmt.Errorf("unable to commit transaction: %v", err)
  1413  	}
  1414  
  1415  	return nil
  1416  }
  1417  
  1418  func (reldb *RelDB) UpdateCustomerPlan(ctx context.Context, customerID int, customerPlan int, paymentSource string, lastPayment string, payerAddress string) error {
  1419  
  1420  	ut, err := strconv.ParseInt(lastPayment, 10, 64)
  1421  	if err != nil {
  1422  		return err
  1423  	}
  1424  	lastPaymentts := time.Unix(ut, 0)
  1425  
  1426  	query := `
  1427          UPDATE customers
  1428          SET customer_plan = $1,
  1429              payment_source = $2,
  1430              last_payment = $3,
  1431  			payer_address = $5
  1432          WHERE customer_id = $4
  1433      `
  1434  	_, err = reldb.postgresClient.Exec(ctx, query, customerPlan, paymentSource, lastPaymentts, customerID, payerAddress)
  1435  	return err
  1436  }
  1437  
  1438  func addWalletPublicKeys(tx pgx.Tx, customerID int, walletPublicKeys []string) error {
  1439  	insertWalletKeyQuery := `
  1440          INSERT INTO wallet_public_keys (customer_id, public_key)
  1441          VALUES ($1, $2)`
  1442  
  1443  	for _, publicKey := range walletPublicKeys {
  1444  		_, err := tx.Exec(context.Background(), insertWalletKeyQuery, customerID, publicKey)
  1445  		if err != nil {
  1446  			return fmt.Errorf("unable to insert wallet public key: %v", err)
  1447  		}
  1448  	}
  1449  
  1450  	return nil
  1451  }
  1452  
  1453  func (reldb *RelDB) GetPlan(ctx context.Context, planID int) (*Plan, error) {
  1454  	var plan Plan
  1455  	query := `SELECT plan_id, plan_name, plan_description, plan_price, total_feeds,total_oracles
  1456  	       FROM plans
  1457  		   WHERE plan_id = $1`
  1458  	err := reldb.postgresClient.QueryRow(ctx, query, planID).Scan(
  1459  		&plan.PlanID,
  1460  		&plan.Name,
  1461  		&plan.Description,
  1462  		&plan.Price,
  1463  		&plan.TotalFeeds,
  1464  		&plan.TotalOracles,
  1465  	)
  1466  	if err != nil {
  1467  		return nil, err
  1468  	}
  1469  	return &plan, err
  1470  
  1471  }
  1472  
  1473  func (reldb *RelDB) GetPendingRequestByPublicKey(owner string) (pk []PublicKey, err error) {
  1474  
  1475  	query := `
  1476  		SELECT customer_id, access_level,username
  1477  		FROM wallet_public_keys_temp
  1478  		WHERE public_key = $1
  1479  	`
  1480  	rows, err := reldb.postgresClient.Query(context.Background(), query, owner)
  1481  	if err != nil {
  1482  		return nil, err
  1483  	}
  1484  	defer rows.Close()
  1485  
  1486  	var username sql.NullString
  1487  
  1488  	for rows.Next() {
  1489  		var publicKey PublicKey
  1490  		if err := rows.Scan(&publicKey.CustomerId, &publicKey.AccessLevel, &username); err != nil {
  1491  			return nil, err
  1492  		}
  1493  		if username.Valid {
  1494  			publicKey.UserName = username.String
  1495  		}
  1496  		pk = append(pk, publicKey)
  1497  	}
  1498  	return
  1499  
  1500  }
  1501  
  1502  func (reldb *RelDB) GetPendingInvites(ctx context.Context, publicKeyAddress string) (pk []PublicKey, err error) {
  1503  
  1504  	query := `
  1505  	SELECT customer_id, access_level,username,invitor
  1506  	FROM wallet_public_keys_temp
  1507  	WHERE public_key = $1
  1508  `
  1509  	rows, err := reldb.postgresClient.Query(ctx, query, publicKeyAddress)
  1510  	if err != nil {
  1511  		return nil, err
  1512  	}
  1513  	defer rows.Close()
  1514  
  1515  	var username sql.NullString
  1516  	var invitor sql.NullString
  1517  
  1518  	var customerId int
  1519  
  1520  	for rows.Next() {
  1521  		var publicKey PublicKey
  1522  		if err := rows.Scan(&customerId, &publicKey.AccessLevel, &username, &invitor); err != nil {
  1523  			return nil, err
  1524  		}
  1525  		if invitor.Valid {
  1526  			publicKey.Invitor = invitor.String
  1527  		}
  1528  		if username.Valid {
  1529  			publicKey.UserName = username.String
  1530  		}
  1531  		publicKey.CustomerId = strconv.Itoa(customerId)
  1532  		publicKey.PublicKey = publicKeyAddress
  1533  		pk = append(pk, publicKey)
  1534  	}
  1535  	return
  1536  
  1537  }
  1538  
  1539  func (reldb *RelDB) GetPendingPublicKeyByCustomer(ctx context.Context, customerId string) (pk []PublicKey, err error) {
  1540  
  1541  	query := `
  1542  		SELECT public_key, access_level,username
  1543  		FROM wallet_public_keys_temp
  1544  		WHERE customer_id = $1
  1545  	`
  1546  	rows, err := reldb.postgresClient.Query(ctx, query, customerId)
  1547  	if err != nil {
  1548  		return nil, err
  1549  	}
  1550  	defer rows.Close()
  1551  
  1552  	var username sql.NullString
  1553  
  1554  	for rows.Next() {
  1555  		var publicKey PublicKey
  1556  		if err := rows.Scan(&publicKey.PublicKey, &publicKey.AccessLevel, &username); err != nil {
  1557  			return nil, err
  1558  		}
  1559  		if username.Valid {
  1560  			publicKey.UserName = username.String
  1561  		}
  1562  		pk = append(pk, publicKey)
  1563  	}
  1564  	return
  1565  
  1566  }
  1567  
  1568  func (reldb *RelDB) GetCustomerByPublicKey(publicKey string) (*Customer, error) {
  1569  	var customer Customer
  1570  	query := `
  1571  		SELECT c.customer_id, c.email, c.account_creation_date, c.customer_plan, c.deployed_oracles,
  1572  		       c.payment_status, c.payment_source, c.number_of_data_feeds, c.active,c.payer_address
  1573  		FROM customers c
  1574  		INNER JOIN wallet_public_keys wpk ON c.customer_id = wpk.customer_id
  1575  		WHERE wpk.public_key = $1
  1576  	`
  1577  	var (
  1578  		emailSql         sql.NullString
  1579  		customerPlanSql  sql.NullInt16
  1580  		paymentStatusSql sql.NullString
  1581  		paymentSourceSql sql.NullString
  1582  		payerAddress     sql.NullString
  1583  	)
  1584  	err := reldb.postgresClient.QueryRow(context.Background(), query, publicKey).Scan(
  1585  		&customer.CustomerID,
  1586  		&emailSql,
  1587  		&customer.AccountCreationDate,
  1588  		&customerPlanSql,
  1589  		&customer.DeployedOracles,
  1590  		&paymentStatusSql,
  1591  		// &customer.LastPayment,
  1592  		&paymentSourceSql,
  1593  		&customer.NumberOfDataFeeds,
  1594  		&customer.Active,
  1595  		&payerAddress,
  1596  	)
  1597  	if err != nil {
  1598  		return nil, err
  1599  	}
  1600  	query = `
  1601  		SELECT public_key, access_level,username
  1602  		FROM wallet_public_keys
  1603  		WHERE customer_id = $1
  1604  	`
  1605  	rows, err := reldb.postgresClient.Query(context.Background(), query, customer.CustomerID)
  1606  	if err != nil {
  1607  		return nil, err
  1608  	}
  1609  	defer rows.Close()
  1610  
  1611  	var username sql.NullString
  1612  
  1613  	for rows.Next() {
  1614  		var publicKey PublicKey
  1615  		if err := rows.Scan(&publicKey.PublicKey, &publicKey.AccessLevel, &username); err != nil {
  1616  			return nil, err
  1617  		}
  1618  		if username.Valid {
  1619  			publicKey.UserName = username.String
  1620  		}
  1621  		customer.PublicKeys = append(customer.PublicKeys, publicKey)
  1622  	}
  1623  
  1624  	if emailSql.Valid {
  1625  		customer.Email = emailSql.String
  1626  	}
  1627  	if payerAddress.Valid {
  1628  		customer.PayerAddress = payerAddress.String
  1629  	}
  1630  	if paymentStatusSql.Valid {
  1631  		customer.PaymentStatus = paymentStatusSql.String
  1632  	}
  1633  	if customerPlanSql.Valid {
  1634  		customer.CustomerPlan = int(customerPlanSql.Int16)
  1635  	}
  1636  	if paymentSourceSql.Valid {
  1637  		customer.PaymentSource = paymentSourceSql.String
  1638  	}
  1639  
  1640  	if rows.Err() != nil {
  1641  		return nil, rows.Err()
  1642  	}
  1643  	return &customer, nil
  1644  }
  1645  
  1646  func (reldb *RelDB) GetAccessLevel(publicKey string) (string, error) {
  1647  	var accessLevel string
  1648  	err := reldb.postgresClient.QueryRow(context.Background(), `
  1649  		SELECT access_level
  1650  		FROM wallet_public_keys
  1651  		WHERE public_key = $1
  1652  	`, publicKey).Scan(&accessLevel)
  1653  
  1654  	if err != nil {
  1655  		return "", err
  1656  	}
  1657  	return accessLevel, nil
  1658  
  1659  }