github.com/machinefi/w3bstream@v1.6.5-rc9.0.20240426031326-b8c7c4876e72/pkg/modules/blockchain/tx.go (about)

     1  package blockchain
     2  
     3  import (
     4  	"context"
     5  	"time"
     6  
     7  	"github.com/ethereum/go-ethereum"
     8  	"github.com/ethereum/go-ethereum/common"
     9  	"github.com/pkg/errors"
    10  
    11  	"github.com/machinefi/w3bstream/pkg/depends/conf/logger"
    12  	"github.com/machinefi/w3bstream/pkg/depends/kit/logr"
    13  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/builder"
    14  	"github.com/machinefi/w3bstream/pkg/depends/kit/sqlx/datatypes"
    15  	"github.com/machinefi/w3bstream/pkg/models"
    16  	"github.com/machinefi/w3bstream/pkg/types"
    17  )
    18  
    19  type tx struct {
    20  	*monitor
    21  	interval time.Duration
    22  }
    23  
    24  func (t *tx) run(ctx context.Context) {
    25  	ticker := time.NewTicker(t.interval)
    26  	defer ticker.Stop()
    27  
    28  	for range ticker.C {
    29  		t.do(ctx)
    30  	}
    31  }
    32  
    33  func (t *tx) do(ctx context.Context) {
    34  	ctx, l := logger.NewSpanContext(ctx, "bc.tx.do")
    35  	defer l.End()
    36  
    37  	d := types.MustMonitorDBExecutorFromContext(ctx)
    38  	m := &models.ChainTx{}
    39  
    40  	cs, err := m.List(d, builder.And(m.ColFinished().Eq(datatypes.FALSE), m.ColPaused().Eq(datatypes.FALSE)))
    41  	if err != nil {
    42  		l.Error(errors.Wrap(err, "list chain tx db failed"))
    43  		return
    44  	}
    45  	for _, c := range cs {
    46  		res, err := t.checkTxAndSendEvent(ctx, &c)
    47  		if err != nil {
    48  			l.Error(errors.Wrap(err, "check chain tx and send event failed"))
    49  			continue
    50  		}
    51  		if res {
    52  			c.Finished = datatypes.TRUE
    53  			c.Uniq = c.ChainTxID
    54  			if err := c.UpdateByID(d); err != nil {
    55  				l.Error(errors.Wrap(err, "update chain tx db failed"))
    56  			}
    57  		}
    58  	}
    59  
    60  }
    61  
    62  func (t *tx) checkTxAndSendEvent(ctx context.Context, c *models.ChainTx) (bool, error) {
    63  	ctx, l := logr.Start(ctx, "bc.tx.checkTxAndSendEvent")
    64  	defer l.End()
    65  
    66  	l = l.WithValues("type", "chain_tx", "chain_tx_id", c.ChainTxID)
    67  
    68  	ethclients := types.MustETHClientConfigFromContext(ctx)
    69  
    70  	cli, ok := ethclients.Clients[uint32(c.ChainID)]
    71  	if !ok {
    72  		return false, errors.Errorf("chain id is not exist: %d", c.ChainID)
    73  	}
    74  
    75  	txhash, ispending, err := cli.TransactionByHash(context.Background(), common.HexToHash(c.TxAddress))
    76  	if err != nil {
    77  		if err == ethereum.NotFound {
    78  			l.WithValues("tx_hash", c.TxAddress).Debug("transaction not found")
    79  			return false, nil
    80  		}
    81  		l.Error(err)
    82  		return false, err
    83  	}
    84  	if ispending {
    85  		l.WithValues("tx_hash", c.TxAddress).Debug("transaction pending")
    86  		return false, nil
    87  	}
    88  	data, err := txhash.MarshalJSON()
    89  	if err != nil {
    90  		l.Error(err)
    91  		return false, err
    92  	}
    93  	if err := t.sendEvent(ctx, data, c.ProjectName, c.EventType); err != nil {
    94  		l.Error(err)
    95  		return false, err
    96  	}
    97  	return true, nil
    98  }