-
Notifications
You must be signed in to change notification settings - Fork 241
/
contact.go
142 lines (119 loc) · 4.1 KB
/
contact.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
package protocol
import (
"crypto/ecdsa"
"github.com/status-im/status-go/eth-node/crypto"
"github.com/status-im/status-go/eth-node/types"
"github.com/status-im/status-go/images"
"github.com/status-im/status-go/protocol/identity/alias"
"github.com/status-im/status-go/protocol/identity/identicon"
)
const (
contactBlocked = ":contact/blocked"
contactAdded = ":contact/added"
contactRequestReceived = ":contact/request-received"
)
// ContactDeviceInfo is a struct containing information about a particular device owned by a contact
type ContactDeviceInfo struct {
// The installation id of the device
InstallationID string `json:"id"`
// Timestamp represents the last time we received this info
Timestamp int64 `json:"timestamp"`
// FCMToken is to be used for push notifications
FCMToken string `json:"fcmToken"`
}
// Contact has information about a "Contact". A contact is not necessarily one
// that we added or added us, that's based on SystemTags.
type Contact struct {
// ID of the contact. It's a hex-encoded public key (prefixed with 0x).
ID string `json:"id"`
// Ethereum address of the contact
Address string `json:"address,omitempty"`
// ENS name of contact
Name string `json:"name,omitempty"`
// EnsVerified whether we verified the name of the contact
ENSVerified bool `json:"ensVerified"`
// Generated username name of the contact
Alias string `json:"alias,omitempty"`
// Identicon generated from public key
Identicon string `json:"identicon"`
// LastUpdated is the last time we received an update from the contact
// updates should be discarded if last updated is less than the one stored
LastUpdated uint64 `json:"lastUpdated"`
// SystemTags contains information about whether we blocked/added/have been
// added.
SystemTags []string `json:"systemTags"`
DeviceInfo []ContactDeviceInfo `json:"deviceInfo"`
LocalNickname string `json:"localNickname,omitempty"`
Images map[string]images.IdentityImage `json:"images"`
}
func (c Contact) PublicKey() (*ecdsa.PublicKey, error) {
b, err := types.DecodeHex(c.ID)
if err != nil {
return nil, err
}
return crypto.UnmarshalPubkey(b)
}
func (c Contact) IsAdded() bool {
return existsInStringSlice(c.SystemTags, contactAdded)
}
func (c Contact) HasBeenAdded() bool {
return existsInStringSlice(c.SystemTags, contactRequestReceived)
}
func (c Contact) IsBlocked() bool {
return existsInStringSlice(c.SystemTags, contactBlocked)
}
func (c *Contact) Remove() {
var newSystemTags []string
// Remove the newSystemTags system-tag, so that the contact is
// not considered "added" anymore
for _, tag := range newSystemTags {
if tag != contactAdded {
newSystemTags = append(newSystemTags, tag)
}
}
c.SystemTags = newSystemTags
}
// existsInStringSlice checks if a string is in a set.
func existsInStringSlice(set []string, find string) bool {
for _, s := range set {
if s == find {
return true
}
}
return false
}
func buildContactFromPkString(pkString string) (*Contact, error) {
publicKeyBytes, err := types.DecodeHex(pkString)
if err != nil {
return nil, err
}
publicKey, err := crypto.UnmarshalPubkey(publicKeyBytes)
if err != nil {
return nil, err
}
return buildContact(pkString, publicKey)
}
func buildContactFromPublicKey(publicKey *ecdsa.PublicKey) (*Contact, error) {
id := types.EncodeHex(crypto.FromECDSAPub(publicKey))
return buildContact(id, publicKey)
}
func buildContact(publicKeyString string, publicKey *ecdsa.PublicKey) (*Contact, error) {
identicon, err := identicon.GenerateBase64(publicKeyString)
if err != nil {
return nil, err
}
contact := &Contact{
ID: publicKeyString,
Alias: alias.GenerateFromPublicKey(publicKey),
Identicon: identicon,
}
return contact, nil
}
// HasCustomFields returns whether the the contact has any field that is valuable
// to the client other than the computed name/image
func (c Contact) HasCustomFields() bool {
return c.IsAdded() || c.HasBeenAdded() || c.IsBlocked() || c.ENSVerified || c.LocalNickname != "" || len(c.Images) != 0
}
func contactIDFromPublicKey(key *ecdsa.PublicKey) string {
return types.EncodeHex(crypto.FromECDSAPub(key))
}