func (s *Storage) CheckAccountKey(account, key string) (bool, error) {
	adata, err := s.api.GetAccount(eos.AN(account))
	if err != nil {
		return false, err
	}
	ret := false
	for _, p := range adata.Permissions {
		for _, keys := range p.RequiredAuth.Keys {
			if keys.PublicKey.String() == key {
				ret = true
			}
		}
	}
	return ret, nil
}
CheckAccountKey checks if the key is authority of account
package eos
import (
	"crypto/sha256"
	"fmt"
	"log"
	"math"
	"time"
	"github.com/eoscanada/eos-go"
	"github.com/eoscanada/eos-go/ecc"
	"github.com/eoscanada/eos-go/system"
	"github.com/iryonetwork/network-poc/config"
	"github.com/iryonetwork/network-poc/logger"
	"github.com/iryonetwork/network-poc/state"
)
type Storage struct {
	config *config.Config
	state  *state.State
	api    *eos.API
	log    *logger.Log
}
func New(cfg *config.Config, state *state.State, log *logger.Log) (*Storage, error) {
	log.Debugf("Eos:: Adding EOS_API from %s", cfg.EosAPI)
	node := eos.New(cfg.EosAPI)
	node.SetSigner(eos.NewKeyBag())
	s := &Storage{log: log, config: cfg, state: state, api: node}
	s.api = node
	return s, nil
}
type AccessReq struct {
	Patient eos.AccountName `json:"patient"`
	Account eos.AccountName `json:"account"`
}
func (s *Storage) GrantAccess(to string) error {
	s.log.Debugf("Eos::grantAccess(%s) called", to)
	action := &eos.Action{
		Account: eos.AN(s.config.EosContractAccount),
		Name:    eos.ActN("grantaccess"),
		Authorization: []eos.PermissionLevel{
			{eos.AN(s.state.EosAccount), eos.PermissionName("active")},
		},
		ActionData: eos.NewActionData(AccessReq{eos.AN(s.state.EosAccount), eos.AN(to)}),
	}
	_, err := s.api.SignPushActions(action)
	s.log.Debugf("Granted access to user; %+v", to)
	return err
}
func (s *Storage) RevokeAccess(to string) error {
	s.log.Debugf("Eos::revokeAccess(%s) called", to)
	action := &eos.Action{
		Account: eos.AN(s.config.EosContractAccount),
		Name:    eos.ActN("revokeaccess"),
		Authorization: []eos.PermissionLevel{
			{eos.AN(s.state.EosAccount), eos.PermissionName("active")},
		},
		ActionData: eos.NewActionData(AccessReq{eos.AN(s.state.EosAccount), eos.AN(to)}),
	}
	_, err := s.api.SignPushActions(action)
	return err
}
func (s *Storage) AccessGranted(patient, to string) (bool, error) {
	s.log.Debugf("Eos::accessGranted(%s, %s) called", patient, to)
	if patient == to {
		return true, nil
	}
	b := false
	list, err := s.ListConnected(patient)
	s.log.Debugf("Got connected users: %s", list)
	if err != nil {
		return b, nil
	}
	for _, entry := range list {
		if entry == to {
			b = true
			break
		}
	}
	return b, nil
}
type TableEntry struct {
	AccountName string `json:"account_name"`
}
func (s *Storage) ListConnected(patient string) ([]string, error) {
	s.log.Debugf("Eos::listAccountFromTable(%s) called", patient)
	r, err := s.api.GetTableRows(eos.GetTableRowsRequest{
		Code:    s.config.EosContractAccount,
		JSON:    true,
		Scope:   patient,
		Table:   "person",
		KeyType: "i64",
		Limit:   math.MaxUint32})
	if err != nil {
		return nil, err
	}
	a := make([]TableEntry, 0)
	r.JSONToStructs(&a)
	ret := []string{}
	for _, entry := range a {
		s.log.Debugf("Adding %s to list", entry.AccountName)
		ret = append(ret, entry.AccountName)
	}
	return ret, nil
}
func (s *Storage) DeployContract() error {
	s.log.Debugf("Eos::deployContract() called")
	if s.config.EosContractAccount == "" {
		return fmt.Errorf("No config.EosContractAccount specified, unable to deploy contract")
	}
	if s.config.EosTokenAccount == "" {
		return fmt.Errorf("No config.EosTokenAccount specified, unable to createa account to deploy contract to")
	}
	err := s.pushContract(s.config.EosContractAccount, s.config.EosContractName)
	if err != nil {
		return fmt.Errorf("Failed to deploy connections contract: %v", err)
	}
	if s.config.EosTokenName == "" {
		return fmt.Errorf("No config.EosTokenName specified, unable to deploy token")
	}
	if s.state.EosAccount == "" {
		return fmt.Errorf("No config.EosAccount specified, unable to createa account to deploy token to")
	}
	err = s.pushContract(s.config.EosTokenAccount, s.config.EosTokenName)
	if err != nil {
		return fmt.Errorf("Failed to deploy new token contract: %v", err)
	}
	return nil
}
func (s *Storage) pushContract(n, cn string) error {
	key, err := s.ImportKey(s.state.EosPrivate)
	if err != nil {
		return err
	}
	err = s.CreateAccount(n, key.PublicKey().String())
	if err != nil {
		return err
	}
	contract, err := system.NewSetContract(eos.AN(n), "../../contract/"+cn+".wasm", "../../contract/"+cn+".abi")
	if err != nil {
		return err
	}
	_, err = s.api.SignPushActions(contract...)
	if err != nil {
		return err
	}
	return nil
}
func (s *Storage) CreateAccount(account, keyStr string) error {
	s.log.Debugf("Eos::createAccount(%s) called", account)
	if err := s.checkBuyResources(s.state.EosAccount); err != nil {
		s.log.Debugf("Bought resources error: %+v", err)
	}
	key, err := ecc.NewPublicKey(keyStr)
	if err != nil {
		return err
	}
	actions := []*eos.Action{}
	actions = append(actions, system.NewNewAccount(eos.AN(s.state.EosAccount), eos.AN(account), key))
	if s.config.EosRequiresRAM {
		actions = append(actions, system.NewBuyRAMBytes(eos.AccountName(s.state.EosAccount), eos.AccountName(account), 4096))
		actions = append(actions, s.buyCpuNetRequest(account, 10000, 10000))
	}
	err = retry(1*time.Second, 5, func() error {
		r, err := s.api.SignPushActions(actions...)
		if err != nil {
			return err
		}
		s.log.Debugf("Actions pushed. Transaction: %s", r.TransactionID)
		time.Sleep(2500 * time.Millisecond)
		if !s.CheckAccountExists(account) {
			return fmt.Errorf("Account does not exists")
		}
		return err
	})
	if err != nil {
		s.log.Debugf("Failed to create account after 5 attempts; %+v", err)
		return err
	}
	return nil
}
func (s *Storage) NewKey() error {
	key, err := ecc.NewRandomPrivateKey()
	if err != nil {
		return err
	}
	s.ImportKey(key.String())
	s.state.EosPrivate = key.String()
	return nil
}
func (s *Storage) ImportKey(prkey string) (*ecc.PrivateKey, error) {
	key, err := ecc.NewPrivateKey(prkey)
	if err != nil {
		return key, err
	}
	s.api.Signer.ImportPrivateKey(prkey)
	return key, nil
}