Hello world! At the end of my latest previous article I finished in a pretty desperated state of mind I have to admit it. But, the world keeps spinning, and good or bad things will keep happening, and this is new day, etc. So here I am again, experimenting stuff š . But for the moment I'm a bit tired of the Binance Smart Chain, so I'm starting to check other blockchains just in case things would be different there, and the first one on my āalternate blockchainsā list is CELO. Lets' see what we have there!
2022/06/16 05:31:36 [__main__] INFO: 31 pair reserves collected in 0.1689 secs 2022/06/16 05:34:00 [__main__] INFO: Block age: 1.033694 2022/06/16 05:34:00 [__main__] INFO: 18 pair reserves collected in 0.1519 secs 2022/06/16 05:35:27 [__main__] INFO: Block age: 1.271724 2022/06/16 05:36:21 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002357E7325F0>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:34 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x0000023519043310>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:36 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x0000023519042380>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:38 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x0000023519043310>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:40 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002351BBA5E40>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:42 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002351BBA5CF0>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:44 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002351BBA6050>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:46 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002351BBA4B80>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:36:59 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002351BBA7A60>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) 2022/06/16 05:37:01 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'getDualReserves' (on 0x...): HTTPSConnectionPool(host='bsc-dataseed1.binance.org', port=443): Max retries exceeded with url: / (Caused by NewConnectionError('<urllib3.connection.HTTPSConnection object at 0x000002351BBA7D90>: Failed to establish a new connection: [Errno 11001] getaddrinfo failed')) Traceback (most recent call last): File "D:\Projects\NervHome\nvh\crypto\blockchain\arbitrage_manager.py", line 975, in <module> comp.run() File "D:\Projects\NervProj\nvp\nvp_component.py", line 81, in run res = self.process_command(cmd) File "D:\Projects\NervHome\nvh\crypto\blockchain\arbitrage_manager.py", line 930, in process_command self.monitor_arbitrages(chain) File "D:\Projects\NervHome\nvh\crypto\blockchain\arbitrage_manager.py", line 124, in monitor_arbitrages result = self.handle_arbitrage_setups() File "D:\Projects\NervHome\nvh\crypto\blockchain\arbitrage_manager.py", line 275, in handle_arbitrage_setups pair_reserves, block_ref = self.get_all_reserves(paddrs) File "D:\Projects\NervHome\nvh\crypto\blockchain\arbitrage_manager.py", line 760, in get_all_reserves result = self.dual_reserves_sc.call_function("getDualReserves", paddrs) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_smart_contract.py", line 139, in call_function self.throw("Cannot execute SmartContract function %s correctly", fname) File "D:\Projects\NervProj\nvp\nvp_object.py", line 73, in throw raise NVPCheckError(fmt % args) nvp.nvp_object.NVPCheckError: Cannot execute SmartContract function getDualReserves correctly 2022/06/16 05:37:04 [nvp.communication.email_handler] INFO: Should send the email message <p style="color: #fd0202;">**WARNING:** an exception occured in the following command:</p><p><em>['D:\\Projects\\NervProj\\.pyenvs\\bsc_env\\python.exe', 'D:\\Projects\\NervHome/nvh/crypto/blockchain/arbitrage_manager.py', 'monitor-arbs']</em></p><p>cwd=None</p><p >=> Check the logs for details.</p> 2022/06/16 05:37:06 [nvp.components.runner] ERROR: Error occured in script command: ['D:\\Projects\\NervProj\\.pyenvs\\bsc_env\\python.exe', 'D:\\Projects\\NervHome/nvh/crypto/blockchain/arbitrage_manager.py', 'monitor-arbs'] (cwd=None)
execute()
method: def execute(self, cmd, **kwargs): """Execute a command optionally displaying the outputs.""" verbose = kwargs.get("verbose", True) cwd = kwargs.get("cwd", None) env = kwargs.get("env", None) check = kwargs.get("check", True) outfile = kwargs.get("outfile", None) print_outputs = kwargs.get("print_outputs", True) output_buffer = kwargs.get("output_buffer", None) # stdout = None if verbose else subprocess.DEVNULL # stderr = None if verbose else subprocess.DEVNULL stdout = subprocess.PIPE if verbose else subprocess.DEVNULL stderr = subprocess.PIPE if verbose else subprocess.DEVNULL if outfile is not None: stdout = outfile # cf. https://stackoverflow.com/questions/31833897/ # python-read-from-subprocess-stdout-and-stderr-separately-while-preserving-order def reader(pipe, queue, id): """Reader function for a stream""" try: with pipe: for line in iter(pipe.readline, b''): queue.put((id, line.decode('utf-8'))) finally: queue.put(None) # logger.info("Executing command: %s", cmd) try: proc = subprocess.Popen(cmd, stdout=stdout, stderr=stderr, cwd=cwd, env=env, bufsize=1) if verbose and (print_outputs or outfile is not None): myq = Queue() Thread(target=reader, args=[proc.stdout, myq, 0]).start() Thread(target=reader, args=[proc.stderr, myq, 1]).start() for _ in range(2): for _source, line in iter(myq.get, None): if print_outputs: # print(f"{source}: {line.strip()}") print(line.strip()) if output_buffer is not None: output_buffer.append(line.strip()) if outfile is not None: outfile.write(line) logger.info("Waiting for subprocess to finish...") proc.wait() logger.info("Returncode: %d", proc.returncode) if check and proc.returncode < 0: raise NVPCheckError(f"Subprocess terminated with error code {proc.returncode} (cmd={cmd})") # if check: # subprocess.check_call(cmd, stdout=stdout, stderr=stderr, cwd=cwd, env=env) # else: # subprocess.run(cmd, stdout=stdout, stderr=stderr, cwd=cwd, env=env, check=False) except KeyboardInterrupt: logger.info("Subprocess was interrupted.")
$ nvp arbman monitor-arbs 2022/06/16 09:19:02 [py.warnings] WARNING: D:\Projects\NervProj\tools\windows\python-3.10.1\lib\subprocess.py:956: RuntimeWarning: line buffering (buffering=1) isn't supported in binary mode, the default buffer size will be used self.stdout = io.open(c2pread, 'rb', bufsize) 2022/06/16 09:19:02 [py.warnings] WARNING: D:\Projects\NervProj\tools\windows\python-3.10.1\lib\subprocess.py:961: RuntimeWarning: line buffering (buffering=1) isn't supported in binary mode, the default buffer size will be used self.stderr = io.open(errread, 'rb', bufsize) 2022/06/16 09:19:08 [nvh.crypto.blockchain.evm_blockchain] INFO: Keeping 1123413/1143549 quotable pairs.
bufsize=1
i'm passing to popen: according to the doc (https://docs.python.org/3/library/subprocess.html):# Execute that command: logger.debug("Executing script command: %s (cwd=%s)", cmd, cwd) auto_restart = desc.get("auto_restart", False) notify = self.config.get("notify_script_errors", True) while True: success, rcode, outputs = self.execute(cmd, cwd=cwd, env=env) if not success: outs = "\n".join(outputs) logger.error( "Error occured in script command:\ncmd=%s\ncwd=%s\nreturn code=%s\nlastest outputs:\n%s", cmd, cwd, rcode or "None", outs) if not success and notify: # And exception occured in the sub process, so we should send a notification: msg = ":warning: **WARNING:** an exception occured in the following command:\n" msg += f"{cmd}\n" msg += f"cwd={cwd}\n\n" msg += "=> Check the logs for details." rchat = self.get_component("rchat") rchat.send_message(msg, channel="problem-reports") msg = "<p style=\"color: #fd0202;\">**WARNING:** an exception occured in the following command:</p>" msg += f"<p><em>{cmd}</em></p>" msg += f"<p>cwd={cwd}</p>" msg += "<p >=> Check the logs for details.</p>" email = self.get_component("email") email.send_message("[NervProj] Exception notification", msg) if success or not auto_restart: break
"monitor_bsc_arbs": { "custom_python_env": "bsc_env", "auto_restart": true, "log_file": "${PROJECT_ROOT_DIR}/monitor_bsc_arbs.log", "cmd": "${PYTHON} ${PROJECT_ROOT_DIR}/nvh/crypto/blockchain/arbitrage_manager.py monitor-arbs -c bsc", "python_path": ["${PROJECT_ROOT_DIR}", "${NVP_ROOT_DIR}"] },
"celo_chain": "nvh.crypto.blockchain.evm_blockchain:celo",
from nvp.nvp_context import NVPContext import numpy as np from hexbytes import HexBytes import matplotlib.pyplot as plt if NVPContext.instance is None: NVPContext() ctx = NVPContext.get() chain = ctx.get_component('celo_chain') db = chain.get_db() bck = chain.get_block('latest', full_tx=True) # bck = chain.get_block('pending', full_tx=True) # print(f"Current timestamp: {chain.get_timestamp()}") bnum = bck['number'] ts = bck['timestamp'] ntx = len(bck["transactions"]) print(f"Block number: {bnum}, timestamp: {ts}, num tx: {ntx}") bck
nblocks = 2000 blocks = [] bck = chain.get_block('latest') start_bnum = bck['number']-nblocks+1 for i in range(nblocks): bck = chain.get_block(start_bnum+i, full_tx=True) ntx = len(bck['transactions']) if (i+1)%100==0: print(f"{(i+1)*100/2000}% : Collected block {start_bnum+i} with {ntx} tx") blocks.append(bck)
num_txs = [len(bck['transactions']) for bck in blocks] plt.plot(num_txs)
times = [bck['timestamp'] for bck in blocks] times = np.array(times) plt.plot(times[1:]-times[:-1])
Total tx count: 28661 Router tx counts: {'0xE3D8bd6Aed4F159bc8000a9cD47CffDb95F96121': 664, '0x1421bDe4B10e8dd459b3BCb598810B1337D56842': 510, '0x7D28570135A2B1930F331c507F65039D4937f66c': 10}
$ nvp bchain collect-gas-price -c celo 2022/06/16 21:00:33 [nvh.crypto.blockchain.evm_blockchain] INFO: Block 13566077: num_tx=5, mode=0.550, mean=0.211, dev=0.190
SQL_CREATE_ADDRESS_TABLE = """ CREATE TABLE IF NOT EXISTS addresses ( id SERIAL PRIMARY KEY, address char(42) NOT NULL UNIQUE ); """ SQL_INSERT_ADDRESS = """ INSERT INTO addresses(address) VALUES(%s); """
SQL_CREATE_ADDRESSES_TABLE = """ CREATE TABLE IF NOT EXISTS addresses ( id SERIAL PRIMARY KEY, a1 BIGINT NOT NULL, a2 BIGINT NOT NULL, a3 INT NOT NULL, UNIQUE (a1, a2, a3) ); """ SQL_INSERT_ADDRESS = """ INSERT INTO addresses(address) VALUES(%s,%s,%s); """
SQL_CREATE_BLOCKS_TABLE = """ CREATE TABLE IF NOT EXISTS blocks ( number INTEGER PRIMARY KEY, timestamp INTEGER, miner_id INTEGER, size INTEGER, difficulty INTEGER, tx_count SMALLINT, gas_used INTEGER ); """ SQL_INSERT_BLOCK = """ INSERT INTO blocks(number,timestamp,miner,size,difficulty,tx_count,gas_used) VALUES(%s,%s,%s,%s,%s,%s,%s); """
SQL_CREATE_TRANSACTIONS_TABLE = """ CREATE TABLE IF NOT EXISTS transactions ( id SERIAL PRIMARY KEY, block_number INTEGER, tx_index SMALLINT, from_id INTEGER, to_id INTEGER, gas INTEGER, gas_price INTEGER, nonce INTEGER, value INTEGER, operation_type SMALINT, sig INTEGER, registers BYTEA ); """ SQL_INSERT_TRANSACTION = """ INSERT INTO transactions(block_number,tx_index,from_id,to_id,gas,gas_price,nonce,value,operation_type,sig,registers) VALUES(%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s); """
def get_handler(self, hname): """Get a handler by name""" if hname in self.handlers: return self.handlers[hname] # otherwise we have to search for that handler: comp_module = import_module(hname) handler = comp_module.handle self.handlers[hname] = handler return handler def call_handler(self, hname, *args, **kwargs): """Call a given handler with arguments""" handler = self.get_handler(hname) return handler(*args, **kwargs)
def handle(self, hname, *args, **kwargs): """Call an handler specific to this component, should be found in a sub folder called 'handlers'""" return self.call_handler(f"{self.handlers_path}.{hname}", self, *args, **kwargs)
set_contrust_frame()
is called in NVPContext.create_component()
now): def set_construct_frame(self, frame): """Assign a construct frame to this component""" self.construct_frame = frame # setup the default handlers path: parts = self.construct_frame["module"].split(".") # Replace the last name on the module path with "handlers" parts[-1] = "handlers" self.handlers_path = ".".join(parts)
if cmd == "collect.blocks": chain_name = self.get_param("chain") chain: EVMBlockchain = self.get_component(f"{chain_name}_chain") chain.handle("collect_evm_blocks") return True
$ nvp bchain collect blocks 2022/06/17 08:40:18 [nvh.crypto.blockchain.handlers.collect_evm_blocks] INFO: Should collect blocks here on chain bsc
def get_address_id(self, addr): """Convert an address into an id""" self.check(len(addr) == 42, "Invalid address %s", addr) # Extract the relevant parts: # we will store 8bytes / 8bytes / 4bytes elements: # each byte takes 2 hex digits so thats 16 chars / 16 chars / 8 chars (excluding the '0x' prefix) addr = addr.lower() # We need to convert from uint to int values below: a1 = utl.to_int64(int(addr[2:18], 16)) a2 = utl.to_int64(int(addr[18:34], 16)) a3 = utl.to_int32(int(addr[34:], 16)) # Check if we already have that entry in the DB: cur = self.sql_db.execute("SELECT id from addresses WHERE a1=%s AND a2=%s AND a3=%s;") row = cur.fetchone() if row is not None: return row[0] # Address not found: we insert it: sql = "INSERT INTO addresses(a1,a2,a3) VALUES(%s,%s,%s) RETURNING id;" cur = self.sql_db.execute(sql, (a1, a2, a3), commit=True) row = cur.fetchone() addr_id = row[0] logger.info("Inserting address %s with id %d", addr, addr_id) return addr_id
2022/06/17 09:45:55 [nvh.crypto.blockchain.chain_db] INFO: Inserting address 0xfcb5df42e06a39e233dc707bb3a80311efd11576 with id 101 Got ID: 101 2022/06/17 09:45:55 [nvh.crypto.blockchain.chain_db] INFO: Inserting address 0xed78e6efaabfba76c43c40ea99003325505e1869 with id 102 Got ID: 102 2022/06/17 09:45:55 [nvh.crypto.blockchain.chain_db] INFO: Inserting address 0xc67687524ab947bf41f35434971c817fa3663413 with id 103 Got ID: 103 2022/06/17 09:45:55 [nvh.crypto.blockchain.chain_db] INFO: Inserting address 0xdb0dec74e23394d1883e2ee859db98d6fe357695 with id 104 Got ID: 104 2022/06/17 09:45:55 [nvh.crypto.blockchain.chain_db] INFO: Inserting address 0x721c5ba18d3cddef5b94c45725f860a830dd067f with id 105 Got ID: 105 2022/06/17 09:45:55 [nvh.crypto.blockchain.chain_db] INFO: Inserting address 0x897fe07d613037c206429628611a2665e18c657d with id 106 Got ID: 106
def get_address(self, addr_id): """Retrieve an addres from a given id""" cur = self.sql_db.execute("SELECT a1,a2,a3 from addresses WHERE id=%s;", (addr_id,)) row = cur.fetchone() if row is None: # No address found: logger.info("No address found with id %d", addr_id) return None # We convert back to uint then to hex: a1 = hex(utl.to_uint64(row[0])) a2 = hex(utl.to_uint64(row[1]))[2:] a3 = hex(utl.to_uint32(row[2]))[2:] # Return the reconstructed address: return f"{a1}{a2}{a3}"
db.get_address(102) '0xed78e6efaabfba76c43c40ea99003325505e1869'
"""Handler function used to collect new blocks on a given chain""" import logging from nvh.crypto.blockchain.chain_db import ChainDB from nvh.crypto.blockchain.evm_blockchain import EVMBlockchain logger = logging.getLogger("collect_evm_blocks") def handle(chain: EVMBlockchain): """Handler function entry point""" # logger.info("Should collect blocks here on chain %s", chain.get_short_name()) sql = chain.get_db() # Get the latest block: last_block = chain.get_block("latest", full_tx=True) # Check what is the last block in the database: last_stored_bnum = sql.get_last_block_number() logger.info("Last stored block number is: %s", last_stored_bnum) if last_stored_bnum is None: # Then we simply store the current block: process_block(sql, last_block) else: # Process all the blocks from last_stored_bnum+1 to the last_block end_bnum = last_block["number"] cur_bnum = last_stored_bnum + 1 count = end_bnum - cur_bnum idx = 1 while cur_bnum < end_bnum: bck = chain.get_block(cur_bnum, full_tx=True) process_block(sql, bck, f"{idx*100.0/count:.2f}%: ") cur_bnum += 1 idx += 1 # Finally we process the final block: process_block(sql, last_block, "100%: ") def process_block(sql: ChainDB, bck, prefix=""): """Process a given block to store it in the DB""" # Get the info we want from the block itself: # (number,timestamp,miner,size,difficulty,tx_count,gas_used) txs = bck["transactions"] logger.info("%sBlock %d, %d txs", prefix, bck["number"], len(txs)) keylist = ("number", "timestamp", "size", "difficulty") desc = {key: bck[key] for key in keylist} desc["gas_used"] = bck["gasUsed"] desc["tx_count"] = len(txs) # **Note** we also need to retrive the id for the miner: desc["miner_id"] = sql.get_address_id(bck["miner"]) logger.debug("Should store block desc: %s", desc) sql.insert_blocks([desc]) process_transactions(sql, txs) def process_transactions(sql: ChainDB, txs): """Process a list of transactions""" descs = [] for trans in txs: txinput = trans["input"][2:] sig = "" registers = "" if len(txinput) >= 8: sig = txinput[:8] registers = txinput[8:] # Note: the to address may be null if we are creating a contract: to_id = trans["to"] if to_id is not None: to_id = sql.get_address_id(to_id) descs.append( { "block_number": trans["blockNumber"], "tx_index": trans["transactionIndex"], "from_id": sql.get_address_id(trans["from"]), "to_id": to_id, "gas": trans["gas"], "gas_price": trans["gasPrice"], "nonce": trans["nonce"], "value": trans["value"], "operation_type": 0, "sig": sig if len(sig) > 0 else None, "registers": registers if len(registers) > 0 else None, } ) # for desc in descs: # logger.info("Inserting tx: %s", desc) # sql.insert_txs([desc]) # logger.debug("Inserting %d transactions", len(descs)) sql.insert_txs(descs)
"bchain": { "lock_file": "${PROJECT_ROOT_DIR}/data/locks/bchain.lock", "custom_python_env": "bsc_env", "cmd": "${PYTHON} ${PROJECT_ROOT_DIR}/nvh/crypto/blockchain/blockchain_manager.py", "python_path": ["${PROJECT_ROOT_DIR}", "${NVP_ROOT_DIR}"] },
lfile="${log_dir}/collect_bsc_blocks.log" nvp collect_bsc_blocks 2>&1 | tee -a $lfile lfile="${log_dir}/collect_eth_blocks.log" nvp collect_eth_blocks 2>&1 | tee -a $lfile lfile="${log_dir}/collect_celo_blocks.log" nvp collect_celo_blocks 2>&1 | tee -a $lfile
nblocks = db.get_num_blocks() nblocks output: 12555 ntx = db.get_num_transactions() ntx output: 146829
sql = "SELECT to_id from transactions WHERE sig = ANY(%s);" cur = db.execute(sql, (sigs_i32,)) rows = cur.fetchall() ids = [row[0] for row in rows] id_counts = {} for to_id in ids: id_counts[to_id] = id_counts.get(to_id,0)+1 id_counts output: {305: 608, 313: 817, 570: 48}
# Get the addresses for those IDs: routers = [] for addid in id_counts.keys(): routers.append(chain.get_address(addid)) routers output: ['0xE3D8bd6Aed4F159bc8000a9cD47CffDb95F96121', '0x1421bDe4B10e8dd459b3BCb598810B1337D56842', '0x7D28570135A2B1930F331c507F65039D4937f66c']
$ nvp bchain update-pairs -c celo celoswap1 2022/06/18 08:11:04 [nvh.crypto.blockchain.evm_smart_contract] INFO: Writing ABI file for contract 0x62d5b84bE28a183aBB507E125B384122D2C25fAE 2022/06/18 08:11:10 [nvh.crypto.blockchain.evm_smart_contract] INFO: Writing ABI file for contract 0x1421bDe4B10e8dd459b3BCb598810B1337D56842 2022/06/18 08:11:15 [__main__] INFO: Updating pairs on CeloSwap1 2022/06/18 08:11:15 [nvh.crypto.blockchain.uniswap_base] INFO: Initial number of pairs: 0 2022/06/18 08:11:15 [nvh.crypto.blockchain.uniswap_base] INFO: Adding 660 pairs to CeloSwap1 2022/06/18 08:11:16 [nvh.crypto.blockchain.evm_smart_contract] INFO: Writing ABI file for contract 0x1E593F1FE7B61c53874B54EC0c59FD0d5eb8621e 2022/06/18 08:11:21 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0x1E593F1FE7B61c53874B54EC0c59FD0d5eb8621e 2022/06/18 08:11:21 [nvh.crypto.blockchain.evm_smart_contract] INFO: Writing ABI file for contract 0x471EcE3750Da237f93B8E339c536989b8978a438 2022/06/18 08:11:26 [nvh.crypto.blockchain.erc20_token] ERROR: Exception occured while trying to initiate token at 0x471EcE3750Da237f93B8E339c536989b8978a438: Invalid function with name name 2022/06/18 08:11:26 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0x471EcE3750Da237f93B8E339c536989b8978a438 (???) 2022/06/18 08:11:27 [nvh.crypto.blockchain.evm_smart_contract] INFO: Writing ABI file for contract 0x765DE816845861e75A25fCA122bb6898B8B1282a 2022/06/18 08:11:32 [nvh.crypto.blockchain.erc20_token] ERROR: Exception occured while trying to initiate token at 0x765DE816845861e75A25fCA122bb6898B8B1282a: Invalid function with name name 2022/06/18 08:11:32 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0x765DE816845861e75A25fCA122bb6898B8B1282a (???) 2022/06/18 08:11:32 [nvh.crypto.blockchain.chain_db] INFO: Replacing symbol ??? with ???#2 2022/06/18 08:11:32 [nvh.crypto.blockchain.uniswap_base] INFO: 0/660: Added pair on ???/???#2 2022/06/18 08:11:33 [nvh.crypto.blockchain.uniswap_base] INFO: Iteration 0: CPU usage: 0.00%, RAM usage: 89.28 MB 2022/06/18 08:11:33 [nvh.crypto.blockchain.evm_smart_contract] INFO: Writing ABI file for contract 0x7B7b05A80b6041cD039C4e487f269f47A776e396 2022/06/18 08:11:38 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0x7B7b05A80b6041cD039C4e487f269f47A776e396 Traceback (most recent call last): File "D:\Projects\NervHome\nvh\crypto\blockchain\blockchain_manager.py", line 447, in <module> comp.run() File "D:\Projects\NervProj\nvp\nvp_component.py", line 93, in run res = self.process_command(cmd) File "D:\Projects\NervProj\nvp\nvp_component.py", line 83, in process_command return self.process_cmd_path(self.ctx.get_command_path()) File "D:\Projects\NervHome\nvh\crypto\blockchain\blockchain_manager.py", line 112, in process_cmd_path dex.update_pairs() File "D:\Projects\NervHome\nvh\crypto\blockchain\uniswap_base.py", line 393, in update_pairs pair = self.chain.get_pair(paddr, pool_id=idx, ex_id=self.get_id()) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 891, in get_pair pair = ERC20Pair(chain=self, address=addr, desc=desc, ex_id=ex_id, pool_id=pool_id) File "D:\Projects\NervHome\nvh\crypto\blockchain\erc20_pair.py", line 52, in __init__ self.t0 = self.chain.get_token(t0addr) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 809, in get_token token = self.create_token(address=addr, desc=desc) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 774, in create_token return ERC20Token(chain=self, address=address, desc=desc) File "D:\Projects\NervHome\nvh\crypto\blockchain\erc20_token.py", line 36, in __init__ self.contract = self.chain.get_contract(self.addr, abi_file) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 468, in get_contract contract = EVMSmartContract(self, address, abi_file) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_smart_contract.py", line 34, in __init__ abi_file = self.download_abi() File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_smart_contract.py", line 64, in download_abi self.check(msg[0:2] == "OK", "Cannot retrieve contract ABI: %s (url=%s)", msg, url) File "D:\Projects\NervProj\nvp\nvp_object.py", line 73, in check raise NVPCheckError(fmt % args) nvp.nvp_object.NVPCheckError: Cannot retrieve contract ABI: Contract source code not verified (url=https://explorer.celo.org/api?module=contract&action=getabi&address=0x39d6477522eB543d750AF82537325FB2930c1Aa6) 2022/06/18 08:11:40 [nvp.nvp_object] ERROR: Subprocess terminated with error code 1 (cmd=['D:\\Projects\\NervProj\\.pyenvs\\bsc_env\\python.exe', 'D:\\Projects\\NervHome/nvh/crypto/blockchain/blockchain_manager.py', 'update-pairs', '-c', 'celo', 'celoswap1']) 2022/06/18 08:11:40 [nvp.components.runner] ERROR: Error occured in script command: cmd=['D:\\Projects\\NervProj\\.pyenvs\\bsc_env\\python.exe', 'D:\\Projects\\NervHome/nvh/crypto/blockchain/blockchain_manager.py', 'update-pairs', '-c', 'celo', 'celoswap1'] cwd=None return code=1 lastest outputs: pair = self.chain.get_pair(paddr, pool_id=idx, ex_id=self.get_id()) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 891, in get_pair pair = ERC20Pair(chain=self, address=addr, desc=desc, ex_id=ex_id, pool_id=pool_id) File "D:\Projects\NervHome\nvh\crypto\blockchain\erc20_pair.py", line 52, in __init__ self.t0 = self.chain.get_token(t0addr) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 809, in get_token token = self.create_token(address=addr, desc=desc) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 774, in create_token return ERC20Token(chain=self, address=address, desc=desc) File "D:\Projects\NervHome\nvh\crypto\blockchain\erc20_token.py", line 36, in __init__ self.contract = self.chain.get_contract(self.addr, abi_file) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_blockchain.py", line 468, in get_contract contract = EVMSmartContract(self, address, abi_file) File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_smart_contract.py", line 34, in __init__ abi_file = self.download_abi() File "D:\Projects\NervHome\nvh\crypto\blockchain\evm_smart_contract.py", line 64, in download_abi self.check(msg[0:2] == "OK", "Cannot retrieve contract ABI: %s (url=%s)", msg, url) File "D:\Projects\NervProj\nvp\nvp_object.py", line 73, in check raise NVPCheckError(fmt % args) nvp.nvp_object.NVPCheckError: Cannot retrieve contract ABI: Contract source code not verified (url=https://explorer.celo.org/api?module=contract&action=getabi&address=0x39d6477522eB543d750AF82537325FB2930c1Aa6)
2022/06/18 08:11:26 [nvh.crypto.blockchain.erc20_token] ERROR: Exception occured while trying to initiate token at 0x471EcE3750Da237f93B8E339c536989b8978a438: Invalid function with name name
_getOwner()
and _getImplementation()
, with the later returning the address of the target implementation for that token.if abi_file is None: abi_file = self.chain.get_token_abi_filename()
$ nvp bchain update-pairs -c celo celoswap1 2022/06/18 08:37:09 [__main__] INFO: Updating pairs on CeloSwap1 2022/06/18 08:37:09 [nvh.crypto.blockchain.uniswap_base] INFO: Initial number of pairs: 0 2022/06/18 08:37:09 [nvh.crypto.blockchain.uniswap_base] INFO: Adding 660 pairs to CeloSwap1 2022/06/18 08:37:09 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0x1E593F1FE7B61c53874B54EC0c59FD0d5eb8621e 2022/06/18 08:37:10 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0x471EcE3750Da237f93B8E339c536989b8978a438 (CELO) 2022/06/18 08:37:10 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0x765DE816845861e75A25fCA122bb6898B8B1282a (cUSD) 2022/06/18 08:37:10 [nvh.crypto.blockchain.uniswap_base] INFO: 0/660: Added pair on CELO/cUSD 2022/06/18 08:37:10 [nvh.crypto.blockchain.uniswap_base] INFO: Iteration 0: CPU usage: 0.00%, RAM usage: 88.96 MB 2022/06/18 08:37:11 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0x7B7b05A80b6041cD039C4e487f269f47A776e396 2022/06/18 08:37:11 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0x39d6477522eB543d750AF82537325FB2930c1Aa6 (KEY) 2022/06/18 08:37:11 [nvh.crypto.blockchain.uniswap_base] INFO: 1/660: Added pair on KEY/CELO 2022/06/18 08:37:11 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0x68f5ad364Aa0fc13a5FAdE9Ddf6BadA7DFCB026c 2022/06/18 08:37:12 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0x041954F3f34422aF8d1f11fD743f3A1B70C30271 (pUSD) 2022/06/18 08:37:12 [nvh.crypto.blockchain.uniswap_base] INFO: 2/660: Added pair on pUSD/CELO 2022/06/18 08:37:12 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0xa2e63c3b9D027270Ff5892A552aaac50515ee61D 2022/06/18 08:37:12 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0x39049C02A56c3ecd046F6c2A9BE0CffA2bc29C08 (MCRS) 2022/06/18 08:37:13 [nvh.crypto.blockchain.uniswap_base] INFO: 3/660: Added pair on MCRS/CELO 2022/06/18 08:37:13 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0x5724CcCFef36B20250817Aa28E0D68707bDd0D9A 2022/06/18 08:37:13 [nvh.crypto.blockchain.evm_blockchain] INFO: Adding new token 0xF06768797ba4e86abFa5aDFBFD223742F2657960 (XGP) 2022/06/18 08:37:13 [nvh.crypto.blockchain.uniswap_base] INFO: 4/660: Added pair on CELO/XGP 2022/06/18 08:37:14 [nvh.crypto.blockchain.erc20_pair] INFO: Registering pair at 0xA413103064E6Fb32744f39Cf3B9D16168ded7590
sc = chain.get_contract("0x7D28570135A2B1930F331c507F65039D4937f66c", abi_file="ABI/celo/0x1421bDe4B10e8dd459b3BCb598810B1337D56842.json") sc.call_function("factory") output: 2022/06/18 08:58:37 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'factory' (on 0x7D28570135A2B1930F331c507F65039D4937f66c): execution reverted 2022/06/18 08:58:39 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'factory' (on 0x7D28570135A2B1930F331c507F65039D4937f66c): execution reverted 2022/06/18 08:58:42 [nvh.crypto.blockchain.evm_smart_contract] ERROR: Exception occured while calling 'factory' (on 0x7D28570135A2B1930F331c507F65039D4937f66c): execution reverted
# Get the most used contracts sql = "SELECT to_id from transactions;" cur = db.execute(sql, (sigs_i32,)) rows = cur.fetchall() ids = [row[0] for row in rows] # total number of transactions: ntx = len(ids) print(f"Number of transactions: {ntx}") # Now we group the to ids: id_counts = {} for to_id in ids: id_counts[to_id] = id_counts.get(to_id,0)+1 nsc = len(id_counts) print(f"Number of different to contracts: {nsc}") # We divide by the total number of tx to get a percentage: for key, val in id_counts.items(): id_counts[key] = 100.0*val / ntx # sort the contracts: sclist = [(key,val) for key,val in id_counts.items()] sclist.sort(key = lambda item: item[1], reverse=True) for idx, item in enumerate(sclist[:20]): addr = chain.get_address(item[0]) print(f"{addr}: {item[1]:.2f}%")
Number of transactions: 231191 Number of different to contracts: 3403 0x6A3A5F4e72C7e0258dEd54157597d4F74Fba0FF9: 32.29% 0x5e00A28B8E1B4eD59b480D46fe2ec9d2aFCA8015: 13.28% 0x00F8525ABb78Ea86233970b5fB6b95c0844d0126: 7.22% 0xa16F9f78C70A16Fdc7637Fd8B96FD69Ea6f496E3: 6.52% 0x765DE816845861e75A25fCA122bb6898B8B1282a: 5.06% 0xefB84935239dAcdecF7c5bA76d8dE40b077B7b33: 4.83% 0x4B19240BC722d2f367A2dF36Fc38AEa7b4533F5c: 3.61% 0xF35ed7156BABF2541E032B3bB8625210316e2832: 2.52% 0x7D1e0D8b0810730e85828EaE1ee1695a95eECf4B: 1.80% 0xa2bf67e12EeEDA23C7cA1e5a34ae2441a17789Ec: 1.51% 0x056d9AAC902cc2925BB31f6C516B1e1579c35df9: 1.51% 0x6A39822cb58C2C3850CDcC96Ee4d7b707772Eecc: 1.48% 0x43D7937C08af98885Dab2481fed00ee3cFc5f22c: 1.45% 0x67316300f17f063085Ca8bCa4bd3f7a5a3C66275: 1.37% 0xeEd64Ef6010a360cDAA9B05cae65901b3250EB91: 0.93% 0xAB7064715B7944110EF7138C0c55D3c4132BdFd5: 0.82% 0xE3D8bd6Aed4F159bc8000a9cD47CffDb95F96121: 0.78% 0x194D9851250Aa8F75f896a6cbb5153a3E20dAfA0: 0.74% 0x1421bDe4B10e8dd459b3BCb598810B1337D56842: 0.63% 0x7BF9DbEcb37BF634769Cc0A93fAAB2Df157128C4: 0.62%
# Get the most active contracts: sql = "SELECT from_id from transactions;" cur = db.execute(sql, (sigs_i32,)) rows = cur.fetchall() ids = [row[0] for row in rows] # total number of transactions: ntx = len(ids) print(f"Number of transactions: {ntx}") # Now we group the to ids: id_counts = {} for to_id in ids: id_counts[to_id] = id_counts.get(to_id,0)+1 nsc = len(id_counts) print(f"Number of different from contracts: {nsc}") # We divide by the total number of tx to get a percentage: for key, val in id_counts.items(): id_counts[key] = 100.0*val / ntx # sort the contracts: sclist = [(key,val) for key,val in id_counts.items()] sclist.sort(key = lambda item: item[1], reverse=True) print("Most active users:") for idx, item in enumerate(sclist[:20]): addr = chain.get_address(item[0]) print(f"{addr}: {item[1]:.2f}%")
# compute the number of unique signature for each from address: sql = "SELECT from_id,sig from transactions;" cur = db.execute(sql, (sigs_i32,)) rows = cur.fetchall() ids = [(row[0],row[1]) for row in rows] # total number of transactions: ntx = len(ids) print(f"Number of transactions: {ntx}") # Now we group the to ids / signatures: descs = {} for elem in ids: addr_id = elem[0] if addr_id not in descs: descs[addr_id] = { 'count': 1, 'sigs': set([elem[1]]) } else: descs[addr_id]['count'] += 1 descs[addr_id]['sigs'].add(elem[1]) nsc = len(descs) print(f"Number of different from contracts: {nsc}") # We divide by the total number of tx to get a percentage: for key, desc in descs.items(): desc['id'] = key desc['percent'] = desc['count']*100.0 / ntx desc['nsigs'] = len(desc['sigs']) # sort the contracts: sclist = list(descs.values()) sclist.sort(key = lambda item: item['nsigs']) # print("Users per number of sigs:") # for idx, item in enumerate(sclist[:20]): # addr = chain.get_address(item['id']) # print(f"{addr}: {item['nsigs']}") # Compute the number of contracts per number of sigs: sig_buckets = {} for desc in sclist: nsig = desc['nsigs'] sig_buckets[nsig] = sig_buckets.get(nsig,0)+1 for key, val in sig_buckets.items(): num = sig_buckets[key] percent = num*100.0/nsc print(f"{key} sig(s): {num} contracts ({percent:.2f}%)")
Number of transactions: 322624 Number of different from contracts: 5368 1 sig(s): 3767 contracts (70.18%) 2 sig(s): 986 contracts (18.37%) 3 sig(s): 328 contracts (6.11%) 4 sig(s): 122 contracts (2.27%) 5 sig(s): 60 contracts (1.12%) 6 sig(s): 29 contracts (0.54%) 7 sig(s): 24 contracts (0.45%) 8 sig(s): 17 contracts (0.32%) 9 sig(s): 5 contracts (0.09%) 10 sig(s): 8 contracts (0.15%) 11 sig(s): 4 contracts (0.07%) 12 sig(s): 1 contracts (0.02%) 13 sig(s): 1 contracts (0.02%) 36 sig(s): 8 contracts (0.15%) 199 sig(s): 8 contracts (0.15%)
# filter by number of sigs: sclist = list(descs.values()) from_ids = [elem['id'] for elem in sclist if elem['nsigs']>1] # Now get the to_ids from all those from_ids: sql = "SELECT to_id from transactions WHERE from_id = ANY(%s);" cur = db.execute(sql, (from_ids,)) rows = cur.fetchall() ids = [row[0] for row in rows] # count the number of occurences for each to address: counts = {} for tid in ids: counts[tid] = counts.get(tid,0)+1 ntx = len(ids) to_ids = [(key,val) for key,val in counts.items()] to_ids.sort(key=lambda item: item[1], reverse=True) print("Most used contracts:") for elem in to_ids[:20]: addr = chain.get_address(elem[0]) percent = elem[1]*100/ntx print(f"{addr}: {percent:.2f}%")
0x5e00A28B8E1B4eD59b480D46fe2ec9d2aFCA8015: 19.31% 0x4B19240BC722d2f367A2dF36Fc38AEa7b4533F5c: 13.01% 0xefB84935239dAcdecF7c5bA76d8dE40b077B7b33: 9.85% 0x43D7937C08af98885Dab2481fed00ee3cFc5f22c: 6.31% 0x056d9AAC902cc2925BB31f6C516B1e1579c35df9: 5.19% 0x67316300f17f063085Ca8bCa4bd3f7a5a3C66275: 4.71% 0x194D9851250Aa8F75f896a6cbb5153a3E20dAfA0: 4.33% 0x765DE816845861e75A25fCA122bb6898B8B1282a: 4.26% 0xE3D8bd6Aed4F159bc8000a9cD47CffDb95F96121: 3.21% 0xAB7064715B7944110EF7138C0c55D3c4132BdFd5: 3.18% 0xF35ed7156BABF2541E032B3bB8625210316e2832: 3.05% 0xb90c0a9008f1bafc12C751Ae33E05Eb7E0002132: 2.53% 0xe5c3A4Dd4eD0d6329398B79B1e61228004b35060: 1.28% 0x1421bDe4B10e8dd459b3BCb598810B1337D56842: 1.27% 0x52c2c35b4f5F03d9097c702c1a90597659ec2DDa: 1.10% 0xc8Fa2DEeDD603c754846a21eDf257abbfF542458: 1.05% 0xbDb92Ca42559adc5adC20a1E4985dC7c476483be: 0.94% 0x471EcE3750Da237f93B8E339c536989b8978a438: 0.93% 0xE383394B913d7302c49F794C7d3243c429d53D1d: 0.49% 0x918146359264C492BD6934071c6Bd31C854EDBc3: 0.47%