| 18123 | return info, graph_data |
| 18124 | |
| 18125 | def get_crypto_graph(self, address): |
| 18126 | icon = CRYPTO_MAP["BTC"]["icon"] |
| 18127 | ticker = "BTC" |
| 18128 | |
| 18129 | for s, cm in CRYPTO_MAP.items(): |
| 18130 | if re.match(cm['regex'], address): |
| 18131 | icon = cm['icon'] |
| 18132 | ticker = s |
| 18133 | break |
| 18134 | |
| 18135 | short_address = f"{address[:6]}...{address[-4:]}" if len(address) > 10 else address |
| 18136 | nodes_dict = {address: {"id": address, "label": short_address, "image": icon, "size": 35}} |
| 18137 | edges = [] |
| 18138 | in_nodes = set() |
| 18139 | out_nodes = set() |
| 18140 | |
| 18141 | try: |
| 18142 | headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64)"} |
| 18143 | |
| 18144 | # --- GRAFICO PER BITCOIN --- |
| 18145 | if ticker == "BTC": |
| 18146 | r = requests.get(f"https://mempool.space/api/address/{address}/txs", headers=headers, timeout=10) |
| 18147 | if r.status_code == 200: |
| 18148 | for tx in r.json()[:15]: |
| 18149 | senders = [vin.get('prevout', {}).get('scriptpubkey_address') for vin in tx.get('vin', []) if vin.get('prevout')] |
| 18150 | receivers = [vout.get('scriptpubkey_address') for vout in tx.get('vout', [])] |
| 18151 | |
| 18152 | if address in senders: # USCITA |
| 18153 | for peer in receivers: |
| 18154 | if peer and peer != address: |
| 18155 | if peer not in nodes_dict: nodes_dict[peer] = {"id": peer, "label": f"{peer[:6]}...{peer[-4:]}", "image": icon, "size": 25} |
| 18156 | if peer not in out_nodes: |
| 18157 | edges.append({"from": address, "to": peer, "color": {"color": "#f43f5e"}, "arrows": "to"}) |
| 18158 | out_nodes.add(peer) |
| 18159 | else: # INGRESSO |
| 18160 | for peer in senders: |
| 18161 | if peer and peer != address: |
| 18162 | if peer not in nodes_dict: nodes_dict[peer] = {"id": peer, "label": f"{peer[:6]}...{peer[-4:]}", "image": icon, "size": 25} |
| 18163 | if peer not in in_nodes: |
| 18164 | edges.append({"from": peer, "to": address, "color": {"color": "#00e676"}, "arrows": "to"}) |
| 18165 | in_nodes.add(peer) |
| 18166 | |
| 18167 | # --- GRAFICO PER RETI EVM (ETH, BSC, POLYGON, AVAX) --- |
| 18168 | elif ticker in ["ETH", "BSC", "POLYGON", "AVAX"]: |
| 18169 | domain_map = {"ETH": "api.etherscan.io", "BSC": "api.bscscan.com", "POLYGON": "api.polygonscan.com", "AVAX": "api.snowtrace.io"} |
| 18170 | url = f"https://{domain_map[ticker]}/api?module=account&action=txlist&address={address}&page=1&offset=15&sort=desc" |
| 18171 | r = requests.get(url, headers=headers, timeout=10) |
| 18172 | if r.status_code == 200 and r.json().get("status") == "1": |
| 18173 | for tx in r.json().get("result", []): |
| 18174 | frm = tx.get("from", "").lower() |
| 18175 | to = tx.get("to", "").lower() |
| 18176 | if not frm or not to: continue |
| 18177 | |
| 18178 | if frm == address.lower(): # USCITA |
| 18179 | if to != address.lower(): |
| 18180 | if to not in nodes_dict: nodes_dict[to] = {"id": to, "label": f"{to[:6]}...{to[-4:]}", "image": icon, "size": 25} |
| 18181 | if to not in out_nodes: |
| 18182 | edges.append({"from": address, "to": to, "color": {"color": "#f43f5e"}, "arrows": "to"}) |