2020-08-03 20:01:38 +00:00
|
|
|
package rpcclient
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"math/big"
|
|
|
|
|
2020-08-06 18:48:57 +00:00
|
|
|
"github.com/Secured-Finance/p2p-oracle-node/contracts/aggregator"
|
2020-08-06 21:47:58 +00:00
|
|
|
"github.com/Secured-Finance/p2p-oracle-node/contracts/oracleemitter"
|
2020-08-06 18:48:57 +00:00
|
|
|
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
2020-08-03 20:01:38 +00:00
|
|
|
"github.com/ethereum/go-ethereum/common"
|
2020-08-04 18:19:42 +00:00
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
2020-08-03 20:01:38 +00:00
|
|
|
"github.com/ethereum/go-ethereum/ethclient"
|
2020-10-20 18:18:36 +00:00
|
|
|
"github.com/ethereum/go-ethereum/event"
|
2020-08-04 18:19:42 +00:00
|
|
|
"github.com/ipfs/go-log"
|
2020-08-03 20:01:38 +00:00
|
|
|
)
|
|
|
|
|
2020-08-06 18:48:57 +00:00
|
|
|
type EthereumClient struct {
|
2020-10-20 18:18:36 +00:00
|
|
|
client *ethclient.Client
|
|
|
|
Logger *log.ZapEventLogger
|
|
|
|
authTransactor *bind.TransactOpts
|
|
|
|
oracleEmitter *oracleemitter.SmartcontractsSession
|
|
|
|
aggregator *aggregator.SmartcontractsSession
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-08-06 21:47:58 +00:00
|
|
|
type OracleEvent struct {
|
|
|
|
RequestType string
|
|
|
|
CallbackAddress common.Address
|
|
|
|
CallbackMethodID [4]byte
|
|
|
|
RequestID *big.Int
|
|
|
|
}
|
|
|
|
|
2020-08-06 18:48:57 +00:00
|
|
|
type Ethereum interface {
|
2020-10-20 18:18:36 +00:00
|
|
|
Initialize(ctx context.Context, url, connectionType, privateKey, oracleEmitterContractAddress, aggregatorContractAddress string) error
|
2020-08-04 18:19:42 +00:00
|
|
|
Balance(context.Context, string) (*big.Int, error)
|
2020-08-03 20:01:38 +00:00
|
|
|
SubscribeOnSmartContractEvents(context.Context, string)
|
2020-10-20 18:18:36 +00:00
|
|
|
SubmitRequestAnswer(reqID *big.Int, data string, callbackAddress common.Address, callbackMethodID [4]byte) error
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-08-06 18:48:57 +00:00
|
|
|
func NewEthereumClient() *EthereumClient {
|
|
|
|
ethereumClient := &EthereumClient{
|
|
|
|
Logger: log.Logger("rendezvous"),
|
|
|
|
}
|
2020-08-06 21:47:58 +00:00
|
|
|
log.SetAllLoggers(log.LevelInfo)
|
2020-08-06 18:48:57 +00:00
|
|
|
|
|
|
|
return ethereumClient
|
|
|
|
}
|
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
func (c *EthereumClient) Initialize(ctx context.Context, url, privateKey, oracleEmitterContractAddress, aggregatorContractAddress string) error {
|
2020-08-03 20:01:38 +00:00
|
|
|
client, err := ethclient.Dial(url)
|
|
|
|
if err != nil {
|
2020-10-20 18:18:36 +00:00
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.client = client
|
|
|
|
ecdsaKey, err := crypto.HexToECDSA(privateKey)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
authTransactor := bind.NewKeyedTransactor(ecdsaKey)
|
|
|
|
c.authTransactor = authTransactor
|
|
|
|
|
|
|
|
oracleEmitter, err := oracleemitter.NewSmartcontracts(common.HexToAddress(oracleEmitterContractAddress), client)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
aggregatorPlainSC, err := aggregator.NewSmartcontracts(common.HexToAddress(aggregatorContractAddress), client)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
c.oracleEmitter = &oracleemitter.SmartcontractsSession{
|
|
|
|
Contract: oracleEmitter,
|
|
|
|
CallOpts: bind.CallOpts{
|
|
|
|
Pending: true,
|
|
|
|
From: authTransactor.From,
|
|
|
|
Context: context.Background(),
|
|
|
|
},
|
|
|
|
TransactOpts: bind.TransactOpts{
|
|
|
|
From: authTransactor.From,
|
|
|
|
Signer: authTransactor.Signer,
|
|
|
|
GasLimit: 0, // 0 automatically estimates gas limit
|
|
|
|
GasPrice: nil, // nil automatically suggests gas price
|
|
|
|
Context: context.Background(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
c.aggregator = &aggregator.SmartcontractsSession{
|
|
|
|
Contract: aggregatorPlainSC,
|
|
|
|
CallOpts: bind.CallOpts{
|
|
|
|
Pending: true,
|
|
|
|
From: authTransactor.From,
|
|
|
|
Context: context.Background(),
|
|
|
|
},
|
|
|
|
TransactOpts: bind.TransactOpts{
|
|
|
|
From: authTransactor.From,
|
|
|
|
Signer: authTransactor.Signer,
|
|
|
|
GasLimit: 0, // 0 automatically estimates gas limit
|
|
|
|
GasPrice: nil, // nil automatically suggests gas price
|
|
|
|
Context: context.Background(),
|
|
|
|
},
|
|
|
|
}
|
|
|
|
return nil
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
// // Balance returns the balance of the given ethereum address.
|
|
|
|
// func (c *EthereumClient) Balance(ctx context.Context, address string) (*big.Int, error) {
|
|
|
|
// ethereumAddress := common.HexToAddress(address)
|
|
|
|
// value, err := c.HttpClient.BalanceAt(ctx, ethereumAddress, nil)
|
|
|
|
// if err != nil {
|
|
|
|
// return nil, err
|
|
|
|
// }
|
|
|
|
// return value, nil
|
|
|
|
// }
|
|
|
|
|
|
|
|
// func (c *EthereumClient) SendTransaction(ctx context.Context, private_key, to string, amount int64) string {
|
|
|
|
// privateKey, err := crypto.HexToECDSA(private_key)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to parse private key", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// publicKey := privateKey.Public()
|
|
|
|
// publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
|
|
|
// if !ok {
|
|
|
|
// c.Logger.Fatal("Cannot assert type: publicKey is not of type *ecdsa.PublicKey", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
|
|
|
|
// nonce, err := c.HttpClient.PendingNonceAt(ctx, fromAddress)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to generate wallet nonce value", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// value := big.NewInt(amount)
|
|
|
|
// gasLimit := uint64(21000) // in units
|
|
|
|
// gasPrice, err := c.HttpClient.SuggestGasPrice(ctx)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to suggest new gas price", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// toAddress := common.HexToAddress(to)
|
|
|
|
// var data []byte
|
|
|
|
// tx := types.NewTransaction(nonce, toAddress, value, gasLimit, gasPrice, data)
|
|
|
|
|
|
|
|
// chainID, err := c.HttpClient.NetworkID(ctx)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to get network ID", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// signedTx, err := types.SignTx(tx, types.NewEIP155Signer(chainID), privateKey)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to sign transaction", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// err = c.HttpClient.SendTransaction(ctx, signedTx)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to send signed transaction", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// TxHash := signedTx.Hash().Hex()
|
|
|
|
|
|
|
|
// c.Logger.Info("Transaction sent: %s", TxHash)
|
|
|
|
|
|
|
|
// return TxHash
|
|
|
|
// }
|
|
|
|
|
|
|
|
// func (c *EthereumClient) GenerateAddressFromPrivateKey(private_key string) string {
|
|
|
|
// privateKey, err := crypto.HexToECDSA(private_key)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to generate private key", err)
|
|
|
|
// }
|
|
|
|
|
|
|
|
// publicKey := privateKey.Public()
|
|
|
|
// publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
|
|
|
// if !ok {
|
|
|
|
// c.Logger.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
|
|
|
|
// }
|
|
|
|
|
|
|
|
// publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
|
|
|
|
// c.Logger.Info(hexutil.Encode(publicKeyBytes)[4:])
|
|
|
|
|
|
|
|
// address := crypto.PubkeyToAddress(*publicKeyECDSA).Hex()
|
|
|
|
|
|
|
|
// return address
|
|
|
|
// }
|
|
|
|
|
|
|
|
func (c *EthereumClient) SubscribeOnOracleEvents(incomingEventsChan chan *oracleemitter.SmartcontractsNewOracleRequest) (event.Subscription, error) {
|
|
|
|
requestsFilter := c.oracleEmitter.Contract.SmartcontractsFilterer
|
|
|
|
subscription, err := requestsFilter.WatchNewOracleRequest(&bind.WatchOpts{
|
|
|
|
Start: nil, //last block
|
|
|
|
Context: nil,
|
|
|
|
}, incomingEventsChan)
|
2020-08-03 20:01:38 +00:00
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-10-20 18:18:36 +00:00
|
|
|
return subscription, err
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
func (c *EthereumClient) SubmitRequestAnswer(reqID *big.Int, data string, callbackAddress common.Address, callbackMethodID [4]byte) error {
|
|
|
|
// privateKey, err := crypto.HexToECDSA(private_key)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal("Failed to generate private key", err)
|
|
|
|
// }
|
2020-08-04 18:19:42 +00:00
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
// publicKey := privateKey.Public()
|
|
|
|
// publicKeyECDSA, ok := publicKey.(*ecdsa.PublicKey)
|
|
|
|
// if !ok {
|
|
|
|
// c.Logger.Fatal("cannot assert type: publicKey is not of type *ecdsa.PublicKey")
|
|
|
|
// }
|
2020-08-04 18:19:42 +00:00
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
// publicKeyBytes := crypto.FromECDSAPub(publicKeyECDSA)
|
|
|
|
// c.Logger.Info(hexutil.Encode(publicKeyBytes)[4:])
|
2020-08-04 18:19:42 +00:00
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
// fromAddress := crypto.PubkeyToAddress(*publicKeyECDSA)
|
|
|
|
// nonce, err := c.HttpClient.PendingNonceAt(ctx, fromAddress)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal(err)
|
|
|
|
// }
|
2020-08-04 18:19:42 +00:00
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
// gasPrice, err := c.HttpClient.SuggestGasPrice(ctx)
|
|
|
|
// if err != nil {
|
|
|
|
// c.Logger.Fatal(err)
|
|
|
|
// }
|
2020-08-06 21:47:58 +00:00
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
_, err := c.aggregator.CollectData(reqID, data, callbackAddress, callbackMethodID)
|
2020-08-03 20:01:38 +00:00
|
|
|
if err != nil {
|
2020-10-20 18:18:36 +00:00
|
|
|
return err
|
2020-08-03 20:01:38 +00:00
|
|
|
}
|
|
|
|
|
2020-10-20 18:18:36 +00:00
|
|
|
return nil
|
2020-08-06 18:48:57 +00:00
|
|
|
}
|