github.com/harveynw/blokechain@v0.0.0-20221114193833-615a6ea7bba4/internal/wallet/wallet.go (about)

     1  package wallet
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"io/ioutil"
     7  	"math/big"
     8  	"os"
     9  	"github.com/harveynw/blokechain/internal/cryptography"
    10  )
    11  
    12  // Wallet for holding multiple key pairs
    13  type Wallet struct {
    14  	Addresses []Address
    15  }
    16  
    17  // Address for a holding a ECDSA public key, private key pair
    18  type Address struct {
    19  	PublicKey cryptography.PublicKey
    20  	SecretKey *big.Int
    21  }
    22  
    23  // Save marshals wallet to file
    24  func (wallet *Wallet) Save() {
    25  	data, marshalErr := json.MarshalIndent(wallet, "", "   ")
    26  	if marshalErr != nil {
    27  		panic(marshalErr)
    28  	}
    29  
    30  	writeErr := ioutil.WriteFile(getWalletFile(), data, 0777)
    31  	if writeErr != nil {
    32  		panic(writeErr)
    33  	}
    34  }
    35  
    36  // Load unmarshals the Wallet after retrieval from file
    37  func Load() *Wallet {
    38  	data, err := getWalletData()
    39  	
    40  	if err != nil {
    41  		w := &Wallet{Addresses: make([]Address, 0)}
    42  		w.Save()
    43  
    44  		return w
    45  	}
    46  
    47  	w := &Wallet{}
    48  	marshalErr := json.Unmarshal(data, w)
    49  
    50  	if marshalErr != nil {
    51  		panic(fmt.Errorf("%v", marshalErr))
    52  	}
    53  
    54  	return w
    55  }
    56  
    57  // Add adds a new keypair to the wallet and saves it
    58  func (wallet *Wallet) Add(pubKey cryptography.PublicKey, secretKey *big.Int) {
    59  	addr := Address{PublicKey: pubKey, SecretKey: secretKey}
    60  	wallet.Addresses = append(wallet.Addresses, addr)
    61  	wallet.Save()
    62  }
    63  
    64  // GenerateNew creates a new keypair and saves it
    65  func (wallet *Wallet) GenerateNew() string {
    66  	secretKey, pubKey := cryptography.RandomKeyPair()
    67  	wallet.Add(pubKey, secretKey)
    68  	return pubKey.ToAddress()
    69  }
    70  
    71  // ListAddresses returns a slice of the addresses in the wallet
    72  func (wallet *Wallet) ListAddresses() (addresses []string) {
    73  	addresses = make([]string, 0)
    74  	for _, addr := range wallet.Addresses {
    75  		addresses = append(addresses, addr.PublicKey.ToAddress())
    76  	}
    77  	return
    78  }
    79  
    80  
    81  func getWalletData() ([]byte, error) {
    82  	if _, err := os.Stat(getWalletFolder()); os.IsNotExist(err) {
    83  		os.Mkdir(getWalletFolder(), 0777)
    84  	}
    85  	if _, err := os.Stat(getWalletFile()); os.IsNotExist(err) {
    86  		return nil, err
    87  	}
    88  	return ioutil.ReadFile(getWalletFile())
    89  }
    90  
    91  func getWalletFolder() string {
    92  	cwd, _ := os.Getwd()
    93  	return cwd + "/configs"
    94  }
    95  
    96  func getWalletFile() string {
    97  	return getWalletFolder() + "/wallet.json"
    98  }