github.com/status-im/status-go@v1.1.0/multiaccounts/settings_wallet/database.go (about)

     1  package walletsettings
     2  
     3  import (
     4  	"database/sql"
     5  	"errors"
     6  )
     7  
     8  type TokenPreferences struct {
     9  	Key           string `json:"key"`
    10  	Position      int    `json:"position"`
    11  	GroupPosition int    `json:"groupPosition"`
    12  	Visible       bool   `json:"visible"`
    13  	CommunityID   string `json:"communityId"`
    14  }
    15  
    16  type CollectiblePreferencesType int
    17  
    18  const (
    19  	CollectiblePreferencesTypeNonCommunityCollectible CollectiblePreferencesType = iota + 1
    20  	CollectiblePreferencesTypeCommunityCollectible
    21  	CollectiblePreferencesTypeCollection
    22  	CollectiblePreferencesTypeCommunity
    23  )
    24  
    25  type CollectiblePreferences struct {
    26  	Type     CollectiblePreferencesType `json:"type"`
    27  	Key      string                     `json:"key"`
    28  	Position int                        `json:"position"`
    29  	Visible  bool                       `json:"visible"`
    30  }
    31  
    32  type WalletSettings struct {
    33  	db *sql.DB
    34  }
    35  
    36  func NewWalletSettings(db *sql.DB) *WalletSettings {
    37  	return &WalletSettings{
    38  		db: db,
    39  	}
    40  }
    41  
    42  // This function should not be used directly, it is called from the functions which update token preferences.
    43  func (ws *WalletSettings) setClockOfLastTokenPreferencesChange(tx *sql.Tx, clock uint64) error {
    44  	if tx == nil {
    45  		return errors.New("database transaction is nil")
    46  	}
    47  	_, err := tx.Exec("UPDATE settings SET wallet_token_preferences_change_clock = ? WHERE synthetic_id = 'id'", clock)
    48  	return err
    49  }
    50  
    51  func (ws *WalletSettings) GetClockOfLastTokenPreferencesChange() (result uint64, err error) {
    52  	query := "SELECT wallet_token_preferences_change_clock FROM settings WHERE synthetic_id = 'id'"
    53  	err = ws.db.QueryRow(query).Scan(&result)
    54  	if err != nil {
    55  		return 0, err
    56  	}
    57  	return result, err
    58  }
    59  
    60  func (ws *WalletSettings) UpdateTokenPreferences(preferences []TokenPreferences, groupByCommunity bool, testNetworksEnabled bool, clock uint64) error {
    61  	if len(preferences) == 0 {
    62  		return errors.New("tokens: trying to create custom order with empty list")
    63  	}
    64  
    65  	tx, err := ws.db.Begin()
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	var mainError error = nil
    71  
    72  	defer func() {
    73  		if mainError == nil {
    74  			err = tx.Commit()
    75  			return
    76  		}
    77  		_ = tx.Rollback()
    78  	}()
    79  
    80  	_, mainError = tx.Exec("DELETE FROM token_preferences WHERE testnet = ?", testNetworksEnabled)
    81  	if mainError != nil {
    82  		return mainError
    83  	}
    84  
    85  	for _, p := range preferences {
    86  		if p.Position < 0 {
    87  			mainError = errors.New("tokens: trying to create custom order with negative position")
    88  			return mainError
    89  		}
    90  		_, err := tx.Exec("INSERT INTO token_preferences (key, position, group_position, visible, community_id, testnet) VALUES (?, ?, ?, ?, ?, ?)", p.Key, p.Position, p.GroupPosition, p.Visible, p.CommunityID, testNetworksEnabled)
    91  		if err != nil {
    92  			mainError = err
    93  			return err
    94  		}
    95  	}
    96  
    97  	if groupByCommunity {
    98  		// Find community tokens without group position
    99  		// Group position can be -1 if it wasn't created yet. Values must be consitstent across all tokens
   100  		rows, err := tx.Query(`SELECT COUNT(*) FROM token_preferences WHERE testnet = ? AND group_position = -1 AND community_id != '' AND visible GROUP BY community_id HAVING COUNT(*) > 0`, testNetworksEnabled)
   101  		if err != nil {
   102  			mainError = err
   103  			return err
   104  		}
   105  		if rows.Next() {
   106  			mainError = errors.New("tokens: not all community tokens have assigned the group position")
   107  			return mainError
   108  		}
   109  	}
   110  
   111  	mainError = ws.setClockOfLastTokenPreferencesChange(tx, clock)
   112  	if mainError != nil {
   113  		return mainError
   114  	}
   115  	return nil
   116  }
   117  
   118  func (ws *WalletSettings) GetTokenPreferences(testNetworksEnabled bool) ([]TokenPreferences, error) {
   119  	rows, err := ws.db.Query("SELECT key, position, group_position, visible, community_id FROM token_preferences WHERE testnet = ?", testNetworksEnabled)
   120  	if err != nil {
   121  		return nil, err
   122  	}
   123  	defer rows.Close()
   124  
   125  	var result []TokenPreferences
   126  
   127  	for rows.Next() {
   128  		token := TokenPreferences{}
   129  		err := rows.Scan(&token.Key, &token.Position, &token.GroupPosition, &token.Visible, &token.CommunityID)
   130  		if err != nil {
   131  			return nil, err
   132  		}
   133  
   134  		result = append(result, token)
   135  	}
   136  
   137  	if err := rows.Err(); err != nil {
   138  		return nil, err
   139  	}
   140  
   141  	return result, nil
   142  }
   143  
   144  func (ws *WalletSettings) setClockOfLastCollectiblePreferencesChange(tx *sql.Tx, clock uint64) error {
   145  	if tx == nil {
   146  		return errors.New("database transaction is nil")
   147  	}
   148  	_, err := tx.Exec("UPDATE settings SET wallet_collectible_preferences_change_clock = ? WHERE synthetic_id = 'id'", clock)
   149  	return err
   150  }
   151  
   152  func (ws *WalletSettings) GetClockOfLastCollectiblePreferencesChange() (result uint64, err error) {
   153  	query := "SELECT wallet_collectible_preferences_change_clock FROM settings WHERE synthetic_id = 'id'"
   154  	err = ws.db.QueryRow(query).Scan(&result)
   155  	if err != nil {
   156  		return 0, err
   157  	}
   158  	return result, err
   159  }
   160  
   161  func (ws *WalletSettings) UpdateCollectiblePreferences(preferences []CollectiblePreferences, groupByCommunity bool, groupByCollection bool, testNetworksEnabled bool, clock uint64) error {
   162  	if len(preferences) == 0 {
   163  		return errors.New("collectibles: trying to create custom order with empty list")
   164  	}
   165  
   166  	tx, err := ws.db.Begin()
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	var mainError error = nil
   172  
   173  	defer func() {
   174  		if mainError == nil {
   175  			err = tx.Commit()
   176  			return
   177  		}
   178  		_ = tx.Rollback()
   179  	}()
   180  
   181  	_, mainError = tx.Exec("DELETE FROM collectible_preferences WHERE testnet = ?", testNetworksEnabled)
   182  	if mainError != nil {
   183  		return mainError
   184  	}
   185  
   186  	for _, p := range preferences {
   187  		if p.Position < 0 {
   188  			mainError = errors.New("collectibles: trying to create custom order with negative position")
   189  			return mainError
   190  		}
   191  		_, err := tx.Exec("INSERT INTO collectible_preferences (type, key, position, visible, testnet) VALUES (?, ?, ?, ?, ?)", p.Type, p.Key, p.Position, p.Visible, testNetworksEnabled)
   192  		if err != nil {
   193  			mainError = err
   194  			return err
   195  		}
   196  	}
   197  
   198  	mainError = ws.setClockOfLastCollectiblePreferencesChange(tx, clock)
   199  	if mainError != nil {
   200  		return mainError
   201  	}
   202  	return nil
   203  }
   204  
   205  func (ws *WalletSettings) GetCollectiblePreferences(testNetworksEnabled bool) ([]CollectiblePreferences, error) {
   206  	rows, err := ws.db.Query("SELECT type, key, position, visible FROM collectible_preferences WHERE testnet = ?", testNetworksEnabled)
   207  	if err != nil {
   208  		return nil, err
   209  	}
   210  	defer rows.Close()
   211  
   212  	var result []CollectiblePreferences
   213  
   214  	for rows.Next() {
   215  		p := CollectiblePreferences{}
   216  		err := rows.Scan(&p.Type, &p.Key, &p.Position, &p.Visible)
   217  		if err != nil {
   218  			return nil, err
   219  		}
   220  
   221  		result = append(result, p)
   222  	}
   223  
   224  	if err := rows.Err(); err != nil {
   225  		return nil, err
   226  	}
   227  
   228  	return result, nil
   229  }