55from datetime import datetime
66import os
77from dotenv import load_dotenv
8+ import csv
9+ from pathlib import Path
810
9- # Load environment variables
1011load_dotenv ()
1112
12- # Configure logging
1313logging .basicConfig (
1414 level = logging .INFO ,
1515 format = '%(asctime)s - %(levelname)s - %(message)s'
1616)
1717logger = logging .getLogger (__name__ )
1818
19- # Contract configuration
2019CONTRACT_ADDRESS = os .getenv ('CONTRACT_ADDRESS' )
21- RPC_URL = os .getenv ('RPC_URL' ) # Your Base network RPC URL
22- PRIVATE_KEY = os .getenv ('PRIVATE_KEY' ) # Contract owner's private key
20+ RPC_URL = os .getenv ('RPC_URL' )
21+ PRIVATE_KEY = os .getenv ('PRIVATE_KEY' )
2322
24- # Load contract ABI
2523with open ('contract_abi.json' , 'r' ) as f :
2624 CONTRACT_ABI = json .load (f )
2725
2826class AgentTrumpListener :
2927 def __init__ (self ):
30- # Initialize Web3
3128 self .w3 = Web3 (Web3 .HTTPProvider (RPC_URL ))
32-
33- # Create contract instance
3429 self .contract = self .w3 .eth .contract (
3530 address = CONTRACT_ADDRESS ,
3631 abi = CONTRACT_ABI
3732 )
38-
39- # Set up account
4033 self .account = self .w3 .eth .account .from_key (PRIVATE_KEY )
41-
42- # Track the last block we processed
4334 self .last_processed_block = self .w3 .eth .block_number
4435
36+ self .csv_path = Path ('event_logs.csv' )
37+ self .json_path = Path ('event_logs.json' )
38+ self .initialize_files ()
39+
4540 logger .info (f"Initialized listener for contract: { CONTRACT_ADDRESS } " )
4641
47- async def process_response (self , player , response , timestamp ):
48- """
49- Process the player's response through the AI agent
50- """
42+ def initialize_files (self ):
43+ """Initialize CSV and JSON files"""
44+ # Initialize CSV
45+ headers = ['timestamp' , 'player' , 'response' , 'block_number' , 'transaction_hash' ]
46+ if not self .csv_path .exists ():
47+ with open (self .csv_path , 'w' , newline = '' ) as f :
48+ writer = csv .writer (f )
49+ writer .writerow (headers )
50+
51+ # Initialize JSON
52+ if not self .json_path .exists ():
53+ with open (self .json_path , 'w' ) as f :
54+ json .dump ([], f )
55+
56+ def log_event (self , event_data ):
57+ """Log event to CSV, JSON and terminal"""
58+ timestamp = datetime .fromtimestamp (event_data ['timestamp' ])
59+
60+ # Prepare event record
61+ event_record = {
62+ 'timestamp' : timestamp .isoformat (),
63+ 'player' : event_data ['player' ],
64+ 'response' : event_data ['response' ],
65+ 'block_number' : event_data ['blockNumber' ],
66+ 'transaction_hash' : event_data ['transactionHash' ].hex ()
67+ }
68+
69+ # Log to CSV
70+ with open (self .csv_path , 'a' , newline = '' ) as f :
71+ writer = csv .writer (f )
72+ writer .writerow ([
73+ timestamp ,
74+ event_record ['player' ],
75+ event_record ['response' ],
76+ event_record ['block_number' ],
77+ event_record ['transaction_hash' ]
78+ ])
79+
80+ # Log to JSON
81+ try :
82+ with open (self .json_path , 'r' ) as f :
83+ events = json .load (f )
84+ except json .JSONDecodeError :
85+ events = []
86+
87+ events .append (event_record )
88+
89+ with open (self .json_path , 'w' ) as f :
90+ json .dump (events , f , indent = 4 )
91+
92+ # Print to terminal
93+ print ("\n === New Event Detected ===" )
94+ print (f"Timestamp: { timestamp } " )
95+ print (f"Player: { event_record ['player' ]} " )
96+ print (f"Response: { event_record ['response' ]} " )
97+ print (f"Block Number: { event_record ['block_number' ]} " )
98+ print (f"Transaction Hash: { event_record ['transaction_hash' ]} " )
99+ print ("=======================\n " )
100+
101+ async def process_response (self , player , response , timestamp , block_number , tx_hash ):
102+ """Process the player's response through the AI agent"""
51103 try :
52104 logger .info (f"Processing response from { player } " )
53- logger .info (f"Response: { response } " )
54- logger .info (f"Timestamp: { datetime .fromtimestamp (timestamp )} " )
105+ self .log_event ({
106+ 'timestamp' : timestamp ,
107+ 'player' : player ,
108+ 'response' : response ,
109+ 'blockNumber' : block_number ,
110+ 'transactionHash' : tx_hash
111+ })
55112
56113 # TODO: Add your AI agent processing logic here
57114 # is_winning = await ai_agent.evaluate_response(response)
@@ -62,9 +119,7 @@ async def process_response(self, player, response, timestamp):
62119 logger .error (f"Error processing response: { e } " )
63120
64121 async def submit_winner (self , winner_address ):
65- """
66- Submit a winner to the smart contract
67- """
122+ """Submit a winner to the smart contract"""
68123 try :
69124 nonce = self .w3 .eth .get_transaction_count (self .account .address )
70125
@@ -85,25 +140,21 @@ async def submit_winner(self, winner_address):
85140 logger .error (f"Error submitting winner: { e } " )
86141
87142 async def process_events (self , events ):
88- """
89- Process a batch of events
90- """
143+ """Process a batch of events"""
91144 for event in events :
92145 player = event ['args' ]['player' ]
93146 response = event ['args' ]['response' ]
94147 timestamp = event ['args' ]['timestamp' ]
95- await self .process_response (player , response , timestamp )
148+ block_number = event ['blockNumber' ]
149+ tx_hash = event ['transactionHash' ]
150+ await self .process_response (player , response , timestamp , block_number , tx_hash )
96151
97152 async def poll_for_events (self ):
98- """
99- Poll for new GuessSubmitted events
100- """
153+ """Poll for new GuessSubmitted events"""
101154 while True :
102155 try :
103- # Get current block number
104156 current_block = self .w3 .eth .block_number
105157
106- # If new blocks exist, check for events
107158 if current_block > self .last_processed_block :
108159 events = self .contract .events .GuessSubmitted .get_logs (
109160 fromBlock = self .last_processed_block + 1 ,
@@ -116,23 +167,19 @@ async def poll_for_events(self):
116167
117168 self .last_processed_block = current_block
118169
119- # Wait before next poll
120170 await asyncio .sleep (2 )
121171
122172 except Exception as e :
123173 logger .error (f"Error polling for events: { e } " )
124174 await asyncio .sleep (5 )
125175
126176 def start (self ):
127- """
128- Start the event listener
129- """
177+ """Start the event listener"""
130178 try :
131179 asyncio .run (self .poll_for_events ())
132180 except KeyboardInterrupt :
133181 logger .info ("Shutting down listener..." )
134182
135183if __name__ == "__main__" :
136- # Create and start the listener
137184 listener = AgentTrumpListener ()
138185 listener .start ()
0 commit comments