181 lines
4.7 KiB
Go
181 lines
4.7 KiB
Go
package generator
|
|
|
|
import (
|
|
"crypto/ecdsa"
|
|
"crypto/sha256"
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"github.com/status-im/status-go/api/multiformat"
|
|
"github.com/status-im/status-go/eth-node/crypto"
|
|
"github.com/status-im/status-go/eth-node/types"
|
|
"github.com/status-im/status-go/extkeys"
|
|
"github.com/status-im/status-go/multiaccounts"
|
|
)
|
|
|
|
type Account struct {
|
|
privateKey *ecdsa.PrivateKey
|
|
extendedKey *extkeys.ExtendedKey
|
|
}
|
|
|
|
func NewAccount(privateKey *ecdsa.PrivateKey, extKey *extkeys.ExtendedKey) Account {
|
|
if privateKey == nil {
|
|
privateKey = extKey.ToECDSA()
|
|
}
|
|
|
|
return Account{
|
|
privateKey: privateKey,
|
|
extendedKey: extKey,
|
|
}
|
|
}
|
|
|
|
func (a *Account) ToAccountInfo() AccountInfo {
|
|
privateKeyHex := types.EncodeHex(crypto.FromECDSA(a.privateKey))
|
|
publicKeyHex := types.EncodeHex(crypto.FromECDSAPub(&a.privateKey.PublicKey))
|
|
addressHex := crypto.PubkeyToAddress(a.privateKey.PublicKey).Hex()
|
|
|
|
return AccountInfo{
|
|
PrivateKey: privateKeyHex,
|
|
PublicKey: publicKeyHex,
|
|
Address: addressHex,
|
|
}
|
|
}
|
|
|
|
func (a *Account) ToIdentifiedAccountInfo(id string) IdentifiedAccountInfo {
|
|
info := a.ToAccountInfo()
|
|
keyUID := sha256.Sum256(crypto.FromECDSAPub(&a.privateKey.PublicKey))
|
|
keyUIDHex := types.EncodeHex(keyUID[:])
|
|
return IdentifiedAccountInfo{
|
|
AccountInfo: info,
|
|
ID: id,
|
|
KeyUID: keyUIDHex,
|
|
}
|
|
}
|
|
|
|
func (a *Account) ToGeneratedAccountInfo(id string, mnemonic string) GeneratedAccountInfo {
|
|
idInfo := a.ToIdentifiedAccountInfo(id)
|
|
return GeneratedAccountInfo{
|
|
IdentifiedAccountInfo: idInfo,
|
|
Mnemonic: mnemonic,
|
|
}
|
|
}
|
|
|
|
// AccountInfo contains a PublicKey and an Address of an account.
|
|
type AccountInfo struct {
|
|
PrivateKey string `json:"privateKey"`
|
|
PublicKey string `json:"publicKey"`
|
|
Address string `json:"address"`
|
|
}
|
|
|
|
func (a AccountInfo) MarshalJSON() ([]byte, error) {
|
|
type Alias AccountInfo
|
|
item := struct {
|
|
Alias
|
|
CompressedKey string `json:"compressedKey"`
|
|
}{
|
|
Alias: (Alias)(a),
|
|
}
|
|
|
|
compressedKey, err := multiformat.SerializeLegacyKey(item.PublicKey)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
item.CompressedKey = compressedKey
|
|
|
|
return json.Marshal(item)
|
|
}
|
|
|
|
// IdentifiedAccountInfo contains AccountInfo and the ID of an account.
|
|
type IdentifiedAccountInfo struct {
|
|
AccountInfo
|
|
ID string `json:"id"`
|
|
// KeyUID is calculated as sha256 of the master public key and used for key
|
|
// identification. This is the only information available about the master
|
|
// key stored on a keycard before the card is paired.
|
|
// KeyUID name is chosen over KeyID in order to make it consistent with
|
|
// the name already used in Status and Keycard codebases.
|
|
KeyUID string `json:"keyUid"`
|
|
}
|
|
|
|
func (i IdentifiedAccountInfo) MarshalJSON() ([]byte, error) {
|
|
accountInfoJSON, err := i.AccountInfo.MarshalJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
type info struct {
|
|
ID string `json:"id"`
|
|
KeyUID string `json:"keyUid"`
|
|
}
|
|
infoJSON, err := json.Marshal(info{
|
|
ID: i.ID,
|
|
KeyUID: i.KeyUID,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
infoJSON[0] = ','
|
|
return append(accountInfoJSON[:len(accountInfoJSON)-1], infoJSON...), nil
|
|
}
|
|
|
|
func (i *IdentifiedAccountInfo) ToMultiAccount() *multiaccounts.Account {
|
|
return &multiaccounts.Account{
|
|
Timestamp: time.Now().Unix(),
|
|
KeyUID: i.KeyUID,
|
|
}
|
|
}
|
|
|
|
// GeneratedAccountInfo contains IdentifiedAccountInfo and the mnemonic of an account.
|
|
type GeneratedAccountInfo struct {
|
|
IdentifiedAccountInfo
|
|
Mnemonic string `json:"mnemonic"`
|
|
}
|
|
|
|
func (g GeneratedAccountInfo) MarshalJSON() ([]byte, error) {
|
|
accountInfoJSON, err := g.IdentifiedAccountInfo.MarshalJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
type info struct {
|
|
Mnemonic string `json:"mnemonic"`
|
|
}
|
|
infoJSON, err := json.Marshal(info{
|
|
Mnemonic: g.Mnemonic,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
infoJSON[0] = ','
|
|
return append(accountInfoJSON[:len(accountInfoJSON)-1], infoJSON...), nil
|
|
}
|
|
|
|
func (g GeneratedAccountInfo) toGeneratedAndDerived(derived map[string]AccountInfo) GeneratedAndDerivedAccountInfo {
|
|
return GeneratedAndDerivedAccountInfo{
|
|
GeneratedAccountInfo: g,
|
|
Derived: derived,
|
|
}
|
|
}
|
|
|
|
// GeneratedAndDerivedAccountInfo contains GeneratedAccountInfo and derived AccountInfo mapped by derivation path.
|
|
type GeneratedAndDerivedAccountInfo struct {
|
|
GeneratedAccountInfo
|
|
Derived map[string]AccountInfo `json:"derived"`
|
|
}
|
|
|
|
func (g GeneratedAndDerivedAccountInfo) MarshalJSON() ([]byte, error) {
|
|
accountInfoJSON, err := g.GeneratedAccountInfo.MarshalJSON()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
type info struct {
|
|
Derived map[string]AccountInfo `json:"derived"`
|
|
}
|
|
infoJSON, err := json.Marshal(info{
|
|
Derived: g.Derived,
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
infoJSON[0] = ','
|
|
return append(accountInfoJSON[:len(accountInfoJSON)-1], infoJSON...), nil
|
|
}
|