|
| 1 | +import json |
| 2 | +import os |
| 3 | + |
| 4 | +import rel |
| 5 | +import websocket |
| 6 | + |
| 7 | +from util import ( |
| 8 | + decode_txs, |
| 9 | + get_block_events, |
| 10 | + get_block_height, |
| 11 | + get_block_txs, |
| 12 | + get_unique_event_addresses, |
| 13 | + remove_useless_data, |
| 14 | + update_latest_height, |
| 15 | +) |
| 16 | + |
| 17 | +# TODO: Save Txs & events to postgres? |
| 18 | +# maybe a redis cache as well so other people can subscribe to redis for events? |
| 19 | + |
| 20 | +# https://docs.tendermint.com/v0.34/rpc/ |
| 21 | +RPC_IP = "15.204.143.232:26657" |
| 22 | +RPC_URL = f"ws://{RPC_IP}/websocket" |
| 23 | +WALLET_PREFIX = "juno1" |
| 24 | +COSMOS_BINARY_FILE = "junod" |
| 25 | + |
| 26 | +current_dir = os.path.dirname(os.path.realpath(__file__)) |
| 27 | +blocks = os.path.join(current_dir, "blocks") |
| 28 | +os.makedirs(blocks, exist_ok=True) |
| 29 | + |
| 30 | + |
| 31 | +# TODO: get current height. If there is a difference, then we need to query the RPC for the missing blocks. |
| 32 | +latest_height_file = os.path.join(current_dir, "latest_height.txt") |
| 33 | +latest_height = -1 |
| 34 | +if os.path.exists(latest_height_file): |
| 35 | + with open(latest_height_file, "r") as f: |
| 36 | + latest_height = int(f.read()) |
| 37 | +print(f"Latest Height: {latest_height}") |
| 38 | + |
| 39 | + |
| 40 | +def on_message(ws, message): |
| 41 | + msg = dict(json.loads(message)) |
| 42 | + |
| 43 | + if msg.get("result") == {}: |
| 44 | + print("Subscribed to New Block...") |
| 45 | + return |
| 46 | + |
| 47 | + block_data = msg.get("result", {}) |
| 48 | + |
| 49 | + # Get height & save latest to file |
| 50 | + block_height = get_block_height(block_data) |
| 51 | + update_latest_height(latest_height_file, block_height) |
| 52 | + |
| 53 | + # Gets block transactions, decodes them to JSON, and saves them to the block_data |
| 54 | + block_txs = get_block_txs(block_data) |
| 55 | + decoded_txs = decode_txs(COSMOS_BINARY_FILE, block_txs) |
| 56 | + block_data["data"]["value"]["block"]["data"]["txs"] = decoded_txs |
| 57 | + |
| 58 | + # Gets unique addresses from events (users/contracts interacted with during this time frame) |
| 59 | + # Useful for cache solutions. So if a user does not have any changes here, then we can keep them cached longer |
| 60 | + block_events = get_block_events(block_data) |
| 61 | + unique_event_addresses = get_unique_event_addresses(WALLET_PREFIX, block_events) |
| 62 | + block_data["events"]["all_unique_event_addresses"] = list(unique_event_addresses) |
| 63 | + |
| 64 | + # Removes useless events we do not need to cache which take up lots of space |
| 65 | + updated_data = remove_useless_data(block_data) |
| 66 | + |
| 67 | + # Saves data to a file |
| 68 | + # TODO: learn postgres and save with relations |
| 69 | + with open(os.path.join(blocks, f"{block_height}.json"), "w") as f: |
| 70 | + f.write(json.dumps(updated_data)) |
| 71 | + |
| 72 | + |
| 73 | +def on_error(ws, error): |
| 74 | + print("error", error) |
| 75 | + |
| 76 | + |
| 77 | +def on_close(ws, close_status_code, close_msg): |
| 78 | + print("### closed ###") |
| 79 | + |
| 80 | + |
| 81 | +def on_open(ws): |
| 82 | + print("Opened connection") |
| 83 | + ws.send( |
| 84 | + '{"jsonrpc": "2.0", "method": "subscribe", "params": ["tm.event=\'NewBlock\'"], "id": 1}' |
| 85 | + ) |
| 86 | + print("Sent subscribe request") |
| 87 | + |
| 88 | + |
| 89 | +# from websocket import create_connection |
| 90 | +if __name__ == "__main__": |
| 91 | + websocket.enableTrace(False) # toggle to show or hide output |
| 92 | + ws = websocket.WebSocketApp( |
| 93 | + f"{RPC_URL}", |
| 94 | + on_open=on_open, |
| 95 | + on_message=on_message, |
| 96 | + on_error=on_error, |
| 97 | + on_close=on_close, |
| 98 | + ) |
| 99 | + |
| 100 | + ws.run_forever( |
| 101 | + dispatcher=rel, reconnect=5 |
| 102 | + ) # Set dispatcher to automatic reconnection, 5 second reconnect delay if connection closed unexpectedly |
| 103 | + rel.signal(2, rel.abort) # Keyboard Interrupt |
| 104 | + rel.dispatch() |
0 commit comments