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  }