github.com/status-im/status-go@v1.1.0/protocol/ens/persistence.go (about)

     1  package ens
     2  
     3  import (
     4  	"context"
     5  	"database/sql"
     6  	"errors"
     7  )
     8  
     9  type Persistence struct {
    10  	db *sql.DB
    11  }
    12  
    13  func NewPersistence(db *sql.DB) *Persistence {
    14  	return &Persistence{db: db}
    15  }
    16  
    17  func (p *Persistence) GetENSToBeVerified(now uint64) ([]*VerificationRecord, error) {
    18  	rows, err := p.db.Query(`SELECT public_key, name, verified, verified_at, clock, verification_retries, next_retry FROM ens_verification_records WHERE NOT(verified) AND verification_retries < ? AND next_retry <= ?`, maxRetries, now)
    19  	if err != nil {
    20  		return nil, err
    21  	}
    22  
    23  	var records []*VerificationRecord
    24  	for rows.Next() {
    25  		var record VerificationRecord
    26  		err := rows.Scan(&record.PublicKey, &record.Name, &record.Verified, &record.VerifiedAt, &record.Clock, &record.VerificationRetries, &record.NextRetry)
    27  		if err != nil {
    28  			return nil, err
    29  		}
    30  		records = append(records, &record)
    31  	}
    32  
    33  	return records, nil
    34  }
    35  
    36  func (p *Persistence) UpdateRecords(records []*VerificationRecord) (err error) {
    37  	var tx *sql.Tx
    38  	tx, err = p.db.BeginTx(context.Background(), &sql.TxOptions{})
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	defer func() {
    44  		if err == nil {
    45  			err = tx.Commit()
    46  			return
    47  		}
    48  		// don't shadow original error
    49  		_ = tx.Rollback()
    50  	}()
    51  
    52  	for _, record := range records {
    53  		var stmt *sql.Stmt
    54  		stmt, err = tx.Prepare(`UPDATE ens_verification_records SET verified = ?, verified_at = ?, verification_retries = ?, next_retry = ? WHERE public_key = ?`)
    55  		if err != nil {
    56  			return err
    57  		}
    58  		defer stmt.Close()
    59  		_, err = stmt.Exec(record.Verified, record.VerifiedAt, record.VerificationRetries, record.NextRetry, record.PublicKey)
    60  		if err != nil {
    61  			return err
    62  		}
    63  
    64  	}
    65  
    66  	return nil
    67  }
    68  
    69  // AddRecord adds a record or return the latest available if already in the database and
    70  // hasn't changed
    71  func (p *Persistence) AddRecord(record VerificationRecord) (response *VerificationRecord, err error) {
    72  	if !record.Valid() {
    73  		err = errors.New("invalid ens record")
    74  		return
    75  	}
    76  	var tx *sql.Tx
    77  	tx, err = p.db.BeginTx(context.Background(), &sql.TxOptions{})
    78  	if err != nil {
    79  		return
    80  	}
    81  
    82  	defer func() {
    83  		if err == nil {
    84  			err = tx.Commit()
    85  			return
    86  		}
    87  		// don't shadow original error
    88  		_ = tx.Rollback()
    89  	}()
    90  
    91  	dbRecord := &VerificationRecord{PublicKey: record.PublicKey}
    92  
    93  	err = tx.QueryRow(`SELECT name, clock, verified FROM ens_verification_records WHERE public_key = ?`, record.PublicKey).Scan(&dbRecord.Name, &dbRecord.Clock, &dbRecord.Verified)
    94  	if err != nil && err != sql.ErrNoRows {
    95  		return
    96  	}
    97  
    98  	if dbRecord.Clock >= record.Clock || dbRecord.Name == record.Name {
    99  		response = dbRecord
   100  		return
   101  	}
   102  
   103  	_, err = tx.Exec(`INSERT INTO ens_verification_records(public_key, name, clock) VALUES (?,?,?)`, record.PublicKey, record.Name, record.Clock)
   104  	return
   105  }
   106  
   107  func (p *Persistence) GetVerifiedRecord(publicKey string) (*VerificationRecord, error) {
   108  	record := &VerificationRecord{}
   109  	err := p.db.QueryRow(`SELECT name, clock FROM ens_verification_records WHERE verified AND public_key =  ?`, publicKey).Scan(&record.Name, &record.Clock)
   110  	switch err {
   111  	case sql.ErrNoRows:
   112  		return nil, nil
   113  	case nil:
   114  		return record, nil
   115  	}
   116  
   117  	return nil, err
   118  
   119  }