Riy777 commited on
Commit
aa96de6
·
1 Parent(s): 89834f5

Update data_manager.py

Browse files
Files changed (1) hide show
  1. data_manager.py +226 -25
data_manager.py CHANGED
@@ -1,4 +1,4 @@
1
- import os, asyncio, httpx, json, traceback, backoff, re, time
2
  from datetime import datetime, timedelta
3
  from functools import wraps
4
  import ccxt.pro as ccxt
@@ -7,7 +7,7 @@ import pandas as pd
7
  import numpy as np
8
  from state import MARKET_STATE_OK
9
 
10
- # --- 🐋 نظام تتبع الحيتان المحسن مع الوقت الدقيق ---
11
  class EnhancedWhaleMonitor:
12
  def __init__(self, contracts_db=None):
13
  self.http_client = httpx.AsyncClient(timeout=10.0, limits=httpx.Limits(max_connections=100, max_keepalive_connections=20))
@@ -24,6 +24,16 @@ class EnhancedWhaleMonitor:
24
  'polygon': 'https://polygon-rpc.com/',
25
  'arbitrum': 'https://arb1.arbitrum.io/rpc',
26
  'avalanche': 'https://api.avax.network/ext/bc/C/rpc',
 
 
 
 
 
 
 
 
 
 
27
  }
28
 
29
  self.price_cache = {}
@@ -37,7 +47,7 @@ class EnhancedWhaleMonitor:
37
 
38
  coin_map = {
39
  'ethereum': 'ethereum', 'bsc': 'binancecoin', 'polygon': 'matic-network',
40
- 'arbitrum': 'arbitrum', 'avalanche': 'avalanche-2'
41
  }
42
  coin_id = coin_map.get(network)
43
  if not coin_id: return 0
@@ -56,7 +66,17 @@ class EnhancedWhaleMonitor:
56
  async def _call_rpc_async(self, network, method, params=[]):
57
  """اتصال RPC غير متزامن"""
58
  try:
59
- payload = {"jsonrpc": "2.0", "method": method, "params": params, "id": 1}
 
 
 
 
 
 
 
 
 
 
60
  response = await self.http_client.post(self.rpc_endpoints[network], json=payload)
61
  response.raise_for_status()
62
  return response.json().get('result')
@@ -114,10 +134,168 @@ class EnhancedWhaleMonitor:
114
  print(f"⚠️ خطأ في مسح شبكة {network}: {e}")
115
  return whale_alerts
116
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
117
  async def get_general_whale_activity(self):
118
  """الوظيفة الرئيسية لمراقبة الحيتان العامة عبر RPC"""
119
  print("🌊 بدء مراقبة الحيتان عبر الشبكات المتعددة...")
120
- tasks = [self._scan_single_evm_network(net) for net in self.rpc_endpoints.keys()]
121
  results = await asyncio.gather(*tasks, return_exceptions=True)
122
 
123
  all_alerts = []
@@ -175,27 +353,42 @@ class EnhancedWhaleMonitor:
175
  if not contract_address:
176
  contract_address = await self._find_contract_address(base_symbol)
177
 
178
- if not contract_address:
179
- return await self._scan_networks_for_symbol(symbol, base_symbol)
180
 
181
  try:
182
  print(f"🔍 جلب بيانات الحيتان لـ {symbol} مع العقد: {contract_address[:10]}...")
183
 
184
- # الحصول على بيانات المصادر الأساسية
185
- api_data = await self._get_combined_api_data(contract_address)
186
-
187
- if api_data:
188
- # 🕒 إضافة معلومات الوقت للبيانات من API
189
- enriched_data = await self._enrich_api_data_with_timing(api_data)
190
- return self._analyze_symbol_specific_data(enriched_data, symbol)
191
  else:
192
- # إذا فشلت المصادر الأساسية، جرب الشبكات المباشرة
193
- return await self._scan_networks_for_symbol(symbol, base_symbol)
 
 
 
 
 
 
 
 
194
 
195
  except Exception as e:
196
  print(f"❌ فشل جلب بيانات الحيتان لـ {symbol}: {e}")
197
  return await self._scan_networks_for_symbol(symbol, base_symbol)
198
 
 
 
 
 
 
 
 
 
 
 
 
199
  async def _get_combined_api_data(self, contract_address):
200
  """جلب البيانات المجمعة من مصادر API"""
201
  tasks = []
@@ -259,10 +452,13 @@ class EnhancedWhaleMonitor:
259
  whale_alerts = []
260
  tasks = []
261
 
262
- # مسح جميع شبكات EVM
263
- for network in ['ethereum', 'bsc', 'polygon', 'arbitrum', 'avalanche']:
264
  if network in self.rpc_endpoints:
265
- tasks.append(self._scan_network_for_token_transfers(network, base_symbol))
 
 
 
266
 
267
  results = await asyncio.gather(*tasks, return_exceptions=True)
268
 
@@ -367,7 +563,7 @@ class EnhancedWhaleMonitor:
367
  if not alerts:
368
  return {
369
  'data_available': False,
370
- 'description': f'لم يتم العثور على نشاط حيتان لـ {symbol} في آخر 50 كتلة',
371
  'total_volume': 0,
372
  'transfer_count': 0
373
  }
@@ -454,12 +650,17 @@ class EnhancedWhaleMonitor:
454
  # 1. البحث في قاعدة البيانات المحلية أولاً
455
  contracts = self.contracts_db.get(base_symbol.upper(), {})
456
  if contracts:
457
- for network in ['ethereum', 'bsc', 'polygon', 'arbitrum']:
458
  if network in contracts:
459
  print(f"✅ وجد عقد {base_symbol} في {network}: {contracts[network][:10]}...")
460
  return contracts[network]
461
 
462
- # 2. البحث في CoinGecko مباشرة
 
 
 
 
 
463
  print(f"🔍 البحث عن عقد {base_symbol} في CoinGecko...")
464
  coin_id = await self._find_coin_id_by_symbol(base_symbol)
465
  if coin_id:
@@ -556,7 +757,7 @@ class DataManager:
556
 
557
  async def initialize(self):
558
  self.http_client = httpx.AsyncClient(timeout=30.0)
559
- print("✅ DataManager initialized - Enhanced RPC Whale Monitoring with Timing Active")
560
 
561
  async def close(self):
562
  if self.http_client: await self.http_client.aclose()
@@ -947,7 +1148,7 @@ class DataManager:
947
  contracts = self.contracts_db.get(base, {})
948
  contract_address = contracts.get("ethereum") # الأولوية للشبكة الرئيسية
949
 
950
- # استخدام النظام المحسن
951
  whale_data = await self.whale_monitor.get_symbol_specific_whale_data(symbol, contract_address)
952
 
953
  if whale_data.get('data_available'):
@@ -1133,4 +1334,4 @@ async def fetch_contracts_from_coingecko():
1133
  print("🚨 فشل جميع محاولات جلب عقود CoinGecko")
1134
  return {}
1135
 
1136
- print("✅ Enhanced Data Manager Loaded - REAL-TIME WHALE TRACKING WITH PRECISE TIMING - 50 BLOCKS SCAN - NO SIMULATION - SENTIMENT FIXED")
 
1
+ import os, asyncio, httpx, json, traceback, backoff, re, time, base58
2
  from datetime import datetime, timedelta
3
  from functools import wraps
4
  import ccxt.pro as ccxt
 
7
  import numpy as np
8
  from state import MARKET_STATE_OK
9
 
10
+ # --- 🐋 نظام تتبع الحيتان المحسن مع دعم Solana ---
11
  class EnhancedWhaleMonitor:
12
  def __init__(self, contracts_db=None):
13
  self.http_client = httpx.AsyncClient(timeout=10.0, limits=httpx.Limits(max_connections=100, max_keepalive_connections=20))
 
24
  'polygon': 'https://polygon-rpc.com/',
25
  'arbitrum': 'https://arb1.arbitrum.io/rpc',
26
  'avalanche': 'https://api.avax.network/ext/bc/C/rpc',
27
+ 'solana': 'https://api.mainnet-beta.solana.com', # ✅ إضافة Solana
28
+ }
29
+
30
+ # قاعدة بيانات للعناوين المشهورة على Solana
31
+ self.solana_known_tokens = {
32
+ 'SWTCH': 'SW1TCHLmRGTfW5xZknqQdpdarB8PD95sJYWpNp9TbFx',
33
+ 'BONK': 'DezXAZ8z7PnrnRJjz3wXBoRgixCa6xjnB7YaB1pPB263',
34
+ 'WIF': 'EKpQGSJtjMFqKZ9KQanSqYXRcF8fBopzLHYxdM65zcjm',
35
+ 'JUP': 'JUPyiwrYJFskUPiHa7hkeR8VUtAeFoSYbKedZNsDvCN',
36
+ 'RAY': '4k3Dyjzvzp8eMZWUXbBCjEvwSkkk59S5iCNLY3QrkX6R'
37
  }
38
 
39
  self.price_cache = {}
 
47
 
48
  coin_map = {
49
  'ethereum': 'ethereum', 'bsc': 'binancecoin', 'polygon': 'matic-network',
50
+ 'arbitrum': 'arbitrum', 'avalanche': 'avalanche-2', 'solana': 'solana'
51
  }
52
  coin_id = coin_map.get(network)
53
  if not coin_id: return 0
 
66
  async def _call_rpc_async(self, network, method, params=[]):
67
  """اتصال RPC غير متزامن"""
68
  try:
69
+ if network == 'solana':
70
+ # تنسيق مختلف لـ Solana RPC
71
+ payload = {
72
+ "jsonrpc": "2.0",
73
+ "id": 1,
74
+ "method": method,
75
+ "params": params
76
+ }
77
+ else:
78
+ payload = {"jsonrpc": "2.0", "method": method, "params": params, "id": 1}
79
+
80
  response = await self.http_client.post(self.rpc_endpoints[network], json=payload)
81
  response.raise_for_status()
82
  return response.json().get('result')
 
134
  print(f"⚠️ خطأ في مسح شبكة {network}: {e}")
135
  return whale_alerts
136
 
137
+ async def _scan_solana_network(self, base_symbol):
138
+ """مسح شبكة Solana لتحويلات العملة"""
139
+ try:
140
+ print(f"🔍 مسح Solana لـ {base_symbol}...")
141
+
142
+ # الحصول على عنوان العقد
143
+ token_address = await self._get_solana_token_address(base_symbol)
144
+ if not token_address:
145
+ return []
146
+
147
+ whale_alerts = []
148
+
149
+ # جلب آخر التوقيعات للعنوان
150
+ payload = {
151
+ "jsonrpc": "2.0",
152
+ "id": 1,
153
+ "method": "getSignaturesForAddress",
154
+ "params": [
155
+ token_address,
156
+ {"limit": 50} # جلب آخر 50 توقيع
157
+ ]
158
+ }
159
+
160
+ response = await self.http_client.post(self.rpc_endpoints['solana'], json=payload)
161
+ if response.status_code != 200:
162
+ return []
163
+
164
+ data = response.json()
165
+ if 'result' not in data:
166
+ return []
167
+
168
+ # الحصول على سعر SOL
169
+ sol_price = await self._get_native_coin_price('solana')
170
+
171
+ # تحليل التوقيعات الحديثة (آخر 20 توقيع)
172
+ for signature_info in data['result'][:20]:
173
+ try:
174
+ # جلب تفاصيل المعاملة
175
+ tx_payload = {
176
+ "jsonrpc": "2.0",
177
+ "id": 1,
178
+ "method": "getTransaction",
179
+ "params": [
180
+ signature_info['signature'],
181
+ {"encoding": "jsonParsed", "maxSupportedTransactionVersion": 0}
182
+ ]
183
+ }
184
+
185
+ tx_response = await self.http_client.post(self.rpc_endpoints['solana'], json=tx_payload)
186
+ if tx_response.status_code == 200:
187
+ tx_data = tx_response.json()
188
+ if 'result' in tx_data and tx_data['result']:
189
+ transaction = tx_data['result']
190
+
191
+ # تحليل حجم التحويل
192
+ transfer_value = await self._analyze_solana_transaction(transaction, base_symbol)
193
+ if transfer_value > 0:
194
+ # تحويل القيمة إلى USD
195
+ value_usd = transfer_value * sol_price
196
+
197
+ if value_usd >= self.whale_threshold_usd:
198
+ block_time = datetime.fromtimestamp(signature_info['blockTime'])
199
+ time_ago = (datetime.now() - block_time).total_seconds() / 60
200
+
201
+ whale_alerts.append({
202
+ 'network': 'solana',
203
+ 'value_usd': value_usd,
204
+ 'signature': signature_info['signature'][:10] + '...',
205
+ 'timestamp': signature_info['blockTime'],
206
+ 'human_time': block_time.isoformat(),
207
+ 'minutes_ago': time_ago,
208
+ 'transaction_type': 'solana_token_transfer',
209
+ 'token_amount': transfer_value,
210
+ 'sol_amount': transfer_value
211
+ })
212
+ except Exception as e:
213
+ print(f"⚠️ خطأ في تحليل معاملة Solana: {e}")
214
+ continue
215
+
216
+ return whale_alerts
217
+
218
+ except Exception as e:
219
+ print(f"❌ فشل مسح Solana لـ {base_symbol}: {e}")
220
+ return []
221
+
222
+ async def _get_solana_token_address(self, base_symbol):
223
+ """الحصول على عنوان الرمز على Solana"""
224
+ # البحث في قاعدة البيانات المحلية أولاً
225
+ contracts = self.contracts_db.get(base_symbol.upper(), {})
226
+ if contracts and 'solana' in contracts:
227
+ return contracts['solana']
228
+
229
+ # البحث في قاعدة البيانات المحلية
230
+ if base_symbol.upper() in self.solana_known_tokens:
231
+ return self.solana_known_tokens[base_symbol.upper()]
232
+
233
+ # البحث في CoinGecko
234
+ coin_id = await self._find_coin_id_by_symbol(base_symbol)
235
+ if coin_id:
236
+ solana_address = await self._get_solana_contract_from_coingecko(coin_id)
237
+ if solana_address:
238
+ return solana_address
239
+
240
+ return None
241
+
242
+ async def _get_solana_contract_from_coingecko(self, coin_id):
243
+ """جلب عنوان Solana من CoinGecko"""
244
+ try:
245
+ url = f"https://api.coingecko.com/api/v3/coins/{coin_id}"
246
+ async with httpx.AsyncClient() as client:
247
+ response = await client.get(url, timeout=10)
248
+ response.raise_for_status()
249
+ data = response.json()
250
+
251
+ platforms = data.get('platforms', {})
252
+ if 'solana' in platforms and platforms['solana']:
253
+ return platforms['solana']
254
+
255
+ except Exception as e:
256
+ print(f"⚠️ فشل جلب عقد Solana من CoinGecko: {e}")
257
+
258
+ return None
259
+
260
+ async def _analyze_solana_transaction(self, transaction, base_symbol):
261
+ """تحليل معاملة Solana للبحث عن تحويلات كبيرة"""
262
+ try:
263
+ if 'meta' not in transaction:
264
+ return 0
265
+
266
+ meta = transaction['meta']
267
+ if 'preTokenBalances' not in meta or 'postTokenBalances' not in meta:
268
+ return 0
269
+
270
+ # حساب التغير في الأرصدة
271
+ total_change = 0
272
+
273
+ # تحليل تغيرات الرصيد قبل وبعد
274
+ pre_balances = {bal['accountIndex']: float(bal.get('uiTokenAmount', {}).get('uiAmount', 0))
275
+ for bal in meta.get('preTokenBalances', [])}
276
+ post_balances = {bal['accountIndex']: float(bal.get('uiTokenAmount', {}).get('uiAmount', 0))
277
+ for bal in meta.get('postTokenBalances', [])}
278
+
279
+ for account_index, post_balance in post_balances.items():
280
+ pre_balance = pre_balances.get(account_index, 0)
281
+ change = post_balance - pre_balance
282
+ if change > 0: # نبحث عن التحويلات الواردة الكبيرة
283
+ total_change += change
284
+
285
+ # إذا كان التغير كبيراً، نعتبره تحويل حوت
286
+ if total_change > 10000: # حد أدنى لكمية الرمز
287
+ return total_change
288
+
289
+ return 0
290
+
291
+ except Exception as e:
292
+ print(f"⚠️ خطأ في تحليل معاملة Solana: {e}")
293
+ return 0
294
+
295
  async def get_general_whale_activity(self):
296
  """الوظيفة الرئيسية لمراقبة الحيتان العامة عبر RPC"""
297
  print("🌊 بدء مراقبة الحيتان عبر الشبكات المتعددة...")
298
+ tasks = [self._scan_single_evm_network(net) for net in self.rpc_endpoints.keys() if net != 'solana']
299
  results = await asyncio.gather(*tasks, return_exceptions=True)
300
 
301
  all_alerts = []
 
353
  if not contract_address:
354
  contract_address = await self._find_contract_address(base_symbol)
355
 
356
+ # تحديد نوع الشبكة
357
+ network_type = self._detect_network_type(contract_address)
358
 
359
  try:
360
  print(f"🔍 جلب بيانات الحيتان لـ {symbol} مع العقد: {contract_address[:10]}...")
361
 
362
+ if network_type == 'solana':
363
+ # مسح شبكة Solana
364
+ return await self._scan_solana_network(base_symbol)
 
 
 
 
365
  else:
366
+ # الحصول على بيانات المصادر الأساسية لـ EVM
367
+ api_data = await self._get_combined_api_data(contract_address)
368
+
369
+ if api_data:
370
+ # 🕒 إضافة معلومات الوقت للبيانات من API
371
+ enriched_data = await self._enrich_api_data_with_timing(api_data)
372
+ return self._analyze_symbol_specific_data(enriched_data, symbol)
373
+ else:
374
+ # إذا فشلت المصادر الأساسية، جرب الشبكات المباشرة
375
+ return await self._scan_networks_for_symbol(symbol, base_symbol)
376
 
377
  except Exception as e:
378
  print(f"❌ فشل جلب بيانات الحيتان لـ {symbol}: {e}")
379
  return await self._scan_networks_for_symbol(symbol, base_symbol)
380
 
381
+ def _detect_network_type(self, contract_address):
382
+ """كشف نوع الشبكة بناءً على عنوان العقد"""
383
+ if not contract_address:
384
+ return 'unknown'
385
+
386
+ # Solana عناوين تكون base58 encoded بطول محدد
387
+ if len(contract_address) in [32, 44] and all(c in '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz' for c in contract_address):
388
+ return 'solana'
389
+ else:
390
+ return 'evm'
391
+
392
  async def _get_combined_api_data(self, contract_address):
393
  """جلب البيانات المجمعة من مصادر API"""
394
  tasks = []
 
452
  whale_alerts = []
453
  tasks = []
454
 
455
+ # مسح جميع شبكات EVM + Solana
456
+ for network in ['ethereum', 'bsc', 'polygon', 'arbitrum', 'avalanche', 'solana']:
457
  if network in self.rpc_endpoints:
458
+ if network == 'solana':
459
+ tasks.append(self._scan_solana_network(base_symbol))
460
+ else:
461
+ tasks.append(self._scan_network_for_token_transfers(network, base_symbol))
462
 
463
  results = await asyncio.gather(*tasks, return_exceptions=True)
464
 
 
563
  if not alerts:
564
  return {
565
  'data_available': False,
566
+ 'description': f'لم يتم العثور على نشاط حيتان لـ {symbol} في الشبكات المباشرة',
567
  'total_volume': 0,
568
  'transfer_count': 0
569
  }
 
650
  # 1. البحث في قاعدة البيانات المحلية أولاً
651
  contracts = self.contracts_db.get(base_symbol.upper(), {})
652
  if contracts:
653
+ for network in ['ethereum', 'bsc', 'polygon', 'arbitrum', 'solana']: # ✅ إضافة Solana
654
  if network in contracts:
655
  print(f"✅ وجد عقد {base_symbol} في {network}: {contracts[network][:10]}...")
656
  return contracts[network]
657
 
658
+ # 2. البحث في قاعدة البيانات المحلية للرموز المعروفة
659
+ if base_symbol.upper() in self.solana_known_tokens:
660
+ print(f"🎯 استخدام عنوان Solana المعروف لـ {base_symbol}")
661
+ return self.solana_known_tokens[base_symbol.upper()]
662
+
663
+ # 3. البحث في CoinGecko مباشرة
664
  print(f"🔍 البحث عن عقد {base_symbol} في CoinGecko...")
665
  coin_id = await self._find_coin_id_by_symbol(base_symbol)
666
  if coin_id:
 
757
 
758
  async def initialize(self):
759
  self.http_client = httpx.AsyncClient(timeout=30.0)
760
+ print("✅ DataManager initialized - Enhanced RPC Whale Monitoring with Solana Support Active")
761
 
762
  async def close(self):
763
  if self.http_client: await self.http_client.aclose()
 
1148
  contracts = self.contracts_db.get(base, {})
1149
  contract_address = contracts.get("ethereum") # الأولوية للشبكة الرئيسية
1150
 
1151
+ # استخدام النظام المحسن مع دعم Solana
1152
  whale_data = await self.whale_monitor.get_symbol_specific_whale_data(symbol, contract_address)
1153
 
1154
  if whale_data.get('data_available'):
 
1334
  print("🚨 فشل جميع محاولات جلب عقود CoinGecko")
1335
  return {}
1336
 
1337
+ print("✅ Enhanced Data Manager Loaded - SOLANA SUPPORT ADDED - REAL-TIME WHALE TRACKING - 50 BLOCKS SCAN - NO SIMULATION")