github.com/trezor/blockbook@v0.4.1-0.20240328132726-e9a08582ee2c/bchain/coins/eth/evm.go (about) 1 package eth 2 3 import ( 4 "context" 5 "math/big" 6 7 "github.com/ethereum/go-ethereum" 8 "github.com/ethereum/go-ethereum/common" 9 "github.com/ethereum/go-ethereum/core/types" 10 "github.com/ethereum/go-ethereum/ethclient" 11 "github.com/ethereum/go-ethereum/rpc" 12 "github.com/trezor/blockbook/bchain" 13 ) 14 15 // EthereumClient wraps a client to implement the EVMClient interface 16 type EthereumClient struct { 17 *ethclient.Client 18 } 19 20 // HeaderByNumber returns a block header that implements the EVMHeader interface 21 func (c *EthereumClient) HeaderByNumber(ctx context.Context, number *big.Int) (bchain.EVMHeader, error) { 22 h, err := c.Client.HeaderByNumber(ctx, number) 23 if err != nil { 24 return nil, err 25 } 26 27 return &EthereumHeader{Header: h}, nil 28 } 29 30 // EstimateGas returns the current estimated gas cost for executing a transaction 31 func (c *EthereumClient) EstimateGas(ctx context.Context, msg interface{}) (uint64, error) { 32 return c.Client.EstimateGas(ctx, msg.(ethereum.CallMsg)) 33 } 34 35 // BalanceAt returns the balance for the given account at a specific block, or latest known block if no block number is provided 36 func (c *EthereumClient) BalanceAt(ctx context.Context, addrDesc bchain.AddressDescriptor, blockNumber *big.Int) (*big.Int, error) { 37 return c.Client.BalanceAt(ctx, common.BytesToAddress(addrDesc), blockNumber) 38 } 39 40 // NonceAt returns the nonce for the given account at a specific block, or latest known block if no block number is provided 41 func (c *EthereumClient) NonceAt(ctx context.Context, addrDesc bchain.AddressDescriptor, blockNumber *big.Int) (uint64, error) { 42 return c.Client.NonceAt(ctx, common.BytesToAddress(addrDesc), blockNumber) 43 } 44 45 // EthereumRPCClient wraps an rpc client to implement the EVMRPCClient interface 46 type EthereumRPCClient struct { 47 *rpc.Client 48 } 49 50 // EthSubscribe subscribes to events and returns a client subscription that implements the EVMClientSubscription interface 51 func (c *EthereumRPCClient) EthSubscribe(ctx context.Context, channel interface{}, args ...interface{}) (bchain.EVMClientSubscription, error) { 52 sub, err := c.Client.EthSubscribe(ctx, channel, args...) 53 if err != nil { 54 return nil, err 55 } 56 57 return &EthereumClientSubscription{ClientSubscription: sub}, nil 58 } 59 60 // EthereumHeader wraps a block header to implement the EVMHeader interface 61 type EthereumHeader struct { 62 *types.Header 63 } 64 65 // Hash returns the block hash as a hex string 66 func (h *EthereumHeader) Hash() string { 67 return h.Header.Hash().Hex() 68 } 69 70 // Number returns the block number 71 func (h *EthereumHeader) Number() *big.Int { 72 return h.Header.Number 73 } 74 75 // Difficulty returns the block difficulty 76 func (h *EthereumHeader) Difficulty() *big.Int { 77 return h.Header.Difficulty 78 } 79 80 // EthereumHash wraps a transaction hash to implement the EVMHash interface 81 type EthereumHash struct { 82 common.Hash 83 } 84 85 // EthereumClientSubscription wraps a client subcription to implement the EVMClientSubscription interface 86 type EthereumClientSubscription struct { 87 *rpc.ClientSubscription 88 } 89 90 // EthereumNewBlock wraps a block header channel to implement the EVMNewBlockSubscriber interface 91 type EthereumNewBlock struct { 92 channel chan *types.Header 93 } 94 95 // NewEthereumNewBlock returns an initialized EthereumNewBlock struct 96 func NewEthereumNewBlock() *EthereumNewBlock { 97 return &EthereumNewBlock{channel: make(chan *types.Header)} 98 } 99 100 // Channel returns the underlying channel as an empty interface 101 func (s *EthereumNewBlock) Channel() interface{} { 102 return s.channel 103 } 104 105 // Read from the underlying channel and return a block header that implements the EVMHeader interface 106 func (s *EthereumNewBlock) Read() (bchain.EVMHeader, bool) { 107 h, ok := <-s.channel 108 return &EthereumHeader{Header: h}, ok 109 } 110 111 // Close the underlying channel 112 func (s *EthereumNewBlock) Close() { 113 close(s.channel) 114 } 115 116 // EthereumNewTx wraps a transaction hash channel to implement the EVMNewTxSubscriber interface 117 type EthereumNewTx struct { 118 channel chan common.Hash 119 } 120 121 // NewEthereumNewTx returns an initialized EthereumNewTx struct 122 func NewEthereumNewTx() *EthereumNewTx { 123 return &EthereumNewTx{channel: make(chan common.Hash)} 124 } 125 126 // Channel returns the underlying channel as an empty interface 127 func (s *EthereumNewTx) Channel() interface{} { 128 return s.channel 129 } 130 131 // Read from the underlying channel and return a transaction hash that implements the EVMHash interface 132 func (s *EthereumNewTx) Read() (bchain.EVMHash, bool) { 133 h, ok := <-s.channel 134 return &EthereumHash{Hash: h}, ok 135 } 136 137 // Close the underlying channel 138 func (s *EthereumNewTx) Close() { 139 close(s.channel) 140 }