github.com/status-im/status-go@v1.1.0/account/generator/account.go (about) 1 package generator 2 3 import ( 4 "crypto/ecdsa" 5 "crypto/sha256" 6 "encoding/json" 7 "time" 8 9 accountJson "github.com/status-im/status-go/account/json" 10 "github.com/status-im/status-go/eth-node/crypto" 11 "github.com/status-im/status-go/eth-node/types" 12 "github.com/status-im/status-go/extkeys" 13 "github.com/status-im/status-go/multiaccounts" 14 ) 15 16 type Account struct { 17 privateKey *ecdsa.PrivateKey 18 extendedKey *extkeys.ExtendedKey 19 } 20 21 func NewAccount(privateKey *ecdsa.PrivateKey, extKey *extkeys.ExtendedKey) Account { 22 if privateKey == nil { 23 privateKey = extKey.ToECDSA() 24 } 25 26 return Account{ 27 privateKey: privateKey, 28 extendedKey: extKey, 29 } 30 } 31 32 func (a *Account) ToAccountInfo() AccountInfo { 33 privateKeyHex := types.EncodeHex(crypto.FromECDSA(a.privateKey)) 34 publicKeyHex := types.EncodeHex(crypto.FromECDSAPub(&a.privateKey.PublicKey)) 35 addressHex := crypto.PubkeyToAddress(a.privateKey.PublicKey).Hex() 36 37 return AccountInfo{ 38 PrivateKey: privateKeyHex, 39 PublicKey: publicKeyHex, 40 Address: addressHex, 41 } 42 } 43 44 func (a *Account) ToIdentifiedAccountInfo(id string) IdentifiedAccountInfo { 45 info := a.ToAccountInfo() 46 keyUID := sha256.Sum256(crypto.FromECDSAPub(&a.privateKey.PublicKey)) 47 keyUIDHex := types.EncodeHex(keyUID[:]) 48 return IdentifiedAccountInfo{ 49 AccountInfo: info, 50 ID: id, 51 KeyUID: keyUIDHex, 52 } 53 } 54 55 func (a *Account) ToGeneratedAccountInfo(id string, mnemonic string) GeneratedAccountInfo { 56 idInfo := a.ToIdentifiedAccountInfo(id) 57 return GeneratedAccountInfo{ 58 IdentifiedAccountInfo: idInfo, 59 Mnemonic: mnemonic, 60 } 61 } 62 63 // AccountInfo contains a PublicKey and an Address of an account. 64 type AccountInfo struct { 65 PrivateKey string `json:"privateKey"` 66 PublicKey string `json:"publicKey"` 67 Address string `json:"address"` 68 } 69 70 func (a AccountInfo) MarshalJSON() ([]byte, error) { 71 type Alias AccountInfo 72 ext, err := accountJson.ExtendStructWithPubKeyData(a.PublicKey, Alias(a)) 73 if err != nil { 74 return nil, err 75 } 76 return json.Marshal(ext) 77 } 78 79 // IdentifiedAccountInfo contains AccountInfo and the ID of an account. 80 type IdentifiedAccountInfo struct { 81 AccountInfo 82 ID string `json:"id"` 83 // KeyUID is calculated as sha256 of the master public key and used for key 84 // identification. This is the only information available about the master 85 // key stored on a keycard before the card is paired. 86 // KeyUID name is chosen over KeyID in order to make it consistent with 87 // the name already used in Status and Keycard codebases. 88 KeyUID string `json:"keyUid"` 89 } 90 91 func (i IdentifiedAccountInfo) MarshalJSON() ([]byte, error) { 92 accountInfoJSON, err := i.AccountInfo.MarshalJSON() 93 if err != nil { 94 return nil, err 95 } 96 type info struct { 97 ID string `json:"id"` 98 KeyUID string `json:"keyUid"` 99 } 100 infoJSON, err := json.Marshal(info{ 101 ID: i.ID, 102 KeyUID: i.KeyUID, 103 }) 104 if err != nil { 105 return nil, err 106 } 107 infoJSON[0] = ',' 108 return append(accountInfoJSON[:len(accountInfoJSON)-1], infoJSON...), nil 109 } 110 111 func (i *IdentifiedAccountInfo) ToMultiAccount() *multiaccounts.Account { 112 return &multiaccounts.Account{ 113 Timestamp: time.Now().Unix(), 114 KeyUID: i.KeyUID, 115 } 116 } 117 118 // GeneratedAccountInfo contains IdentifiedAccountInfo and the mnemonic of an account. 119 type GeneratedAccountInfo struct { 120 IdentifiedAccountInfo 121 Mnemonic string `json:"mnemonic"` 122 } 123 124 func (g GeneratedAccountInfo) MarshalJSON() ([]byte, error) { 125 accountInfoJSON, err := g.IdentifiedAccountInfo.MarshalJSON() 126 if err != nil { 127 return nil, err 128 } 129 type info struct { 130 Mnemonic string `json:"mnemonic"` 131 } 132 infoJSON, err := json.Marshal(info{ 133 Mnemonic: g.Mnemonic, 134 }) 135 if err != nil { 136 return nil, err 137 } 138 infoJSON[0] = ',' 139 return append(accountInfoJSON[:len(accountInfoJSON)-1], infoJSON...), nil 140 } 141 142 func (g GeneratedAccountInfo) toGeneratedAndDerived(derived map[string]AccountInfo) GeneratedAndDerivedAccountInfo { 143 return GeneratedAndDerivedAccountInfo{ 144 GeneratedAccountInfo: g, 145 Derived: derived, 146 } 147 } 148 149 // GeneratedAndDerivedAccountInfo contains GeneratedAccountInfo and derived AccountInfo mapped by derivation path. 150 type GeneratedAndDerivedAccountInfo struct { 151 GeneratedAccountInfo 152 Derived map[string]AccountInfo `json:"derived"` 153 } 154 155 func (g GeneratedAndDerivedAccountInfo) MarshalJSON() ([]byte, error) { 156 accountInfoJSON, err := g.GeneratedAccountInfo.MarshalJSON() 157 if err != nil { 158 return nil, err 159 } 160 type info struct { 161 Derived map[string]AccountInfo `json:"derived"` 162 } 163 infoJSON, err := json.Marshal(info{ 164 Derived: g.Derived, 165 }) 166 if err != nil { 167 return nil, err 168 } 169 infoJSON[0] = ',' 170 return append(accountInfoJSON[:len(accountInfoJSON)-1], infoJSON...), nil 171 }