인프런 커뮤니티 질문&답변

JUNI님의 프로필 이미지
JUNI

작성한 질문수

스마트 컨트랙트 이벤트 모듈 배우고 학습하기

Transfer Topic, Data 값 파싱하기

needToCatchEvent 오류

해결된 질문

작성

·

325

0

event Transfer 감지가 안되고 있습니다.

오타확인했을 경우에도 문제가 없었음에도 불구하고 질무드립니다.


c.needToCatchEvent = map[common.Hash]types.NeedToCatchEvent{ common.BytesToHash(crypto.Keccak256([]byte("Transfer(address,address,uint256"))): { NeedToCatchEventFunc: c.Transfer, }, }

 

코드는 이렇게 됩니다.

추가적으로 address는 0xbB9260Fc0d1427B7A014B6993D84e75f88Cd700C

mint 블록 44961870 입니다.

답변 3

0

JUNI님의 프로필 이미지
JUNI
질문자

네 디버깅하면서 logs가 안들어오는 것까지 확인을 했습니다.
그런데 어디 부터 잘못되는지 확인이 불가능합니다.

혹시 git에 소스코드 공유 부탁드려도 될까요?

package event

import (
	"context"
	"event/config"
	"fmt"
	"math/big"
	"time"

	"github.com/ethereum/go-ethereum"
	"github.com/ethereum/go-ethereum/common"
	ethType "github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/ethclient"
)

type Scan struct {
	config *config.Config

	FilterQuery ethereum.FilterQuery
	client      *ethclient.Client
}

func NewScan(config *config.Config, client *ethclient.Client, catchEventList []common.Hash) (*Scan, chan []ethType.Log, error) {
	s := &Scan{
		config: config,
		client: client,
	}

	eventLog := make(chan []ethType.Log, 100)

	scanCallection := common.HexToAddress("0x97D6Aba16E92d82A58519C452c006e4058A631D7")

	go s.lookingScan(config.Node.StartBlock, scanCallection, catchEventList, eventLog)

	return s, eventLog, nil
}

//44961870
// 배포 : 44961732

func (s *Scan) lookingScan(startBlock int64, scanCallection common.Address, catchEventList []common.Hash, eventLog chan<- []ethType.Log) {
	startReadtBlock, to := startBlock, uint64(0)

	s.FilterQuery = ethereum.FilterQuery{
		Addresses: []common.Address{scanCallection},
		Topics:    [][]common.Hash{catchEventList},
		FromBlock: big.NewInt(startReadtBlock),
	}

	for {
		time.Sleep(1e8)

		ctx := context.Background()

		if maxBlock, err := s.client.BlockNumber(ctx); err != nil {
			fmt.Println("Get BlockNumber", "err", err.Error())
		} else {
			to = maxBlock

			if to > uint64(startBlock) {
				fmt.Println("from Block", s.FilterQuery.ToBlock, "to Block", to)
				s.FilterQuery.ToBlock = big.NewInt(int64(to))
				s.FilterQuery.FromBlock = big.NewInt(startReadtBlock)

				tryCount := 1

				fmt.Println("s.FilterQuery : ", s.FilterQuery)

			Retry:
				if logs, err := s.client.FilterLogs(ctx, s.FilterQuery); err != nil {

					if tryCount == 3 {
						fmt.Println("failed to get Filter", "err", err.Error())
						break
					} else {
						newTo := big.NewInt(int64(to) - 1)
						newFrom := big.NewInt(startBlock - 1)

						s.FilterQuery.ToBlock = newTo
						s.FilterQuery.FromBlock = newFrom

						tryCount++

						goto Retry
					}

				} else if len(logs) > 0 {
					eventLog <- logs
					startReadtBlock = int64(to)
				}
			}
		}
	}
}



s.FilterQuery : {<nil> 44961732 52617540 [0x97D6Aba16E92d82A58519C452c006e4058A631D7] [[0xd99659a21de82e379975ce8df556f939a4ccb95e92144f38bb0dd35730ffcdd5]]}

from Block 52617540 to Block 52617540

s.FilterQuery : {<nil> 44961732 52617540 [0x97D6Aba16E92d82A58519C452c006e4058A631D7] [[0xd99659a21de82e379975ce8df556f939a4ccb95e92144f38bb0dd35730ffcdd5]]}

from Block 52617540 to Block 52617541

s.FilterQuery : {<nil> 44961732 52617541 [0x97D6Aba16E92d82A58519C452c006e4058A631D7] [[0xd99659a21de82e379975ce8df556f939a4ccb95e92144f38bb0dd35730ffcdd5]]}

from Block 52617541 to Block 52617541

s.FilterQuery : {<nil> 44961732 52617541 [0x97D6Aba16E92d82A58519C452c006e4058A631D7] [[0xd99659a21de82e379975ce8df556f939a4ccb95e92144f38bb0dd35730ffcdd5]]}

from Block 52617541 to Block 52617542

s.FilterQuery : {<nil> 44961732 52617542 [0x97D6Aba16E92d82A58519C452c006e4058A631D7] [[0xd99659a21de82e379975ce8df556f939a4ccb95e92144f38bb0dd35730ffcdd5]]}

from Block 52617542 to Block 52617542

s.FilterQuery : {<nil> 44961732 52617542 [0x97D6Aba16E92d82A58519C452c006e4058A631D7] [[0xd99659a21de82e379975ce8df556f939a4ccb95e92144f38bb0dd35730ffcdd5]]}

exit status 0xc000013a

s.FilterQuery는 잘 들어오고 있는것 같은데 nil은 정상적인거죠?

July님의 프로필 이미지
July
지식공유자

Filter쿼리 로그를 찍으셨기 떄문에, 해당 구조체에서 초기화 되어있지 않은 값은 Nil로 나오게 될 겁니다.

저희가 사용해야 하는

Addresses, Topics, FromBlock값만 nil이 아니면 됩니다.

제가 퍼블릭 레파지토리를 따로 활용을 안할 예정이라서.. 강의 마지막 챕터에 소스코드를 압축해서 올려두겠습니다.

여러가지 작업을 했던거라, 강의에 사용되었던 소스코드가 맞는지는 모르겠는데 일단 확인 결과 맞는걸로 보이니깐 해당 코드를 참고하시면 좋을꺼같습니다.




소스코드를 업로드 하였지만, 잘못된 공부 방향인거 같아서. 다시 댓글을 수정하게 되었습니다.
저는 기본적으로 일단 모두 해보고 실제로 디버깅을 해보는게 맞다고 생각을 하는 주의입니다. 그래서 모두가 볼 수 있는 공간에 소스코드를 업로드하면, 다른 분들도 쉽게 접해서 이해하지 못하고 코드만 보고 따라할 수 있다는 생각이 들어서

따로 저에게 메일을 보내주시면, 해당 메일로 소스코드를 질문자님에게 전송해 드리는게 더 좋은 방향이라는 생각이 들었습니다.
괜찮으시다면, sdl155@naver.com 으로 메일 주시면, 소스코드를 전달해드리도록 하겠습니다.

혼동을 드려서 죄송합니다.

0

JUNI님의 프로필 이미지
JUNI
질문자

package event

import (
	"context"
	"event/config"
	"event/types"
	"fmt"

	"github.com/ethereum/go-ethereum/common"
	ethType "github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/crypto"
	"github.com/ethereum/go-ethereum/ethclient"
)

type Catch struct {
	config           *config.Config
	client           *ethclient.Client
	needToCatchEvent map[common.Hash]types.NeedToCatchEvent
}

func NewCatch(config *config.Config, client *ethclient.Client) (*Catch, error) {
	c := &Catch{
		config: config,
		client: client,
	}

	c.needToCatchEvent = map[common.Hash]types.NeedToCatchEvent{
		common.BytesToHash(crypto.Keccak256([]byte("Transfer(address,address,uint256"))): {
			NeedToCatchEventFunc: c.Transfer,
		},
	}

	return c, nil
}

func (c *Catch) Transfer(e *ethType.Log, tx *ethType.Transaction) {
	fmt.Println("들어 왔습니다.")
}

// start To Catch Event
func (c *Catch) StartToCatch(events <-chan []ethType.Log) {
	fmt.Println("Event가 들어 왔습니다.")

	for event := range events {
		ctx := context.Background()
		txList := make(map[common.Hash]*ethType.Transaction)

		for _, e := range event {
			Hash := e.TxHash

			if _, ok := txList[Hash]; !ok {
				if tx, pending, err := c.client.TransactionByHash(ctx, Hash); err == nil {
					if !pending {
						txList[Hash] = tx
					}
				}
			}

			if e.Removed {
				continue
			} else if et, ok := c.needToCatchEvent[e.Topics[0]]; !ok {

			} else {
				et.NeedToCatchEventFunc(&e, txList[Hash])
			}

			//e.Topics[0]

		}
	}
}

func (c *Catch) GetEventsToCatch() []common.Hash {
	eventsToCatch := make([]common.Hash, 0)

	for e := range c.needToCatchEvent {
		eventsToCatch = append(eventsToCatch, e)
	}

	return eventsToCatch
}
package app

import (
	"event/config"
	"event/event"
	repostory "event/repository"

	ethType "github.com/ethereum/go-ethereum/core/types"
	"github.com/ethereum/go-ethereum/ethclient"
)

type App struct {
	config *config.Config

	client *ethclient.Client

	repostory *repostory.Repostory
	scan      *event.Scan
	catch     *event.Catch
}

func NewApp(config *config.Config) {
	a := App{
		config: config,
	}

	var err error

	if a.client, err = ethclient.Dial(config.Node.Uri); err != nil {
		panic(err)
	} else {
		if a.repostory, err = repostory.NewRepostory(config); err != nil {
			panic(err)
		}

		if a.catch, err = event.NewCatch(config, a.client); err != nil {
			panic(err)
		}

		var eventChan chan []ethType.Log

		if a.scan, eventChan, err = event.NewScan(config, a.client, a.catch.GetEventsToCatch()); err != nil {
			panic(err)
		}

		go a.catch.StartToCatch(eventChan)

		for {

		}
	}
}

에러 코드는 없었습니다.
트랜잭션을 전송하셨는지 질문을 드렸는데?
mumbai에 트랜잭션을 말씀하신건가요? => 테스트넷에서
0x9f878a0a73a53dd676d4f9ec58b823ab9130df335c8b38b4df8ac2d15f49adee 검색할 수 있는 트랜잭션 해쉬 코드 입니다.

실행 했을때의 로그입니다,

Event가 들어 왔습니다.

from Block <nil> to Block 52533290

from Block 52533290 to Block 52533290

from Block 52533290 to Block 52533291

exit status 0xc000013a

July님의 프로필 이미지
July
지식공유자

네 정보 감사합니다.!

트랜잭션이 들어왔고, 제대로 읽었지만,
needToCatchEvent 라는 변수 값에 해당 값을 읽을 수 없을 수 있을꺼 같습니다.

et, ok := c.needToCatchEvent[e.Topics[0]]; !ok


해당 로직 내부에 로그를 찍어보시고, 해당 로그가 찍힌다면,
needToCatchEvent를 선언하는 곳이 잘못된것으로 확인이 가능합니다.


일단 로직 자체가 동작을 하지 않는것은 아니니 큰 문제는 아니고, 각각의 변수값들을 초기화하는 부분을 다시 살펴보시면 좋을꺼 같아요.

추가로 제가 마지막쯤에 실제 실행을 하면서 디버깅을 했던 영상이 있을텐데, 해당 영상도 한번 참고해보시는것도 좋을거 같습니다.!!

0

July님의 프로필 이미지
July
지식공유자

음 혹시 추가적인 정보를 얻을 수 있을까요?

에러코드라든지 트랜잭션을 전송하셨는지

추가적인 정보가 필요합니다.

 

 

블럭 넘버에 대한 값을 보내주신걸보니 트랜재션은 성공한걸로 보입니다.

 

아마도 채널값에서 초기화하기 전에 이벤트를 잡으려고 하셔서 그런걸로 보입니다.

 

컨트랙트 또는 app.go에 있는 코드 보내주시면 답변해드리는데에 있어서 도움을 드릴 수 있을거 같아요!!!

JUNI님의 프로필 이미지
JUNI

작성한 질문수

질문하기