mirror of
https://github.com/0glabs/0g-chain.git
synced 2024-12-27 16:55:21 +00:00
104 lines
2.5 KiB
Go
104 lines
2.5 KiB
Go
|
package util
|
||
|
|
||
|
import (
|
||
|
"context"
|
||
|
"crypto/ecdsa"
|
||
|
"fmt"
|
||
|
"math/big"
|
||
|
|
||
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||
|
"github.com/ethereum/go-ethereum/common"
|
||
|
ethtypes "github.com/ethereum/go-ethereum/core/types"
|
||
|
"github.com/ethereum/go-ethereum/crypto"
|
||
|
"github.com/ethereum/go-ethereum/ethclient"
|
||
|
)
|
||
|
|
||
|
type EvmTxRequest struct {
|
||
|
Tx *ethtypes.Transaction
|
||
|
Data interface{}
|
||
|
}
|
||
|
type EvmTxResponse struct {
|
||
|
Request EvmTxRequest
|
||
|
TxHash common.Hash
|
||
|
Err error
|
||
|
}
|
||
|
|
||
|
type EvmFailedToSignError struct{ Err error }
|
||
|
|
||
|
func (e EvmFailedToSignError) Error() string {
|
||
|
return fmt.Sprintf("failed to sign tx: %s", e.Err)
|
||
|
}
|
||
|
|
||
|
type EvmFailedToBroadcastError struct{ Err error }
|
||
|
|
||
|
func (e EvmFailedToBroadcastError) Error() string {
|
||
|
return fmt.Sprintf("failed to broadcast tx: %s", e.Err)
|
||
|
}
|
||
|
|
||
|
// EvmSigner manages signing and broadcasting requests to transfer Erc20 tokens
|
||
|
// Will work for calling all contracts that have func signature `transfer(address,uint256)`
|
||
|
type EvmSigner struct {
|
||
|
auth *bind.TransactOpts
|
||
|
signerAddress common.Address
|
||
|
EvmClient *ethclient.Client
|
||
|
}
|
||
|
|
||
|
func NewEvmSigner(
|
||
|
evmClient *ethclient.Client,
|
||
|
privKey *ecdsa.PrivateKey,
|
||
|
chainId *big.Int,
|
||
|
) (*EvmSigner, error) {
|
||
|
auth, err := bind.NewKeyedTransactorWithChainID(privKey, chainId)
|
||
|
if err != nil {
|
||
|
return &EvmSigner{}, err
|
||
|
}
|
||
|
|
||
|
publicKey := privKey.Public()
|
||
|
publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
||
|
if !ok {
|
||
|
return &EvmSigner{}, fmt.Errorf("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
|
||
|
}
|
||
|
|
||
|
return &EvmSigner{
|
||
|
auth: auth,
|
||
|
signerAddress: crypto.PubkeyToAddress(*publicKeyECDSA),
|
||
|
EvmClient: evmClient,
|
||
|
}, nil
|
||
|
}
|
||
|
|
||
|
func (s *EvmSigner) Run(requests <-chan EvmTxRequest) <-chan EvmTxResponse {
|
||
|
responses := make(chan EvmTxResponse)
|
||
|
|
||
|
// receive tx requests, sign & broadcast them.
|
||
|
// Responses are sent once the tx is added to the pending tx pool.
|
||
|
// To see result, use TransactionReceipt after tx has been included in a block.
|
||
|
go func() {
|
||
|
for {
|
||
|
// wait for incoming request
|
||
|
req := <-requests
|
||
|
|
||
|
signedTx, err := s.auth.Signer(s.signerAddress, req.Tx)
|
||
|
if err != nil {
|
||
|
err = EvmFailedToSignError{Err: err}
|
||
|
} else {
|
||
|
err = s.EvmClient.SendTransaction(context.Background(), signedTx)
|
||
|
if err != nil {
|
||
|
err = EvmFailedToBroadcastError{Err: err}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
responses <- EvmTxResponse{
|
||
|
Request: req,
|
||
|
TxHash: signedTx.Hash(),
|
||
|
Err: err,
|
||
|
}
|
||
|
}
|
||
|
}()
|
||
|
|
||
|
return responses
|
||
|
}
|
||
|
|
||
|
func (s *EvmSigner) Address() common.Address {
|
||
|
return s.signerAddress
|
||
|
}
|