import time
from web3 import Web3
from web3.middleware import ExtraDataToPOAMiddleware
# Chainstack Zora mainnet endpoint
ZORA_RPC = "YOUR_CHAINSTACK_HTTP_ENDPOINT"
# Exclude these tokens (USDzC and WETH)
EXCLUDED_TOKENS = {
"0xCccCCccc7021b32EBb4e8C08314bD62F7c653EC4".lower(), # USDzC
"0x4200000000000000000000000000000000000006".lower(), # WETH
}
# Standard ERC-20 ABI fragments
ERC20_ABI = [
{
"anonymous": False,
"inputs": [
{"indexed": True, "name": "from", "type": "address"},
{"indexed": True, "name": "to", "type": "address"},
{"indexed": False, "name": "value", "type": "uint256"},
],
"name": "Transfer",
"type": "event",
},
{"constant": True, "inputs": [], "name": "name", "outputs": [{"name": "", "type": "string"}], "type": "function"},
{"constant": True, "inputs": [], "name": "symbol", "outputs": [{"name": "", "type": "string"}], "type": "function"},
{"constant": True, "inputs": [], "name": "decimals", "outputs": [{"name": "", "type": "uint8"}], "type": "function"},
]
# Connect to Zora mainnet
w3 = Web3(Web3.HTTPProvider(ZORA_RPC))
# Zora is OP Stack, so it needs POA middleware
w3.middleware_onion.inject(ExtraDataToPOAMiddleware, layer=0)
print(f"Connected to Zora: {w3.is_connected()}")
# Get the Transfer event signature hash
TRANSFER_EVENT_SIG = "0x" + w3.keccak(text="Transfer(address,address,uint256)").hex()
# Track seen token addresses
seen_tokens = set()
# Helper to get token info
def get_token_info(token_address):
# Convert to checksum address for web3.py compatibility
checksum_address = Web3.to_checksum_address(token_address)
contract = w3.eth.contract(address=checksum_address, abi=ERC20_ABI)
try:
name = contract.functions.name().call()
except Exception:
name = "?"
try:
symbol = contract.functions.symbol().call()
except Exception:
symbol = "?"
try:
decimals = contract.functions.decimals().call()
except Exception:
decimals = "?"
return name, symbol, decimals
# Start from latest block
start_block = w3.eth.block_number
print(f"Starting from block {start_block}")
while True:
latest_block = w3.eth.block_number
for block_num in range(start_block, latest_block + 1):
block = w3.eth.get_block(block_num, full_transactions=False)
logs = w3.eth.get_logs({
"fromBlock": block_num,
"toBlock": block_num,
"topics": [TRANSFER_EVENT_SIG],
})
for log in logs:
token_address = log["address"].lower()
if token_address in EXCLUDED_TOKENS:
continue
# Only fetch token info once per token
if token_address not in seen_tokens:
name, symbol, decimals = get_token_info(token_address)
seen_tokens.add(token_address)
print(f"\nNew token detected: {token_address}")
print(f" Name: {name}")
print(f" Symbol: {symbol}")
print(f" Decimals: {decimals}")
# Parse transfer event
from_addr = "0x" + log["topics"][1].hex()[-40:]
to_addr = "0x" + log["topics"][2].hex()[-40:]
value = int.from_bytes(log["data"].rjust(32, b"\x00"), byteorder="big")
print(f"Transfer | Token: {token_address} | From: {from_addr} | To: {to_addr} | Value: {value}")
start_block = latest_block + 1
time.sleep(2)