Files
ark/pkg/client-sdk/wallet/singlekey/wallet.go
2024-08-09 17:46:42 +02:00

119 lines
2.6 KiB
Go

package singlekeywallet
import (
"bytes"
"context"
"encoding/hex"
"fmt"
"github.com/ark-network/ark/pkg/client-sdk/internal/utils"
"github.com/ark-network/ark/pkg/client-sdk/store"
"github.com/ark-network/ark/pkg/client-sdk/wallet"
walletstore "github.com/ark-network/ark/pkg/client-sdk/wallet/singlekey/store"
"github.com/decred/dcrd/dcrec/secp256k1/v4"
)
type singlekeyWallet struct {
configStore store.ConfigStore
walletStore walletstore.WalletStore
privateKey *secp256k1.PrivateKey
walletData *walletstore.WalletData
}
func (w *singlekeyWallet) GetType() string {
return wallet.SingleKeyWallet
}
func (w *singlekeyWallet) Create(
_ context.Context, password, seed string,
) (string, error) {
var privateKey *secp256k1.PrivateKey
if len(seed) <= 0 {
privKey, err := utils.GenerateRandomPrivateKey()
if err != nil {
return "", err
}
privateKey = privKey
} else {
privKeyBytes, err := hex.DecodeString(seed)
if err != nil {
return "", err
}
privateKey = secp256k1.PrivKeyFromBytes(privKeyBytes)
}
pwd := []byte(password)
passwordHash := utils.HashPassword(pwd)
pubkey := privateKey.PubKey()
buf := privateKey.Serialize()
encryptedPrivateKey, err := utils.EncryptAES128(buf, pwd)
if err != nil {
return "", err
}
walletData := walletstore.WalletData{
EncryptedPrvkey: encryptedPrivateKey,
PasswordHash: passwordHash,
Pubkey: pubkey,
}
if err := w.walletStore.AddWallet(walletData); err != nil {
return "", err
}
w.walletData = &walletData
return hex.EncodeToString(privateKey.Serialize()), nil
}
func (w *singlekeyWallet) Lock(_ context.Context, password string) error {
if w.walletData == nil {
return fmt.Errorf("wallet not initialized")
}
if w.privateKey == nil {
return nil
}
pwd := []byte(password)
currentPassHash := utils.HashPassword(pwd)
if !bytes.Equal(w.walletData.PasswordHash, currentPassHash) {
return fmt.Errorf("invalid password")
}
w.privateKey = nil
return nil
}
func (w *singlekeyWallet) Unlock(
_ context.Context, password string,
) (bool, error) {
if w.walletData == nil {
return false, fmt.Errorf("wallet not initialized")
}
if w.privateKey != nil {
return true, nil
}
pwd := []byte(password)
currentPassHash := utils.HashPassword(pwd)
if !bytes.Equal(w.walletData.PasswordHash, currentPassHash) {
return false, fmt.Errorf("invalid password")
}
privateKeyBytes, err := utils.DecryptAES128(w.walletData.EncryptedPrvkey, pwd)
if err != nil {
return false, err
}
w.privateKey = secp256k1.PrivKeyFromBytes(privateKeyBytes)
return false, nil
}
func (w *singlekeyWallet) IsLocked() bool {
return w.privateKey == nil
}