func (c *clefSigner) SignTypedData(typedData *eip712.TypedData) ([]byte, error) {
	var sig hexutil.Bytes
	err := c.client.Call(&sig, "account_signTypedData", c.account.Address, typedData)
	if err != nil {
		return nil, err
	}
	return sig, nil
}
SignTypedData signs data according to eip712.
package clef
import (
	"crypto/ecdsa"
	"errors"
	"fmt"
	"math/big"
	"os"
	"path/filepath"
	"runtime"
	"github.com/ethereum/go-ethereum/accounts"
	"github.com/ethereum/go-ethereum/common"
	"github.com/ethereum/go-ethereum/common/hexutil"
	"github.com/ethereum/go-ethereum/core/types"
	"github.com/ethsana/sana/pkg/crypto"
	"github.com/ethsana/sana/pkg/crypto/eip712"
)
var (
	ErrNoAccounts          = errors.New("no accounts found in clef")
	ErrAccountNotAvailable = errors.New("account not available in clef")
	clefRecoveryMessage    = []byte("public key recovery message")
)
type ExternalSignerInterface interface {
	SignData(account accounts.Account, mimeType string, data []byte) ([]byte, error)
	SignTx(account accounts.Account, tx *types.Transaction, chainID *big.Int) (*types.Transaction, error)
	Accounts() []accounts.Account
}
type Client interface {
	Call(result interface{}, method string, args ...interface{}) error
}
type clefSigner struct {
	client  Client  
	clef    ExternalSignerInterface
	account accounts.Account  
	pubKey  *ecdsa.PublicKey  
}
func DefaultIpcPath() (string, error) {
	socket := "clef.ipc"
	if runtime.GOOS == "windows" {
		return `\\.\pipe\` + socket, nil
	}
	home, err := os.UserHomeDir()
	if err != nil {
		return "", err
	}
	if runtime.GOOS == "darwin" {
		return filepath.Join(home, "Library", "Signer", socket), nil
	}
	return filepath.Join(home, ".clef", socket), nil
}
func selectAccount(clef ExternalSignerInterface, ethAddress *common.Address) (accounts.Account, error) {
	clefAccounts := clef.Accounts()
	if len(clefAccounts) == 0 {
		return accounts.Account{}, ErrNoAccounts
	}
	if ethAddress == nil {
		return clefAccounts[0], nil
	}
	for _, availableAccount := range clefAccounts {
		if availableAccount.Address == *ethAddress {
			return availableAccount, nil
		}
	}
	return accounts.Account{}, ErrAccountNotAvailable
}
func NewSigner(clef ExternalSignerInterface, client Client, recoverFunc crypto.RecoverFunc, ethAddress *common.Address) (signer crypto.Signer, err error) {
	account, err := selectAccount(clef, ethAddress)
	if err != nil {
		return nil, err
	}
	sig, err := clef.SignData(account, accounts.MimetypeTextPlain, clefRecoveryMessage)
	if err != nil {
		return nil, err
	}
	pubKey, err := recoverFunc(sig, clefRecoveryMessage)
	if err != nil {
		return nil, err
	}
	return &clefSigner{
		client:  client,
		clef:    clef,
		account: account,
		pubKey:  pubKey,
	}, nil
}
func (c *clefSigner) PublicKey() (*ecdsa.PublicKey, error) {
	return c.pubKey, nil
}
func (c *clefSigner) Sign(data []byte) ([]byte, error) {
	return c.clef.SignData(c.account, accounts.MimetypeTextPlain, data)
}
func (c *clefSigner) SignTx(transaction *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
	tx, err := c.clef.SignTx(c.account, transaction, nil)
	if err != nil {
		return nil, err
	}
	if chainID.Cmp(tx.ChainId()) != 0 {
		return nil, fmt.Errorf("misconfigured signer: wrong chain id %d; wanted %d", tx.ChainId(), chainID)
	}
	return tx, nil
}
func (c *clefSigner) EthereumAddress() (common.Address, error) {
	return c.account.Address, nil
}