Crawler Flow

1. tools/crawler.js

1.1. Connect to Provider

// Connect to the specified network using the configured provider (web3.eth)
await getProvider(network);
config에서 설정한 network를 가져와서 provider(web3.eth)를 연결합니다.

// Update node state in the database
updateNodeState(network, 1);
provider가 정상적으로 연결되면 database에 nodes_table에 네트워크에 맞는 node_state를 1로 업데이트합니다.
연결 실패 시 상태는 0으로 다시 설정됩니다.

// Get the last synced block number of the node
let nLastBlockNum = await getLastBlockNumber(provider);
node의 싱크완료된 마지막 제일 최신 블록 번호를 가져옵니다.

// Handle the initial state
await getFirstState(network);
제일 첫 시작 시 이전에 종료 시 수집하지 못한 블록이 있을 경우를 대비하여 crawler_table에 crawled_block_number를 2씩 줄입니다.

// Get next state from the crawler table
[next, state] = await getNextState(network, nLastBlockNum-7);
crawler_table에 crawled_block_number를 가져와서 next에 넣어주고 데이터베이스 연결상태를확인하여 연결이 정상적이면 state 1 아니면 0을 가져옵니다

2. lib/crawler.js

2.1. Gather Block Information

// Get block information and transaction receipts for the specified block number
await block_gatherer.getBlock(provider, blockNumber);
provider를 이용하여 현재 수집할 블록 넘버의 블록 정보와 TransactionReceipt(상세 정보)를 가져옵니다.

// Parse and collect Deploy and Transfer information
await block_parser.parseBlock(network, provider, block);
Deploy 및 Transfer 정보를 수집합니다.

// Parse and collect Sale information
await block_trader_parser.parseBlock(network, provider, block);
Sale 정보를 수집합니다.

3. lib/parser.js

3.1. Parse Transaction Receipts

// Parse transaction receipts for the specified network, provider, and block
await parseTransactionReceipts(network, provider, block);
getBlock 함수로 가져온 TransactionReceipt를 하나씩 parseTransactionReceipt 함수로 전달합니다.

// Parse Deploy information
await parseTransactionDetails(network, provider, block_timestamp, receipt);
Deploy 정보를 수집합니다.

// Parse Sale information
await block_trader_parser.parseBlock(network, provider, block);
Sale정보를 수집합니다.

await parseTransactionDetails(network, provider, block_timestamp, receipt);
Deploy정보를 수집합니다
블록정보 안에 contractAddress가 존재하고 from만 존재하면 Deploy 데이터입니다.
네이티브 코인정보를 수집합니다(현재는 토큰수집안해서 주석처리)
Deploy정보가아닌 모든 데이터

3.2. Parse Logs

await parseLogs(network, provider, block_timestamp, receipt);
먼저 receipt 안에 logs를 한 줄씩 파싱합니다.

isNoneStandardNft()는 erc721, erc1155이 등장하기 전 NFT로 인정받고있는 크립토 키티와 크립토 펑크 를 예외사항으로 수집하기 위해서 추가하였습니다.

if(log.topics[0].toLowerCase() === "0x2771bca31dd40ca5838bfc40fc5063e49ff49235e90223669dc5d81916e52d04")
이것은 저희 컨트렉트를 통한 deploy시 deploy_date와 creator를 수집하기위해 넣었습니다. (저희 deploy는 contract를 통해 배포하기 때문에 from to(소장님브릿지)가 전부 존재해서 deploy데이터로 잡히지 않아서 수동으로 추가해줬습니다.)

if (log.topics[0].toUpperCase() === contract_abi.funcTransfer.toUpperCase())
logs의 topics 0번 signature가 transfer 함수이면 조건문을 탑니다
erc20, erc721은 동일한 함수를 사용해서 topics의 Length와  supportsInterface로 구별합니다 erc20(3) erc721(4)
erc 1155 는 tranferSingle과 transferBatch함수를 독자적으로 수집합니다.

3.3. Parse NFT Information

// Parse ERC721, ERC1155 information
parseERC721(), parseERC1155Single(), parseERC1155Batch()
컨트랙트 주소로 컨트랙트를 연결하여 이름, 심볼 등을 조회하고 nft_collection_table에 존재 여부를 확인하고 없으면 insert해줍니다.
그 후 nft_token_table과 nft_transaction_table을 insert합니다.

4. lib/tradeParser.js

4.1. Parse Market Data

// Parse market data from transaction receipts
await parseTransactionReceipts(network, provider, block);
getBlock 함수로 가져온 TransactionReceipt를 하나씩 parseTransactionReceipt 함수로 전달합니다.

// Determine the market based on the function signature in logs
let market = getMarket(receipt);
logs의 topics 0번 signature가 각 마켓에서 사용하는 함수를 포함하고 있으면 해당 함수에 맞는 마켓을 반환합니다.

4.2. Analyze Market Functions

// Analyze data for each market function
parsePala(), parseOpenSeaTrade() 등등
각 마켓 함수의 데이터를 분석합니다. 각 함수마다 정보가 있는 위치가 다르므로 코드를 참조합니다.

Last updated