diff --git a/appdatabase/migrations/bindata.go b/appdatabase/migrations/bindata.go index 2bf7de640..98038c088 100644 --- a/appdatabase/migrations/bindata.go +++ b/appdatabase/migrations/bindata.go @@ -1,7 +1,7 @@ // Code generated by go-bindata. DO NOT EDIT. // sources: // 0001_app.down.sql (387B) -// 0001_app.up.sql (2.951kB) +// 0001_app.up.sql (3.088kB) // 0002_tokens.down.sql (19B) // 0002_tokens.up.sql (248B) // doc.go (74B) @@ -93,7 +93,7 @@ func _0001_appDownSql() (*asset, error) { return a, nil } -var __0001_appUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\x4d\x93\xaa\x38\x14\xdd\xf3\x2b\xb2\xb4\xab\xd8\xcc\xfa\xad\x50\xa3\x4d\x0d\x03\x33\x88\xd3\xfd\x56\xa9\x34\x44\x4c\x35\x10\x5e\x12\xdb\xf6\xdf\x4f\xe5\x0b\x50\x01\xbb\xe7\xed\x48\xee\xc9\xf5\x9c\x73\x6f\x6e\x5c\xa5\x30\xc8\x20\xc8\x82\x65\x04\x41\xb8\x01\x71\x92\x01\xf8\x1a\xee\xb2\x1d\x10\x44\x4a\xda\x94\x02\x2c\x3c\x79\x69\x09\xf8\x37\x48\x57\xcf\x41\x0a\xfe\x4e\xc3\xbf\x82\xf4\x27\xf8\x13\xfe\xf4\xbd\x0f\x5c\x9d\x08\x58\x46\xc9\xd2\x7b\x02\x2f\x61\xf6\x9c\xec\x33\x90\x26\x2f\xe1\xfa\x87\xe7\xcd\x24\xc7\x79\xce\x4e\x8d\x54\xc9\x71\x51\x70\x22\xc4\x78\xfe\x33\xae\x2a\x22\xc1\x32\x49\x22\x18\xc4\xbe\x97\x1f\xf1\x60\xa5\x79\x65\xf0\x35\xf3\x3d\x21\x19\xc7\xa5\x5b\xb5\xa7\xb7\x77\x72\xd1\xbc\x7c\xaf\xc5\xf2\x68\xf7\x1b\x5c\x3b\x48\xce\x2a\xc6\xf5\xf7\x34\xf3\x7d\x1c\xfe\xb3\x87\x20\x8c\xd7\xf0\x15\x9c\x1a\xfa\xeb\x44\x90\x61\x84\x1c\xeb\x24\x1e\x68\x31\xb1\x27\xf0\xf2\x0c\x53\xd8\x2d\x7f\xcc\xa5\x53\x82\xc6\x93\xa9\x48\x97\x4a\x2f\xe6\x2d\x7d\xe3\xec\x2c\x08\x57\x96\xd2\x42\x0b\xbb\xb6\xb2\xd3\xae\x0f\xc5\xfb\x28\xf2\x3d\x49\x6b\x22\x24\xae\x5b\xb0\xdf\x6d\xc3\x6d\x0c\xd7\x60\x19\x6e\xc3\x38\xf3\xbd\x02\xb7\xad\x73\x1a\xac\xe1\x26\xd8\x47\x19\x38\xe0\x4a\x10\xdf\x3b\x52\x65\xf7\x25\x6c\x0a\xf2\x09\xf6\xf1\xce\x9c\x0c\xe3\x19\x2b\xe7\x18\x23\x9b\x0f\x2c\x3c\xbb\x85\x9c\x82\x9e\xaa\xc3\x98\xea\x6d\x92\x14\x86\xdb\x58\x29\x5b\xf4\x67\x9e\x40\x0a\x37\x30\x85\xf1\x0a\xf6\xd9\x17\x6a\x3f\x51\x1a\x22\x98\x41\xb0\x0a\x76\xab\x60\x0d\xbd\x07\x6e\x2a\xf9\xca\xca\xde\xb5\x81\x99\xdf\x93\xd9\x12\x5e\x53\x21\x28\x6b\x54\x42\x95\x18\x8d\xd5\xa2\x87\xdd\x46\x86\x62\xbb\xe3\x57\x5a\x35\xdb\x85\xd9\x1e\x97\x3a\x47\x50\x72\xdc\x88\x83\x69\x9d\x86\xc8\x33\xe3\xef\xaa\x00\x5d\x61\x4d\x4b\x0c\x6b\x81\xc5\xb1\xbb\xaf\xfd\xf6\xed\x4d\xee\x23\x6f\xd5\x3b\x9a\x38\x24\x3f\xed\x35\x15\xa4\x29\x08\x1f\x41\x70\x92\x13\xda\x4a\x0b\xab\x58\x69\xbf\xae\xa6\xd2\xb8\x5b\xbd\x1a\xdf\x51\xb8\xee\x91\x8a\xe5\xef\x62\x08\x33\x90\x3b\x0f\x7d\x6f\x95\xc4\xbb\x2c\x0d\x94\x11\xf6\xea\x3a\xdb\x50\x4b\xb8\xbb\xc2\xfa\xdb\xa6\x73\xf7\x7d\xa1\x72\xfa\x16\xe0\xf7\xbf\xf5\xf4\xa8\x07\x0d\xbb\xdf\x2c\x4a\x73\xaa\xdf\x08\xbf\x87\x0f\xae\xfe\x74\x4a\x82\x0b\x3d\x03\xba\x01\xb0\x09\xa2\xdd\xa8\x19\x9a\xeb\xa8\xfa\x5b\x73\x27\x0f\x1b\xa6\x8f\x72\x18\xd4\x43\xef\xdc\x1c\x45\x92\xa1\xef\xf9\x38\xdf\xc5\x53\x76\x8a\x4b\x93\x03\x3d\x38\x67\xfa\xcf\x72\x9f\xef\x40\x07\xfa\x52\x0f\xd6\xb8\x6d\x69\x53\xa2\x03\xe3\xc8\x4a\xee\x14\x8f\x3a\xe9\xda\xb0\xa7\xf3\x9d\x8e\xac\x31\xad\x04\xe1\x1f\x66\x56\x00\x00\x00\x2d\xc6\x1f\x6e\x15\xd3\x53\xee\xde\x46\x15\x9a\x36\x59\x45\x5b\x2c\xc4\x99\xf1\x2e\xb5\xd9\x3d\x54\x84\xc8\xbb\x13\xdf\x9b\xc5\xbd\x00\xc4\xc9\xaf\x13\x11\x12\x95\xb8\x75\x62\x4a\xdc\xa2\x03\x67\xf5\xd5\x9b\x06\xb7\xf0\x96\x9f\xc2\x49\xf6\x08\x35\xfa\x0a\xab\x80\x7e\xf3\x6f\x5f\xb8\x69\x1d\xe6\xff\xc2\x04\x73\x64\x93\x21\x5a\x7c\xaa\x96\x99\x14\x68\x71\x5f\x2e\x30\x92\xac\xa5\xb9\x73\x46\x2f\xa6\x2b\x6d\x93\x8b\xeb\x82\x55\x58\x48\xc7\xa2\xf3\xc8\x4d\x92\x3f\x0c\xa6\xa0\x22\x67\x1f\x84\x5f\xee\xfe\x6b\xd8\x51\xa3\x1b\x89\x94\x4c\x52\x2c\x49\x31\x8e\xfa\xdf\x3d\xa0\x79\x3b\x9f\x38\x6e\x4a\xe2\x04\xbb\x1a\x4d\x4a\xae\xd8\x99\xf4\xf2\x4c\xdb\x58\x8d\x06\x70\xa4\xe5\x71\x88\x90\xcc\xc5\xef\xe9\xfe\x17\x00\x00\xff\xff\xbe\x1f\x2a\xc2\x87\x0b\x00\x00") +var __0001_appUpSql = []byte("\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\xff\xa4\x56\xc1\x92\xaa\x38\x14\xdd\xf3\x15\x59\xda\x55\x6c\x66\xfd\x56\xa8\xd1\xa6\xc6\x07\x33\x88\xd3\xfd\x56\xa9\x34\x44\x4c\x09\x24\x2f\x09\x6d\xfb\xf7\x53\x21\x09\xa0\x82\xb6\x33\x3b\x92\x7b\x73\x3c\xe7\xdc\xeb\x4d\x16\x09\x0c\x52\x08\xd2\x60\xbe\x81\x20\x5c\x81\x28\x4e\x01\x7c\x0f\xb7\xe9\x16\x48\xa2\x14\xad\x0b\x09\x66\x9e\x3a\x73\x02\xfe\x09\x92\xc5\x6b\x90\x80\xbf\x92\xf0\x67\x90\xfc\x02\x7f\xc2\x5f\xbe\xf7\x89\xcb\x86\x80\xf9\x26\x9e\x7b\x2f\xe0\x2d\x4c\x5f\xe3\x5d\x0a\x92\xf8\x2d\x5c\xfe\xf0\xbc\x3b\xe0\x38\xcb\x58\x53\x2b\x0d\x8e\xf3\x5c\x10\x29\xc7\xf1\x4f\xb8\x2c\x89\x02\xf3\x38\xde\xc0\x20\xf2\xbd\xec\x80\x07\xab\x96\x57\x0a\xdf\x53\xdf\x93\x8a\x09\x5c\xb8\x15\x6f\x3e\x8e\xe4\xdc\xf2\xf2\x3d\x8e\xd5\xc1\xee\xd7\xb8\x72\x29\x19\x2b\x99\x70\xdf\x82\x60\x45\x72\x84\x15\x58\x06\x29\x4c\xc3\x9f\xb0\x25\x1b\xed\x36\x1b\xdf\x6b\x78\x3e\x19\x9d\x56\xbd\x8b\xc2\xbf\x77\x10\x84\xd1\x12\xbe\x83\xa6\xa6\xbf\x1b\x82\x8c\x1a\xe4\x14\xc7\xd1\xc0\x07\x13\x7b\x01\x6f\xaf\x30\x81\xdd\xf2\xc7\x3d\x38\x6d\xc6\x38\x98\x8e\x74\x50\xed\xa2\x03\x32\x08\xbd\x62\x64\x4f\x5d\x01\x74\xf1\x1e\xa6\xdf\xba\x5f\xdb\x0f\xc1\x4e\x92\x08\x5d\x5b\x9a\xb7\x0e\x5f\xd6\xb4\x2b\xc2\xc0\x63\x45\x2b\x22\x15\xae\x38\xd8\x6d\xd7\xe1\x3a\x82\x4b\x30\x0f\xd7\x61\x94\xfa\x5e\x8e\x39\x77\x25\x07\x4b\xb8\x0a\x76\x9b\x14\xec\x71\x29\x89\xef\x1d\xa8\xae\xfb\x39\xac\x73\xf2\x05\x76\xd1\xd6\x9c\x0c\xa3\xf4\xb9\x6e\x74\x8c\x91\xc5\x03\x33\xcf\x6e\x21\xa7\xa0\xa7\xea\x72\x4c\xeb\xac\xe2\x04\x86\xeb\x48\x2b\x9b\xf5\x67\x5e\x40\x02\x57\x30\x81\xd1\x02\xf6\xe8\x33\xbd\x1f\x6b\x0d\x1b\x98\x42\xb0\x08\xb6\x8b\x60\x09\xbd\x07\x6e\x6a\xf9\xda\xca\xde\xb5\x81\x99\xcf\xc9\xe4\x44\x54\x54\x4a\xca\x6a\x0d\xa8\x81\xd1\x58\x2d\xfa\xb4\xeb\xc8\x50\x6c\x77\xfc\x42\x6b\xcb\x76\x66\xb6\xc7\xa5\xde\x23\xa8\x04\xae\xe5\xde\xb4\x4e\x4d\xd4\x89\x89\xa3\x2e\x40\x57\x58\xd3\x12\xc3\x5a\x60\x79\xe8\x06\x47\xbf\x7d\x3d\x52\xfa\xc8\x47\x79\x44\x13\x87\xd4\x97\x9d\x17\x92\xd4\x39\x11\x23\x19\x82\x64\x84\x72\x65\xd3\x4a\x56\xd8\xaf\x8b\xf1\x38\xee\x56\xaf\xc6\x77\x14\x2e\x7b\xa4\x64\xd9\x51\x0e\xd3\x4c\xca\x8d\x87\xbe\xb7\x88\xa3\x6d\x9a\x04\xda\x08\x3b\x07\x9c\x6d\x88\x13\xe1\xe6\x41\xfb\x6d\xe1\xdc\xf0\x98\x69\x4c\xdf\x26\xf8\xfd\x6f\xbd\x3c\xea\x41\xc3\xee\x7f\x16\xa5\x6e\xaa\x0f\x22\x6e\xd3\x07\x7f\xfd\x69\x48\x82\xf3\x76\x06\x74\x03\x60\x15\x6c\xb6\xa3\x66\xb4\x5c\x47\xd5\x5f\x9b\x3b\x79\xd8\x30\x7d\x84\x61\xb2\x1e\x7a\xe7\x66\x2a\x52\x0c\x3d\xe7\xe3\xfd\x2e\x9e\xb2\x53\x9e\xeb\x0c\xb4\x83\xf3\x4e\xff\x59\xee\xf7\x3b\xd0\x25\x7d\xab\x07\x2b\xcc\x39\xad\x0b\xb4\x67\xc2\xdd\x28\x9d\xe2\x51\x27\x5d\x1b\xf6\x74\x9e\xe9\xc8\x0a\xd3\x52\x12\xf1\x69\x66\x05\x00\x00\xd0\x7c\xfc\x05\xa1\x63\xed\x94\xbb\xb5\x51\x87\xa6\x4d\xd6\x51\x8e\xa5\x3c\x31\xd1\x41\x9b\xdd\x7d\x49\x88\xba\x39\xf1\xdc\x2c\xee\x05\x20\x41\x7e\x37\x44\x2a\x54\x60\xee\xc4\x14\x98\xa3\xbd\x60\xd5\xc5\x9d\x06\xd7\xf0\x9a\x9f\xce\x53\xec\x51\xd6\xe8\x2d\xac\x03\xed\x03\xe2\xfa\x86\x9b\xd6\x61\x9e\x0e\x13\xcc\x91\x05\x43\x34\xff\xd2\x2d\x33\x29\xd0\xe6\x7d\xbb\xc0\x48\x31\x4e\x33\xe7\x4c\xbb\x98\xae\xb4\x05\x97\x97\x05\x2b\xb1\x54\x8e\x45\xe7\x91\x9b\x24\x7f\x98\x9c\x9c\xca\x8c\x7d\x12\x71\xbe\x79\x6b\xd8\x51\xd3\x36\x12\x29\x98\xa2\xfa\x19\x34\x9e\xf5\x9f\x7b\xa0\xe5\xed\x7c\x12\xb8\x2e\x88\x13\xec\x6a\x34\x29\xb9\x64\x27\xd2\xcb\x33\x6d\x63\x35\x9a\x84\x03\x2d\x0e\xc3\x0c\xc5\x5c\xfc\x96\xee\xbf\x01\x00\x00\xff\xff\x5a\xea\xe5\xa6\x10\x0c\x00\x00") func _0001_appUpSqlBytes() ([]byte, error) { return bindataRead( @@ -108,8 +108,8 @@ func _0001_appUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0001_app.up.sql", size: 2951, mode: os.FileMode(0644), modTime: time.Unix(1575989917, 0)} - a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xb4, 0x2, 0xd5, 0x91, 0xff, 0x5f, 0x8f, 0xb0, 0xe8, 0x19, 0x84, 0xd1, 0xa5, 0xd5, 0xec, 0xa5, 0x4, 0x1d, 0x4c, 0x5c, 0xb5, 0xd3, 0xde, 0x36, 0xd8, 0xa6, 0x98, 0x69, 0xee, 0xfa, 0x10, 0x97}} + info := bindataFileInfo{name: "0001_app.up.sql", size: 3088, mode: os.FileMode(0644), modTime: time.Unix(1576507278, 0)} + a := &asset{bytes: bytes, info: info, digest: [32]uint8{0x93, 0xb8, 0x68, 0x17, 0x49, 0x51, 0xc0, 0xe8, 0xbc, 0x36, 0xa4, 0x29, 0xc9, 0x93, 0x6c, 0x3e, 0xdf, 0x3d, 0x23, 0x22, 0xab, 0x18, 0x49, 0xbd, 0x6, 0xf, 0xc5, 0xec, 0xf8, 0xcf, 0x1b, 0x6a}} return a, nil } @@ -128,7 +128,7 @@ func _0002_tokensDownSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(0644), modTime: time.Unix(1575992350, 0)} + info := bindataFileInfo{name: "0002_tokens.down.sql", size: 19, mode: os.FileMode(0644), modTime: time.Unix(1575999124, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xd1, 0x31, 0x2, 0xcc, 0x2f, 0x38, 0x90, 0xf7, 0x58, 0x37, 0x47, 0xf4, 0x18, 0xf7, 0x72, 0x74, 0x67, 0x14, 0x7e, 0xf3, 0xb1, 0xd6, 0x5f, 0xb0, 0xd5, 0xe7, 0x91, 0xf4, 0x26, 0x77, 0x8e, 0x68}} return a, nil } @@ -148,7 +148,7 @@ func _0002_tokensUpSql() (*asset, error) { return nil, err } - info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(0644), modTime: time.Unix(1575992350, 0)} + info := bindataFileInfo{name: "0002_tokens.up.sql", size: 248, mode: os.FileMode(0644), modTime: time.Unix(1575999124, 0)} a := &asset{bytes: bytes, info: info, digest: [32]uint8{0xcc, 0xd6, 0xde, 0xd3, 0x7b, 0xee, 0x92, 0x11, 0x38, 0xa4, 0xeb, 0x84, 0xca, 0xcb, 0x37, 0x75, 0x5, 0x77, 0x7f, 0x14, 0x39, 0xee, 0xa1, 0x8b, 0xd4, 0x5c, 0x6e, 0x55, 0x6, 0x50, 0x16, 0xd4}} return a, nil } diff --git a/appdatabase/migrations/sql/0001_app.up.sql b/appdatabase/migrations/sql/0001_app.up.sql index 9f8fd511d..7e2603a0b 100644 --- a/appdatabase/migrations/sql/0001_app.up.sql +++ b/appdatabase/migrations/sql/0001_app.up.sql @@ -12,11 +12,14 @@ storage TEXT, pubkey BLOB, path TEXT, name TEXT, -color TEXT +color TEXT, +created_at DATETIME NOT NULL, +updated_at DATETIME NOT NULL ) WITHOUT ROWID; CREATE UNIQUE INDEX unique_wallet_address ON accounts (wallet) WHERE (wallet); CREATE UNIQUE INDEX unique_chat_address ON accounts (chat) WHERE (chat); +CREATE INDEX created_at_account ON accounts (created_at) WHERE (created_at); CREATE TABLE IF NOT EXISTS browsers ( id TEXT PRIMARY KEY, diff --git a/multiaccounts/accounts/database.go b/multiaccounts/accounts/database.go index 4b6f50e05..1ce3fa1b4 100644 --- a/multiaccounts/accounts/database.go +++ b/multiaccounts/accounts/database.go @@ -28,10 +28,10 @@ type Account struct { Address common.Address `json:"address"` Wallet bool `json:"wallet"` Chat bool `json:"chat"` - Type string `json:"type"` - Storage string `json:"storage"` - Path string `json:"path"` - PublicKey hexutil.Bytes `json:"publicKey"` + Type string `json:"type,omitempty"` + Storage string `json:"storage,omitempty"` + Path string `json:"path,omitempty"` + PublicKey hexutil.Bytes `json:"public-key,omitempty"` Name string `json:"name"` Color string `json:"color"` } @@ -91,7 +91,7 @@ func (db *Database) GetConfigBlobs(types []string) (map[string]json.RawMessage, } func (db *Database) GetAccounts() ([]Account, error) { - rows, err := db.db.Query("SELECT address, wallet, chat, type, storage, pubkey, path, name, color FROM accounts") + rows, err := db.db.Query("SELECT address, wallet, chat, type, storage, pubkey, path, name, color FROM accounts ORDER BY created_at") if err != nil { return nil, err } @@ -133,11 +133,11 @@ func (db *Database) SaveAccounts(accounts []Account) (err error) { }() // NOTE(dshulyak) replace all record values using address (primary key) // can't use `insert or replace` because of the additional constraints (wallet and chat) - insert, err = tx.Prepare("INSERT OR IGNORE INTO accounts (address) VALUES (?)") + insert, err = tx.Prepare("INSERT OR IGNORE INTO accounts (address, created_at, updated_at) VALUES (?, datetime('now'), datetime('now'))") if err != nil { return err } - update, err = tx.Prepare("UPDATE accounts SET wallet = ?, chat = ?, type = ?, storage = ?, pubkey = ?, path = ?, name = ?, color = ? WHERE address = ?") + update, err = tx.Prepare("UPDATE accounts SET wallet = ?, chat = ?, type = ?, storage = ?, pubkey = ?, path = ?, name = ?, color = ?, updated_at = datetime('now') WHERE address = ?") if err != nil { return err } @@ -161,6 +161,11 @@ func (db *Database) SaveAccounts(accounts []Account) (err error) { return } +func (db *Database) DeleteAccount(address common.Address) error { + _, err := db.db.Exec("DELETE FROM accounts WHERE address = ?", address) + return err +} + func (db *Database) GetWalletAddress() (rst common.Address, err error) { err = db.db.QueryRow("SELECT address FROM accounts WHERE wallet = 1").Scan(&rst) return @@ -172,7 +177,7 @@ func (db *Database) GetChatAddress() (rst common.Address, err error) { } func (db *Database) GetAddresses() (rst []common.Address, err error) { - rows, err := db.db.Query("SELECT address FROM accounts") + rows, err := db.db.Query("SELECT address FROM accounts ORDER BY created_at") if err != nil { return nil, err } diff --git a/multiaccounts/accounts/database_test.go b/multiaccounts/accounts/database_test.go index aeee87b9d..4a2b4d39a 100644 --- a/multiaccounts/accounts/database_test.go +++ b/multiaccounts/accounts/database_test.go @@ -125,6 +125,22 @@ func TestUpdateAccounts(t *testing.T) { require.Equal(t, accounts, rst) } +func TestDeleteAccount(t *testing.T) { + db, stop := setupTestDB(t) + defer stop() + accounts := []Account{ + {Address: common.Address{0x01}, Chat: true, Wallet: true}, + } + require.NoError(t, db.SaveAccounts(accounts)) + rst, err := db.GetAccounts() + require.NoError(t, err) + require.Equal(t, 1, len(rst)) + require.NoError(t, db.DeleteAccount(common.Address{0x01})) + rst2, err := db.GetAccounts() + require.NoError(t, err) + require.Equal(t, 0, len(rst2)) +} + func TestGetAddresses(t *testing.T) { db, stop := setupTestDB(t) defer stop() diff --git a/services/accounts/accounts.go b/services/accounts/accounts.go index 1cd7e98a6..cac28837d 100644 --- a/services/accounts/accounts.go +++ b/services/accounts/accounts.go @@ -3,6 +3,7 @@ package accounts import ( "context" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/event" "github.com/status-im/status-go/multiaccounts/accounts" ) @@ -29,3 +30,7 @@ func (api *API) SaveAccounts(ctx context.Context, accounts []accounts.Account) e func (api *API) GetAccounts(ctx context.Context) ([]accounts.Account, error) { return api.db.GetAccounts() } + +func (api *API) DeleteAccount(ctx context.Context, address common.Address) error { + return api.db.DeleteAccount(address) +}