mirror of
				https://github.com/grassrootseconomics/eth-tracker.git
				synced 2025-11-03 18:11:53 +01:00 
			
		
		
		
	feat: handle contract creation (#43)
* feat: add contract creation handler * fix: process contract creations * fix: redis keys name
This commit is contained in:
		
							parent
							
								
									4b2ad3daf9
								
							
						
					
					
						commit
						05d142664d
					
				@ -230,12 +230,12 @@ func bootstrapCache() error {
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		for _, address := range ko.MustStrings("bootstrap.watchlist") {
 | 
			
		||||
			if err := cache.Add(ctx, address); err != nil {
 | 
			
		||||
			if err := cache.Add(ctx, ethutils.HexToAddress(address).Hex()); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		for _, address := range ko.MustStrings("bootstrap.blacklist") {
 | 
			
		||||
			if err := cache.Remove(ctx, address); err != nil {
 | 
			
		||||
			if err := cache.Remove(ctx, ethutils.HexToAddress(address).Hex()); err != nil {
 | 
			
		||||
				return err
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@ -11,6 +11,8 @@ func bootstrapEventRouter(cacheProvider cache.Cache, pubCB router.Callback) *rou
 | 
			
		||||
	handlerContainer := handler.New(cacheProvider)
 | 
			
		||||
	router := router.New(pubCB)
 | 
			
		||||
 | 
			
		||||
	router.RegisterContractCreationHandler(handler.HandleContractCreation())
 | 
			
		||||
 | 
			
		||||
	router.RegisterLogRoute(w3.H("0x26162814817e23ec5035d6a2edc6c422da2da2119e27cfca6be65cc2dc55ca4c"), handler.HandleFaucetGiveLog())
 | 
			
		||||
	router.RegisterLogRoute(w3.H("0xa226db3f664042183ee0281230bba26cbf7b5057e50aee7f25a175ff45ce4d7f"), handler.HandleIndexAddLog(handlerContainer))
 | 
			
		||||
	router.RegisterLogRoute(w3.H("0x24a12366c02e13fe4a9e03d86a8952e85bb74a456c16e4a18b6d8295700b74bb"), handler.HandleIndexRemoveLog(handlerContainer))
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										4
									
								
								internal/cache/redis.go
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								internal/cache/redis.go
									
									
									
									
										vendored
									
									
								
							@ -40,8 +40,8 @@ func (c *redisCache) Remove(ctx context.Context, key string) error {
 | 
			
		||||
	return c.client.Do(ctx, cmd).Error()
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (c *redisCache) Exists(ctx context.Context, key ...string) (bool, error) {
 | 
			
		||||
	cmd := c.client.B().Exists().Key(key...).Build()
 | 
			
		||||
func (c *redisCache) Exists(ctx context.Context, keys ...string) (bool, error) {
 | 
			
		||||
	cmd := c.client.B().Exists().Key(keys...).Build()
 | 
			
		||||
	res, err := c.client.Do(ctx, cmd).AsBool()
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return false, err
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								internal/handler/contract_creation.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								internal/handler/contract_creation.go
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,28 @@
 | 
			
		||||
package handler
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"context"
 | 
			
		||||
 | 
			
		||||
	"github.com/grassrootseconomics/eth-tracker/pkg/event"
 | 
			
		||||
	"github.com/grassrootseconomics/eth-tracker/pkg/router"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
const contractCreationEventName = "CONTRACT_CREATION"
 | 
			
		||||
 | 
			
		||||
func HandleContractCreation() router.ContractCreationHandlerFunc {
 | 
			
		||||
	return func(ctx context.Context, ccp router.ContractCreationPayload, c router.Callback) error {
 | 
			
		||||
		contractCreationEvent := event.Event{
 | 
			
		||||
			Block:           ccp.Block,
 | 
			
		||||
			ContractAddress: ccp.ContractAddress,
 | 
			
		||||
			Success:         ccp.Success,
 | 
			
		||||
			Timestamp:       ccp.Timestamp,
 | 
			
		||||
			TxHash:          ccp.TxHash,
 | 
			
		||||
			TxType:          contractCreationEventName,
 | 
			
		||||
			Payload: map[string]any{
 | 
			
		||||
				"from": ccp.From,
 | 
			
		||||
			},
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		return c(ctx, contractCreationEvent)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@ -54,7 +54,7 @@ func (p *Processor) ProcessBlock(ctx context.Context, blockNumber uint64) error
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	for _, receipt := range receipts {
 | 
			
		||||
		if receipt.Status > 0 {
 | 
			
		||||
		if receipt.Status == 1 {
 | 
			
		||||
			for _, log := range receipt.Logs {
 | 
			
		||||
				exists, err := p.cache.Exists(ctx, log.Address.Hex())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
@ -72,13 +72,72 @@ func (p *Processor) ProcessBlock(ctx context.Context, blockNumber uint64) error
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		} else {
 | 
			
		||||
 | 
			
		||||
			if receipt.ContractAddress != (common.Address{}) {
 | 
			
		||||
				tx, err := p.chain.GetTransaction(ctx, receipt.TxHash)
 | 
			
		||||
				if err != nil && !errors.Is(err, context.Canceled) {
 | 
			
		||||
					return fmt.Errorf("get transaction error: tx %s: %v", receipt.TxHash.Hex(), err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return fmt.Errorf("transaction decode error: tx %s: %v", receipt.TxHash.Hex(), err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				exists, err := p.cache.Exists(ctx, from.Hex())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
				if exists {
 | 
			
		||||
					if err := p.router.ProcessContractCreation(
 | 
			
		||||
						ctx,
 | 
			
		||||
						router.ContractCreationPayload{
 | 
			
		||||
							From:            from.Hex(),
 | 
			
		||||
							Block:           blockNumber,
 | 
			
		||||
							ContractAddress: receipt.ContractAddress.Hex(),
 | 
			
		||||
							Timestamp:       block.Time(),
 | 
			
		||||
							TxHash:          receipt.TxHash.Hex(),
 | 
			
		||||
							Success:         true,
 | 
			
		||||
						},
 | 
			
		||||
					); err != nil && !errors.Is(err, context.Canceled) {
 | 
			
		||||
						return fmt.Errorf("route success contract creation error: tx %s: %v", receipt.TxHash.Hex(), err)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		if receipt.Status == 0 {
 | 
			
		||||
			tx, err := p.chain.GetTransaction(ctx, receipt.TxHash)
 | 
			
		||||
			if err != nil && !errors.Is(err, context.Canceled) {
 | 
			
		||||
				return fmt.Errorf("get transaction error: tx %s: %v", receipt.TxHash.Hex(), err)
 | 
			
		||||
			}
 | 
			
		||||
			if tx.To() == nil {
 | 
			
		||||
				from, err := types.Sender(types.LatestSignerForChainID(tx.ChainId()), tx)
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return fmt.Errorf("transaction decode error: tx %s: %v", receipt.TxHash.Hex(), err)
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
			if tx.To() != nil {
 | 
			
		||||
				exists, err := p.cache.Exists(ctx, from.Hex())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
				}
 | 
			
		||||
 | 
			
		||||
				if exists {
 | 
			
		||||
					if err := p.router.ProcessContractCreation(
 | 
			
		||||
						ctx,
 | 
			
		||||
						router.ContractCreationPayload{
 | 
			
		||||
							From:            from.Hex(),
 | 
			
		||||
							Block:           blockNumber,
 | 
			
		||||
							ContractAddress: receipt.ContractAddress.Hex(),
 | 
			
		||||
							Timestamp:       block.Time(),
 | 
			
		||||
							TxHash:          receipt.TxHash.Hex(),
 | 
			
		||||
							Success:         false,
 | 
			
		||||
						},
 | 
			
		||||
					); err != nil && !errors.Is(err, context.Canceled) {
 | 
			
		||||
						return fmt.Errorf("route reverted contract creation error: tx %s: %v", receipt.TxHash.Hex(), err)
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
			} else {
 | 
			
		||||
				exists, err := p.cache.Exists(ctx, tx.To().Hex())
 | 
			
		||||
				if err != nil {
 | 
			
		||||
					return err
 | 
			
		||||
 | 
			
		||||
@ -25,8 +25,18 @@ type (
 | 
			
		||||
		TxHash          string
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LogHandlerFunc       func(context.Context, LogPayload, Callback) error
 | 
			
		||||
	InputDataHandlerFunc func(context.Context, InputDataPayload, Callback) error
 | 
			
		||||
	ContractCreationPayload struct {
 | 
			
		||||
		From            string
 | 
			
		||||
		ContractAddress string
 | 
			
		||||
		Block           uint64
 | 
			
		||||
		Timestamp       uint64
 | 
			
		||||
		TxHash          string
 | 
			
		||||
		Success         bool
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	LogHandlerFunc              func(context.Context, LogPayload, Callback) error
 | 
			
		||||
	InputDataHandlerFunc        func(context.Context, InputDataPayload, Callback) error
 | 
			
		||||
	ContractCreationHandlerFunc func(context.Context, ContractCreationPayload, Callback) error
 | 
			
		||||
 | 
			
		||||
	LogRouteEntry struct {
 | 
			
		||||
		Signature   common.Hash
 | 
			
		||||
@ -39,17 +49,19 @@ type (
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	Router struct {
 | 
			
		||||
		callbackFn        Callback
 | 
			
		||||
		logHandlers       map[common.Hash]LogRouteEntry
 | 
			
		||||
		inputDataHandlers map[string]InputDataEntry
 | 
			
		||||
		callbackFn              Callback
 | 
			
		||||
		logHandlers             map[common.Hash]LogRouteEntry
 | 
			
		||||
		inputDataHandlers       map[string]InputDataEntry
 | 
			
		||||
		contractCreationHandler ContractCreationHandlerFunc
 | 
			
		||||
	}
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
func New(callbackFn Callback) *Router {
 | 
			
		||||
	return &Router{
 | 
			
		||||
		callbackFn:        callbackFn,
 | 
			
		||||
		logHandlers:       make(map[common.Hash]LogRouteEntry),
 | 
			
		||||
		inputDataHandlers: make(map[string]InputDataEntry),
 | 
			
		||||
		callbackFn:              callbackFn,
 | 
			
		||||
		logHandlers:             make(map[common.Hash]LogRouteEntry),
 | 
			
		||||
		inputDataHandlers:       make(map[string]InputDataEntry),
 | 
			
		||||
		contractCreationHandler: nil,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -67,6 +79,10 @@ func (r *Router) RegisterInputDataRoute(signature string, handlerFunc InputDataH
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Router) RegisterContractCreationHandler(handlerFunc ContractCreationHandlerFunc) {
 | 
			
		||||
	r.contractCreationHandler = handlerFunc
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Router) ProcessLog(ctx context.Context, payload LogPayload) error {
 | 
			
		||||
	handler, ok := r.logHandlers[payload.Log.Topics[0]]
 | 
			
		||||
	if ok {
 | 
			
		||||
@ -88,3 +104,7 @@ func (r *Router) ProcessInputData(ctx context.Context, payload InputDataPayload)
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (r *Router) ProcessContractCreation(ctx context.Context, payload ContractCreationPayload) error {
 | 
			
		||||
	return r.contractCreationHandler(ctx, payload, r.callbackFn)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user