package walletsettings import ( "database/sql" "errors" ) type TokenPreferences struct { Key string `json:"key"` Position int `json:"position"` GroupPosition int `json:"groupPosition"` Visible bool `json:"visible"` CommunityID string `json:"communityId"` } type WalletSettings struct { db *sql.DB } func NewWalletSettings(db *sql.DB) *WalletSettings { return &WalletSettings{ db: db, } } // This function should not be used directly, it is called from the functions which update token preferences. func (ws *WalletSettings) setClockOfLastTokenPreferencesChange(tx *sql.Tx, clock uint64) error { if tx == nil { return errors.New("database transaction is nil") } _, err := tx.Exec("UPDATE settings SET wallet_token_preferences_change_clock = ? WHERE synthetic_id = 'id'", clock) return err } func (ws *WalletSettings) GetClockOfLastTokenPreferencesChange() (result uint64, err error) { query := "SELECT wallet_token_preferences_change_clock FROM settings WHERE synthetic_id = 'id'" err = ws.db.QueryRow(query).Scan(&result) if err != nil { return 0, err } return result, err } func (ws *WalletSettings) UpdateTokenPreferences(preferences []TokenPreferences, groupByCommunity bool, testNetworksEnabled bool, clock uint64) error { if len(preferences) == 0 { return errors.New("tokens: trying to create custom order with empty list") } tx, err := ws.db.Begin() if err != nil { return err } var mainError error = nil defer func() { if mainError == nil { err = tx.Commit() return } _ = tx.Rollback() }() _, mainError = tx.Exec("DELETE FROM token_preferences WHERE testnet = ?", testNetworksEnabled) if mainError != nil { return mainError } for _, p := range preferences { if p.Position < 0 { mainError = errors.New("tokens: trying to create custom order with negative position") return mainError } _, 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) if err != nil { mainError = err return err } } if groupByCommunity { // Find community tokens without group position // Group position can be -1 if it wasn't created yet. Values must be consitstent across all tokens 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) if err != nil { mainError = err return err } if rows.Next() { mainError = errors.New("tokens: not all community tokens have assigned the group position") return mainError } } mainError = ws.setClockOfLastTokenPreferencesChange(tx, clock) if mainError != nil { return mainError } return nil } func (ws *WalletSettings) GetTokenPreferences(testNetworksEnabled bool) ([]TokenPreferences, error) { rows, err := ws.db.Query("SELECT key, position, group_position, visible, community_id FROM token_preferences WHERE testnet = ?", testNetworksEnabled) if err != nil { return nil, err } defer rows.Close() var result []TokenPreferences for rows.Next() { token := TokenPreferences{} err := rows.Scan(&token.Key, &token.Position, &token.GroupPosition, &token.Visible, &token.CommunityID) if err != nil { return nil, err } result = append(result, token) } if err := rows.Err(); err != nil { return nil, err } return result, nil }