package scanner
import (
"context"
"fmt"
"math/big"
"github.com/ethereum/go-ethereum"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/crypto"
)
var transferTopic = crypto.Keccak256Hash([]byte("Transfer(address,address,uint256)"))
func ScanNativeBlock(ctx context.Context, client *ethclient.Client, chainID int64, height uint64, monitored map[common.Address]bool) error {
block, err := client.BlockByNumber(ctx, new(big.Int).SetUint64(height))
if err != nil {
return err
}
for _, tx := range block.Transactions() {
if tx.To() == nil || tx.Value().Sign() == 0 || !monitored[*tx.To()] {
continue
}
receipt, err := client.TransactionReceipt(ctx, tx.Hash())
if err != nil || receipt.Status != types.ReceiptStatusSuccessful {
continue
}
key := fmt.Sprintf("%d:%s:native", chainID, tx.Hash())
if err := UpsertDeposit(key, tx.Hash(), *tx.To(), tx.Value()); err != nil {
return err
}
}
return nil
}
func ScanERC20(ctx context.Context, client *ethclient.Client, chainID int64, token common.Address, fromBlock, toBlock uint64, recipients []common.Address) error {
for _, recipient := range recipients {
query := ethereum.FilterQuery{
FromBlock: new(big.Int).SetUint64(fromBlock),
ToBlock: new(big.Int).SetUint64(toBlock),
Addresses: []common.Address{token},
Topics: [][]common.Hash{
{transferTopic},
nil,
{common.BytesToHash(recipient.Bytes())},
},
}
logs, err := client.FilterLogs(ctx, query)
if err != nil {
return err
}
for _, log := range logs {
receipt, err := client.TransactionReceipt(ctx, log.TxHash)
if err != nil || receipt.Status != types.ReceiptStatusSuccessful {
continue
}
amount := new(big.Int).SetBytes(log.Data)
key := fmt.Sprintf("%d:%s:%d:%s", chainID, log.TxHash, log.Index, token)
if err := UpsertDeposit(key, log.TxHash, recipient, amount); err != nil {
return err
}
}
}
return nil
}
func UpsertDeposit(key string, txHash common.Hash, to common.Address, amount *big.Int) error {
return nil
}