133 lines
3.7 KiB
Go
133 lines
3.7 KiB
Go
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
|
|
RegisterNewDeviceID(ctx context.Context, contractID [32]byte, deviceID [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) RegisterNewDeviceID(ctx context.Context, contractID [32]byte, deviceID [32]byte) error {
|
|
conn, contract, err := s.getClient(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
txn, err := contract.RegisterNewDeviceId(s.getTransactOpts(), contractID, deviceID)
|
|
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
|
|
}
|