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 }