Upstream sync
This commit is contained in:
132
services/blockchain/service.go
Normal file
132
services/blockchain/service.go
Normal file
@@ -0,0 +1,132 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"math/big"
|
||||
|
||||
"github.com/ethereum/go-ethereum/accounts/abi/bind"
|
||||
"github.com/ethereum/go-ethereum/common"
|
||||
"github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/ethereum/go-ethereum/ethclient"
|
||||
"github.com/ethereum/go-ethereum/log"
|
||||
"gitlab.com/pactual1/backend/config"
|
||||
blockchain "gitlab.com/pactual1/backend/services/blockchain/lib"
|
||||
)
|
||||
|
||||
type service struct {
|
||||
networkEndpoint string
|
||||
contractAddress string
|
||||
walletAddress string
|
||||
walletPrivateKey string
|
||||
chainID big.Int
|
||||
}
|
||||
|
||||
func NewService(blockchainConfig config.Blockchain) Service {
|
||||
return &service{networkEndpoint: blockchainConfig.NetworkEndpoint, contractAddress: blockchainConfig.ContractAddress, walletAddress: blockchainConfig.WalletAddress, walletPrivateKey: blockchainConfig.WalletPrivateKey}
|
||||
}
|
||||
|
||||
type Service interface {
|
||||
CreateContract(ctx context.Context, contractID [32]byte) error
|
||||
AddIOTData(ctx context.Context, contractID [32]byte, deviceID [32]byte, timestamp *big.Int, data []byte) error
|
||||
RegisterNewDeviceIDs(ctx context.Context, contractID [32]byte, deviceIDs [][32]byte) error
|
||||
}
|
||||
|
||||
func (s *service) signerFunc(address common.Address, txn *types.Transaction) (*types.Transaction, error) {
|
||||
signer := types.NewLondonSigner(&s.chainID)
|
||||
privateKey, err := crypto.HexToECDSA(s.walletPrivateKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return types.SignTx(txn, signer, privateKey)
|
||||
}
|
||||
|
||||
func (s *service) getTransactOpts() *bind.TransactOpts {
|
||||
return &bind.TransactOpts{
|
||||
From: common.HexToAddress(s.walletAddress),
|
||||
Signer: s.signerFunc,
|
||||
}
|
||||
}
|
||||
|
||||
func (s *service) getClient(ctx context.Context) (*ethclient.Client, *blockchain.Blockchain, error) {
|
||||
// connect to polygon network
|
||||
conn, err := ethclient.Dial(s.networkEndpoint)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
// create contract client
|
||||
contract, err := blockchain.NewBlockchain(common.HexToAddress(s.contractAddress), conn)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
chainID, err := conn.ChainID(ctx)
|
||||
if err != nil {
|
||||
return nil, nil, err
|
||||
}
|
||||
|
||||
s.chainID = *chainID
|
||||
return conn, contract, nil
|
||||
}
|
||||
|
||||
// track transaction to handle failure in go routine
|
||||
func (s *service) trackTransaction(txn *types.Transaction, conn *ethclient.Client) {
|
||||
receipt, err := bind.WaitMined(context.Background(), conn, txn)
|
||||
defer conn.Close()
|
||||
if err != nil {
|
||||
log.Error("blockchain transaction failed with error", "error", err.Error())
|
||||
}
|
||||
|
||||
if receipt.Status != types.ReceiptStatusSuccessful {
|
||||
log.Error("blockchain transaction not successful")
|
||||
}
|
||||
}
|
||||
|
||||
// create contract with blockchain contract ID
|
||||
func (s *service) CreateContract(ctx context.Context, contractID [32]byte) error {
|
||||
conn, contract, err := s.getClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txn, err := contract.CreateContract(s.getTransactOpts(), contractID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go s.trackTransaction(txn, conn)
|
||||
return nil
|
||||
}
|
||||
|
||||
// map devices with blockchain contract
|
||||
func (s *service) RegisterNewDeviceIDs(ctx context.Context, contractID [32]byte, deviceIDs [][32]byte) error {
|
||||
conn, contract, err := s.getClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txn, err := contract.RegisterNewDeviceIds(s.getTransactOpts(), contractID, deviceIDs)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go s.trackTransaction(txn, conn)
|
||||
return nil
|
||||
}
|
||||
|
||||
// store device data with blockchain contract
|
||||
func (s *service) AddIOTData(ctx context.Context, contractID [32]byte, deviceID [32]byte, timestamp *big.Int, data []byte) error {
|
||||
conn, contract, err := s.getClient(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
txn, err := contract.AddIOTData(s.getTransactOpts(), contractID, deviceID, timestamp, data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
go s.trackTransaction(txn, conn)
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user