func (w *Wallet) SendRawTransaction(txn *transaction.Transaction) (string, error) {
	return w.SendRawTransactionContext(context.Background(), txn)
}
SendRawTransaction wraps SendRawTransactionContext with background context.
package nkn
import (
	"context"
	"encoding/hex"
	"encoding/json"
	"sync"
	"github.com/nknorg/nkn/v2/common"
	"github.com/nknorg/nkn/v2/pb"
	"github.com/nknorg/nkn/v2/program"
	"github.com/nknorg/nkn/v2/signature"
	"github.com/nknorg/nkn/v2/transaction"
	"github.com/nknorg/nkn/v2/vault"
)
type Wallet struct {
	config  *WalletConfig
	account *Account
	address string
	lock       sync.Mutex
	walletData *vault.WalletData
}
func NewWallet(account *Account, config *WalletConfig) (*Wallet, error) {
	config, err := MergeWalletConfig(config)
	if err != nil {
		return nil, err
	}
	var walletData *vault.WalletData
	if len(config.Password) > 0 || len(config.MasterKey) > 0 {
		defer func() {
			config.Password = ""
			config.MasterKey = nil
		}()
		walletData, err = vault.NewWalletData(
			account.Account,
			[]byte(config.Password),
			config.MasterKey,
			config.IV,
			config.ScryptConfig.Salt,
			config.ScryptConfig.N,
			config.ScryptConfig.R,
			config.ScryptConfig.P,
		)
		if err != nil {
			return nil, err
		}
	}
	wallet := &Wallet{
		config:     config,
		account:    account,
		address:    account.WalletAddress(),
		walletData: walletData,
	}
	return wallet, nil
}
func WalletFromJSON(walletJSON string, config *WalletConfig) (*Wallet, error) {
	config, err := MergeWalletConfig(config)
	if err != nil {
		return nil, err
	}
	defer func() {
		config.Password = ""
		config.MasterKey = nil
	}()
	walletData := &vault.WalletData{}
	err = json.Unmarshal([]byte(walletJSON), walletData)
	if err != nil {
		return nil, err
	}
	if walletData.Version < vault.MinCompatibleWalletVersion || walletData.Version > vault.MaxCompatibleWalletVersion {
		return nil, ErrInvalidWalletVersion
	}
	account, err := walletData.DecryptAccount([]byte(config.Password))
	if err != nil {
		return nil, err
	}
	address, err := account.ProgramHash.ToAddress()
	if err != nil {
		return nil, err
	}
	if address != walletData.Address {
		return nil, ErrWrongPassword
	}
	if walletData.Version == vault.WalletVersion {
		wallet := &Wallet{
			config:     config,
			account:    &Account{account},
			address:    address,
			walletData: walletData,
		}
		return wallet, nil
	}
	iv, err := hex.DecodeString(walletData.IV)
	if err != nil {
		return nil, err
	}
	masterKey, err := walletData.DecryptMasterKey([]byte(config.Password))
	if err != nil {
		return nil, err
	}
	config.IV = iv
	config.MasterKey = masterKey
	return NewWallet(&Account{account}, config)
}
func (w *Wallet) getWalletData() (*vault.WalletData, error) {
	w.lock.Lock()
	defer w.lock.Unlock()
	if w.walletData == nil {
		walletData, err := vault.NewWalletData(
			w.account.Account,
			[]byte(w.config.Password),
			w.config.MasterKey,
			w.config.IV,
			w.config.ScryptConfig.Salt,
			w.config.ScryptConfig.N,
			w.config.ScryptConfig.R,
			w.config.ScryptConfig.P,
		)
		if err != nil {
			return nil, err
		}
		w.walletData = walletData
	}
	return w.walletData, nil
}
func (w *Wallet) MarshalJSON() ([]byte, error) {
	walletData, err := w.getWalletData()
	if err != nil {
		return nil, err
	}
	return json.Marshal(walletData)
}
func (w *Wallet) ToJSON() (string, error) {
	b, err := w.MarshalJSON()
	if err != nil {
		return "", err
	}
	return string(b), nil
}
func (w *Wallet) Account() *Account {
	return w.account
}
func (w *Wallet) Seed() []byte {
	return w.account.Seed()
}
func (w *Wallet) PubKey() []byte {
	return w.account.PubKey()
}
func (w *Wallet) Address() string {
	return w.address
}
func (w *Wallet) VerifyPassword(password string) error {
	walletData, err := w.getWalletData()
	if err != nil {
		return err
	}
	return walletData.VerifyPassword([]byte(password))
}
func (w *Wallet) ProgramHash() common.Uint160 {
	return w.account.ProgramHash
}
func (w *Wallet) SignTransaction(tx *transaction.Transaction) error {
	ct, err := program.CreateSignatureProgramContext(w.account.PublicKey)
	if err != nil {
		return err
	}
	sig, err := signature.SignBySigner(tx, w.account.Account)
	if err != nil {
		return err
	}
	tx.SetPrograms([]*pb.Program{ct.NewProgram(sig)})
	return nil
}
func (w *Wallet) NewNanoPay(recipientAddress, fee string, duration int) (*NanoPay, error) {
	return NewNanoPay(w, w, recipientAddress, fee, duration)
}
func (w *Wallet) NewNanoPayClaimer(recipientAddress string, claimIntervalMs int32, minFlushAmount string, onError *OnError) (*NanoPayClaimer, error) {
	if len(recipientAddress) == 0 {
		recipientAddress = w.Address()
	}
	return NewNanoPayClaimer(w, recipientAddress, claimIntervalMs, minFlushAmount, onError)
}
func (w *Wallet) GetNonce(txPool bool) (int64, error) {
	return w.GetNonceContext(context.Background(), txPool)
}
func (w *Wallet) GetNonceContext(ctx context.Context, txPool bool) (int64, error) {
	return w.GetNonceByAddress(w.address, txPool)
}
func (w *Wallet) GetNonceByAddress(address string, txPool bool) (int64, error) {
	return w.GetNonceByAddressContext(context.Background(), address, txPool)
}
func (w *Wallet) GetNonceByAddressContext(ctx context.Context, address string, txPool bool) (int64, error) {
	return GetNonce(address, txPool, w.config)
}
func (w *Wallet) GetHeight() (int32, error) {
	return w.GetHeightContext(context.Background())
}
func (w *Wallet) GetHeightContext(ctx context.Context) (int32, error) {
	return GetHeight(w.config)
}
func (w *Wallet) Balance() (*Amount, error) {
	return w.BalanceContext(context.Background())
}
func (w *Wallet) BalanceContext(ctx context.Context) (*Amount, error) {
	return w.BalanceByAddress(w.address)
}
func (w *Wallet) BalanceByAddress(address string) (*Amount, error) {
	return w.BalanceByAddressContext(context.Background(), address)
}
func (w *Wallet) BalanceByAddressContext(ctx context.Context, address string) (*Amount, error) {
	return GetBalance(address, w.config)
}
func (w *Wallet) GetSubscribers(topic string, offset, limit int, meta, txPool bool, subscriberHashPrefix []byte) (*Subscribers, error) {
	return w.GetSubscribersContext(context.Background(), topic, offset, limit, meta, txPool, subscriberHashPrefix)
}
func (w *Wallet) GetSubscribersContext(ctx context.Context, topic string, offset, limit int, meta, txPool bool, subscriberHashPrefix []byte) (*Subscribers, error) {
	return GetSubscribers(topic, offset, limit, meta, txPool, subscriberHashPrefix, w.config)
}
func (w *Wallet) GetSubscription(topic string, subscriber string) (*Subscription, error) {
	return w.GetSubscriptionContext(context.Background(), topic, subscriber)
}
func (w *Wallet) GetSubscriptionContext(ctx context.Context, topic string, subscriber string) (*Subscription, error) {
	return GetSubscription(topic, subscriber, w.config)
}
func (w *Wallet) GetSubscribersCount(topic string, subscriberHashPrefix []byte) (int, error) {
	return w.GetSubscribersCountContext(context.Background(), topic, subscriberHashPrefix)
}
func (w *Wallet) GetSubscribersCountContext(ctx context.Context, topic string, subscriberHashPrefix []byte) (int, error) {
	return GetSubscribersCount(topic, subscriberHashPrefix, w.config)
}
func (w *Wallet) GetRegistrant(name string) (*Registrant, error) {
	return w.GetRegistrantContext(context.Background(), name)
}
func (w *Wallet) GetRegistrantContext(ctx context.Context, name string) (*Registrant, error) {
	return GetRegistrant(name, w.config)
}