Go proporciona la implementación oficial de Ethereum a través de go-ethereum (geth), convirtiéndolo en una opción potente para el desarrollo en Ethereum.
Implementación oficial en Go del protocolo Ethereum.
package ethereum
import (
"context"
"math/big"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type EthereumClient struct {
client *ethclient.Client
}
func NewEthereumClient(url string) (*EthereumClient, error) {
client, err := ethclient.Dial(url)
if err != nil {
return nil, err
}
return &EthereumClient{client: client}, nil
}
func (ec *EthereumClient) GetBalance(address string) (*big.Float, error) {
account := common.HexToAddress(address)
balance, err := ec.client.BalanceAt(context.Background(), account, nil)
if err != nil {
return nil, err
}
fbalance := new(big.Float)
fbalance.SetString(balance.String())
ethValue := new(big.Float).Quo(fbalance, big.NewFloat(1e18))
return ethValue, nil
}
func (ec *EthereumClient) SendTransaction(from, to common.Address, value *big.Int) (*types.Transaction, error) {
nonce, err := ec.client.PendingNonceAt(context.Background(), from)
if err != nil {
return nil, err
}
gasPrice, err := ec.client.SuggestGasPrice(context.Background())
if err != nil {
return nil, err
}
tx := types.NewTransaction(nonce, to, value, 21000, gasPrice, nil)
return tx, nil
}
Trabajando con contratos inteligentes en Go:
package contracts
import (
"github.com/ethereum/go-ethereum/accounts/abi/bind"
"github.com/ethereum/go-ethereum/common"
)
type SmartContractClient struct {
contract *bind.BoundContract
address common.Address
}
func NewContract(address common.Address, client *ethclient.Client) (*SmartContractClient, error) {
parsed, err := abi.JSON(strings.NewReader(ContractABI))
if err != nil {
return nil, err
}
contract := bind.NewBoundContract(address, parsed, client, client, client)
return &SmartContractClient{
contract: contract,
address: address,
}, nil
}
func (sc *SmartContractClient) CallMethod(method string, args ...interface{}) error {
opts := &bind.CallOpts{
Pending: false,
Context: context.Background(),
}
return sc.contract.Call(opts, method, args...)
}
Suscripción y monitoreo de eventos Ethereum:
func (ec *EthereumClient) MonitorBlocks() (<-chan *types.Header, error) {
headers := make(chan *types.Header)
sub, err := ec.client.SubscribeNewHead(context.Background(), headers)
if err != nil {
return nil, err
}
go func() {
for {
select {
case err := <-sub.Err():
log.Fatal(err)
case header := <-headers:
block, err := ec.client.BlockByHash(context.Background(), header.Hash())
if err != nil {
log.Fatal(err)
}
fmt.Println("New block:", block.Number().Uint64())
}
}
}()
return headers, nil
}
Utilidades útiles para el desarrollo en Ethereum:
package utils
import (
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
)
// WeiToEther converts wei to ether
func WeiToEther(wei *big.Int) *big.Float {
return new(big.Float).Quo(
new(big.Float).SetInt(wei),
new(big.Float).SetInt(big.NewInt(1e18)),
)
}
// EtherToWei converts ether to wei
func EtherToWei(ether *big.Float) *big.Int {
truncInt, _ := new(big.Float).Mul(ether, big.NewFloat(1e18)).Int(nil)
return truncInt
}
// IsValidAddress checks if the address is valid
func IsValidAddress(address string) bool {
return common.IsHexAddress(address)
}