
    Гh              	       Z   d dl mZ d dlmZ d dlZd dlZd dlZej                  j                  ej                  j                  ej                  j                  ej                  j                  e      d                   d dlmZ d dlmZ d dl d dlmZ  G d	 d
      Z G d de      Zy)    )defaultdict)ClientNz..)CoingeckoAPI)JupAPI)*)StaticMethodc                       e Zd ZdZdZed        Zed        Zed        Zed        Z	ed        Z
d Zed        Zed	        Zed
        Zed        Zd Zd Zy)HelperNc           	          t        dd      }d|  d}|j                  |      }g d}|D cg c]  }t        t        ||             }}|S c c}w )N	localhostwallets_infohostdatabasea[  
            SELECT
                wallet_address,
                token_extracted,
                signature,
                type,
                profit,
                blocktime,
                delta_sol,
                delta_token,
                fee,
                MC
            FROM transactions
            WHERE wallet_address = 'z.'
            ORDER BY blocktime DESC
        )
walletmint_address	signaturetypeprofit	blocktime	delta_soldelta_tokenfeeMC)r   executedictzip)r   clientqueryresultkeysrow	formatteds          4/home/ubuntu/SOL_API/sol_API/src/v3/utils/analyze.pyget_wallet_transactions_from_DBz&Helper.get_wallet_transactions_from_DB   sg    [>B% &,H -	" & 5;<cT#dC.)<	< =s   Ac                 $   | st        d       yt        dd      }g }| D ]  }|j                  |j                  dd      |j                  dd      |j                  d	d      |j                  d
d      |j                  d      t	        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            t        |j                  dd            f
        	 |j                  d|       t        dt        |       d       	 |j                          y# t        $ r(}t        d|        Y d}~|j                          yd}~ww xY w# |j                          w xY w)u  
        Сохраняет проанализированные транзакции в базу данных ClickHouse
        
        Args:
            transactions: список транзакций с полями:
                - wallet_address
                - token_extracted (mint_address)
                - signature
                - type
                - profit
                - blocktime
                - delta_sol
                - delta_token
                - fee
                - MC
        u?   ⚠️  Нет транзакций для сохраненияFr   r   r   wallet_address token_extractedr   r   r   r   r   r   r   r   r   zINSERT INTO transactions VALUESu   ✅ Сохранено u.    транзакций в базу данныхTuC   ❌ Ошибка при сохранении транзакций: N)
printr   appendgetintfloatr   len
disconnect	Exception)transactionsr   data_to_inserttxes        r$   add_transactions_to_DBzHelper.add_transactions_to_DB3   sq   $ ST[>B  	B!!',("-{B'vr"x BFF;*+bff[!,-bff]A./bffUA&'bffT1o&# 		 NN1 +C,?+@@nop
 	  	WXYWZ[\		 s*   *E	 		E:E5 E= 5E::E= =Fc                 z    | sg S t        dd      }g }| D ]"  }d}|j                  |d|i      }|r|d   }!d}$ S )  
        Возвращает для списка токенов их creator и время миграции (migrated).
        Если токен отсутствует в таблице, он будет возвращён с None и migtime = 0.
        r   tokens_infor   zy
                SELECT migrated
                FROM tokens
                WHERE token_address = %(token)s
            tokenr   )r   r   )tokensr   r    r;   r   rowsmig_times          r$   !get_tokens_migration_time_from_DBz(Helper.get_tokens_migration_time_from_DBi   sf     Im<  	EE >>%'5)9:D7 	      c                     | sg S t        dd      }g }| D ]W  }d}|j                  |d|i      }|r(|d   }|j                  |d   |d   |d   xs dd	       C|j                  |d
dd	       Y |S )r8   r   r9   r:   z
                SELECT token_address, creator, migrated
                FROM tokens
                WHERE token_address = %(token)s
            r;   r         r;   creatormigtimeN)r   r   r+   )r<   r   r    r;   r   r=   r"   s          r$   -get_tokens_migration_time_and_creator_from_DBz4Helper.get_tokens_migration_time_and_creator_from_DB   s     Im<  	EE >>%'5)9:D1g V"1v"1v{  "#  '	2 r@   c                 H    t        j                  |       }|d   }|d   }||fS )Nmigration_startedcreator_hash)r   get_token_pool_info)r;   	pool_infomigration_timerE   s       r$   -get_token_migration_time_and_creator_from_JUPz4Helper.get_token_migration_time_and_creator_from_JUP   s4     ..u5	"#67N+w&&r@   c                    | j                  |      }|D ci c]  }|d   |
 }}g }|D ]  }|j                  |      }||d   |d   dk(  rr| j                  |      \  }}|rG||r|nd}	|j                  |||	d       W|r||d<   ||d<   n
||d<   d|d<   |j                  |       |s|j                  |       |j                  |        |S c c}w )u'  
        Получает creator и время миграции для токенов.
        Если данных нет в БД или они неполные, дополняет их через Jupiter.
        Также обновляет БД при необходимости.
        r;   rE   rF   r   rB   rD   )rG   r,   rN   r+   )
selfr<   
token_dataentrytoken_data_dictr    r;   rM   rE   new_migtimes
             r$   %get_tokens_migration_time_and_creatorz,Helper.get_tokens_migration_time_and_creator   s    GGO
 ?IIU5>50II 	%E#''.E}i 0 8E)<LPQ<Q*.*\*\]b*c'}8FnA'Va&bc */6E),/=E), 07E),/0E),e, e, e$?	%B I Js   Cc                     | j                  dd      }| j                  dd      }| j                  d      }|dk(  ryt        j                  |      }t        ||z        |z  dz  }|S )Nr   r   r   rB   r   i ʚ;)r,   r   get_sol_price_on_timestampabs)transactionr   r   	timestamp	sol_pricemcs         r$   get_market_capzHelper.get_market_cap   sk      OOK3	!oomQ7OOK0	! ;;IF	[()I5E	r@   c                 R   g }t        | d       D ]  }|j                  dd      }|j                  dd      }|j                  d      dk(  r6|dkD  r1|}|dk7  rt        |      |z  nd}|j                  ||d       d |d	<   r|j                  d      d
k(  s|dk  st        |      }d}|dkD  rT|rR|d   }	t	        ||	d         }
||
|	d   z  z  }|	dxx   |
z  cc<   ||
z  }|	d   dk(  r|j                  d       |dkD  r|rRt        |      }|dk7  r||z
  |z  dz  nd |d	<    | S )Nc                 &    | j                  dd      S Nr   r   r,   xs    r$   <lambda>z;Helper.get_profit_percent_to_transactions.<locals>.<lambda>   s    QUU;5J r@   keyr   r   r   r   buy)amountpricer   sell        rh   ri   d   )sortedr,   rX   r+   minpop)r2   
fifo_queuer4   r   r   rh   ri   sold_amount
total_costlotused_amountrevenues               r$   "get_profit_percent_to_transactionsz)Helper.get_profit_percent_to_transactions   sY    
+JK 	fB&&2K{A.Ivvf~&;?$39Q;I/A!!Ve"DE#86)kAo!+. 
!Ao*$Q-C"%k3x="AK+G"<<JM[0M;.K8})"q) "Ao* i.LVZ[O* 4
BSHae8+	f, r@   c                 &    t        d | D              S )uo   
        Проверяет, были ли покупки токена в диапазоне MC_RANGE.
        c              3      K   | ]B  }|j                  d       dk(  xr( t        |j                  dd      cxk  xr	 t        k  nc  D yw)r   rg   r   r   N)r,   MIN_MARKET_CAPMAX_MARKET_CAP).0r4   s     r$   	<genexpr>z4Helper.get_token_buys_in_valid_mc.<locals>.<genexpr>  sA      
 FF6Ne#["&&q/([^([[
s   AA
)any)r2   s    r$   get_token_buys_in_valid_mcz!Helper.get_token_buys_in_valid_mc  s      
"
 
 	
r@   c                    t        | d       } d}d}| D ]f  }|j                  d      }|j                  dd      }|j                  d      }|dk(  r||}|}CD|d	k(  sJ|M|t        |      z  }|dk  sa||z
  c S  |y
y)u  
        Считает удержание токена от первой покупки до полного слива этой первой покупки (не учитываются последующие покупки).

        Возвращает:
            int: удержание в секундах
            'hold': если токены из первой покупки ещё держатся
            None: если покупок не было
        c                 &    | j                  dd      S r`   ra   rb   s    r$   rd   z,Helper.get_first_hold_time.<locals>.<lambda>-  s    !%%Q:O r@   re   Nr   r   r   r   rg   rj   hold)rm   r,   rX   )r2   first_buy_timeremaining_from_first_buyr4   tx_typedeltatimes          r$   get_first_hold_timezHelper.get_first_hold_time#  s     l0OP#$  	1BffVnGFF=!,E66+&D%!)%)N/4, F"~'A(CJ6(+q0.00'	1, %r@   c                    g }t        |j                  dg       d       }|j                  d      }|j                  d      }|s|r|d   j                  d      }|D ]  }|j                  dd      }|j                  dd      }|j                  d	      }	| j                  |      }
|j                  d
      |	d |j                  d      |||j                  d      |
d}|j                  |        ||d<   | j	                  |      }||d<   g }|D ]  }|||j                  d
d      |j                  d	d      |j                  d      |j                  dd      |j                  dd      |j                  dd      |j                  dd      |j                  dd      d
}|j                  |        |r| j                  |       |S )Nr2   c                 &    | j                  dd      S r`   ra   rb   s    r$   rd   z4Helper.analyze_wallet_transactions.<locals>.<lambda>P  s    Z[Z_Z_`kmnZo r@   re   r;   r   r   r   r   r   r   r   r   )r   r   r   r   r   r   r   r   r(   r   r   )
r'   r)   r   r   r   r   r   r   r   r   )rm   r,   r]   r+   rv   r6   )rP   token_entryupdated_transactionsoriginal_transactionsr;   r   r4   r   r   r   r\   
updated_txdb_transactionsdb_txs                 r$   analyze_wallet_transactionsz"Helper.analyze_wallet_transactionsM  s   ! &{~r'JPo p (* /*1-11(;F' 	4B&&2K{A.IffVnG$$R(B
  VVK0VVK0&*vve}J !''
3%	4( ';N##FFG[\&:N# & 	*B"(#(VVK4vr*&&*VVK3VVK3!vvmQ7vveQ'ffT1oE ""5)	*  ''8r@   c                 l   | j                  |      }|s|g dS |d   j                  d      }t        t              }|D ]8  }t	        |t
              s|j                  d      }||   j                  |       : g }|j                         D ]h  \  }}|||d}	| j                  |	      }
|
j                  dg       }| j                  |      }| j                  |      }||||d}|j                  |       j ||d}t        j                  j                  d| d	      }t        j                  ||       |S )
u=  
        Обрабатывает транзакции из базы данных для кошелька
        
        Args:
            wallet: адрес кошелька 
            
        Returns:
            словарь в формате:
            {
                "wallet": "адрес_кошелька",
                "tokens": [
                    {
                        "token": "адрес_токена",
                        "transactions": [список_транзакций]
                    }
                ]
            }
        )r   r<   r   r   r   )r;   r   r2   r2   )r;   buy_in_valid_mcfirst_hold_timer2   z3/home/ubuntu/SOL_API/sol_API/src/v3/tmp/filter_tmp/z.json)r%   r,   r   list
isinstancer   r+   itemsr   r~   r   ospathjoinr   save_to_file)rP   r   wallet_transactions_resulttoken_groupsr4   	token_keyanalyzed_tokensr;   r2   r   analyzed_tokenanalyzed_transactionsr   r   token_resultr    output_paths                    r$   "process_wallet_transactions_resultz)Helper.process_wallet_transactions_result  sn   ( &*%I%I&%Q")$33+A.228< #4(, 	3B"d#FF>2	Y'..r2		3  $0#5#5#7 	1E<   ,K "==kJN %3$6$6~r$J! #==>STO #667LMO #2#2 5	L ""<09	1@ %

 ggll%XY_X``e#fg!!&+6r@   )__name__
__module____qualname__wallet_resultr9   staticmethodr%   r6   r?   rG   rN   rU   r]   rv   r~   r   r   r    r@   r$   r
   r
      s    MK
  6 3  3 j  < % %N ' '.f    6 
 
 & &R;BNr@   r
   c                       e Zd Zed        Zedefd       Zed        Zed        Zed        Z	e
efdZd Zd	 Zd
 Zy)Filtersc                 B   | r| j                  d      sy| j                  dg       }g }|D ]  }|j                  d      s|j                  dg       }|s*|D cg c]  }|j                  d      dk(  s| }}|sQt        |d       }|j                  d	d      }|st|j                  |        |sy|j                          d}	t	        |      }
d}t        |
      D ]8  }||   ||   z
  d
k\  r|dz  }||   ||   z
  d
k\  r||z
  dz   }t        |	|      }	: |	S c c}w )u3  
        Возвращает максимальное количество токенов, купленных в течение любого интервала в 1 час
        (3600 секунд), начиная от времени первой покупки каждого токена.
        Учитываются только токены с валидной покупкой (`buy_in_valid_mc`).
        
        Args:
            wallet_result: результат от process_wallet_transactions_result в формате:
                          {"wallet": "...", "tokens": [{"token": "...", "buy_in_valid_mc": bool, "transactions": [...]}]}
        
        Returns:
            int: максимальное количество токенов в любом часовом интервале
        r<   r   r   r2   r   rg   c                 &    | j                  dd      S r`   ra   rb   s    r$   rd   z1Filters.get_max_tokens_per_hour.<locals>.<lambda>  s    AEE+q<Q r@   re   r   i  rB   )r,   rn   r+   sortr/   rangemax)r   r   purchase_timesr   r2   r4   buy_transactions	first_buy
block_time	max_countnleftrightcounts                 r$   get_max_tokens_per_hourzFilters.get_max_tokens_per_hour  s_    M$5$5h$?'++Hb9 * 	2K??#45&??>2>L .:UrRVVF^u=TUU#,2QRI"{A6J%%j1	2"  		 1X 	.E '.*>>$F	 !'.*>>$FDL1$EIu-I		. 5  Vs   D3Dreturnc                 >   | r| j                  d      sy| j                  dg       }d}d}|D ]_  }|j                  d      du r|j                  d      }|dz  }|dk(  s||dz  }:t        |t        t        f      sQ|t        k\  s[|dz  }a |dk(  ry||z  d	z  }|S )
uK  
        Возвращает процент токенов, которые удерживались долго на кошельке.
        
        Args:
            wallet_result: результат от process_wallet_transactions_result в формате:
                        {"wallet": "...", "tokens": [{"token": "...", "buy_in_valid_mc": bool, 
                        "first_hold_time": int|'hold'|None, "transactions": [...]}]}

        Returns:
            float: процент токенов, удержанных достаточно долго (0.0–100.0)
        r<   rk   r   r   Fr   rB   r   rl   )r,   r   r-   r.   MIN_HOLD_TIME_SECONDS)r   r   valid_hold_tokenstotal_tokensr   r   
percentages          r$   get_hold_time_on_wallet_percentz'Filters.get_hold_time_on_wallet_percent  s     M$5$5h$?'++Hb9* 	+K01U:)oo.?@OAL&(O,C!Q&!Oc5\:"&;;%*%	+ 1',6#=
r@   c                    | r| j                  d      sy| j                  dg       }d}d}d}d}|D ]  }|j                  d      s|j                  dg       }|D cg c]  }|j                  d      dk(  s| }	}|	sN|dz  }d	}
|	D ]e  }|j                  d
d      }t        |j                  dd            }t        |cxk  r
t        k  sDn G|dz  }|t        k  r|dz  }|t        k\  sdd}
g |
s|dz  } |dk(  ry||z  dz  }|S c c}w )u\  
        Возвращает процент токенов, где есть хотя бы одна покупка >= MIN_BUY
        в пределах допустимой рыночной капитализации.
        
        Args:
            wallet_result: результат от process_wallet_transactions_result в формате:
                          {"wallet": "...", "tokens": [{"token": "...", "buy_in_valid_mc": bool, "transactions": [...]}]}
        
        Returns:
            float: процент токенов с крупными покупками (0.0-100.0)
        r<   rk   r   r   r2   r   rg   rB   Fr   r   Trl   )r,   rX   ry   rz   MIN_BUY)r   r   valid_tokensr   
total_buys
small_buysr   r2   r4   r   has_big_buy_in_valid_mcr\   r   r   s                 r$   get_min_buy_percentzFilters.get_min_buy_percentC  sH    M$5$5h$?'++Hb9

* 	"K??#45&??>2>L-9UrRVVF^u=TUU#AL ',#& 7VVD!_{A 67	!R9>9!OJ 7*"a
 G+26/7 '!1	"4 1 #\1S8
7  Vs   D
6D
c                    | r| j                  d      sy| j                  dg       }|D ci c]  }|d   |
 }}d}d}|D ]  }|j                  d      s|dz  }|j                  d      }|j                  |i       }	|	j                  dd      sRdkD  sX|j                  dg       }
t        fd	|
D              }|s|dz  } |dk(  ry||z  d
z  }|S c c}w )u  
        Возвращает процент токенов, купленных до миграции.
        Токены без migration_time считаются как НЕ купленные до миграции.
        
        Args:
            wallet_result: результат от process_wallet_transactions_result в формате:
                          {"wallet": "...", "tokens": [{"token": "...", "buy_in_valid_mc": bool, "transactions": [...]}]}
            tokens_info: информация о токенах с миграцией и создателем из get_tokens_migration_time_and_creator
        
        Returns:
            float: процент токенов, купленных до миграции (0.0-100.0)
        r<   rk   r;   r   r   rB   rF   r2   c              3   t   K   | ]/  }|j                  d       dk(  xr |j                  dd      k   1 yw)r   rg   r   r   Nra   )r{   r4   rM   s     r$   r|   z0Filters.get_migration_percent.<locals>.<genexpr>  s>      * FF6Ne+X{A0F.0XX*s   58rl   )r,   r}   )r   r9   r   itemtokens_info_dictmigration_tokensr   r   r;   
token_infor2   buy_until_migrationmigration_percentrM   s                @r$   get_migration_percentzFilters.get_migration_percentz  s    M$5$5h$?'++Hb9 =HHDDM4/HH* 	*K??#45ALOOG,E)--eR8J (^^Iq9N.1"4*~rB&) *** '# '$)$%	*( 1-<C  ; Is   Cc                    | r| j                  d      sy| j                  dg       }| j                  d      }|sy|D ci c]  }|d   |
 }}d}d}|D ]X  }|j                  d      s|dz  }|j                  d      }	|j                  |	i       }
|
j                  d      }||k(  sT|dz  }Z |dk(  ry||z  d	z  }|S c c}w )
u  
        Возвращает процент токенов, созданных тем же кошельком.
        
        Args:
            wallet_result: результат от process_wallet_transactions_result в формате:
                          {"wallet": "...", "tokens": [{"token": "...", "buy_in_valid_mc": bool, "transactions": [...]}]}
            tokens_info: информация о токенах с миграцией и создателем из get_tokens_migration_time_and_creator
        
        Returns:
            float: процент токенов, созданных тем же кошельком (0.0-100.0)
        r<   rk   r   r;   r   r   rB   rE   rl   ra   )r   r9   r   r   r   r   created_tokensr   r   r;   r   rE   created_percents                r$   get_created_tokens_percentz"Filters.get_created_tokens_percent  s     M$5$5h$?'++Hb9""8, =HHDDM4/HH* 	$K??#45ALOOG,E)--eR8J !nnY/G& !#	$ 1)L8C?- Is   B?c           	      ,   | j                   }| j                  }|r|j                  d      sy|j                  dg       }|D ci c]  }|d   |
 }}d}d}	|D ]  }
|
j                  d      s|
j                  d      }|j                  |i       }|j                  dd      }|dvrP|dz  }	 t               j	                  |      }|d	   |d
   }|
j                  dg       D cg c]c  }|j                  d      dk(  rM|j                  dd      |k  r8t
        |j                  dd      cxk  r	t        k  rn n|j                  dd      e }}|rt        fd|D              |k\  r|	dz  }	 |dk(  ry|	|z  dz  }||k\  S c c}w c c}w #  Y :xY w)Nr<   Fr;   r   r   rF   )r   rB   rB   	ath_priceath_timer2   r   rg   r   r   c              3   4   K   | ]  }|z
  |z  d z    yw)rl   Nr   )r{   r\   r   s     r$   r|   z-Filters.filter_normal_plus.<locals>.<genexpr>  s     %Wby2~&;c&A%Ws   rl   )r   r9   r,   r   get_ath_of_tokenry   rz   r   )rP   admission_percentprofit_percentager   r9   r   r   r   valid_tokens_countprofitable_tokens_countr   r;   r   rM   ath_infor   r4   
valid_buysnon_mig_profit_percentr   s                      @r$   filter_normal_pluszFilters.filter_normal_plus  s   **&&M$5$5h$?'++Hb9<GHDDM4/HH"#* 	K??#45OOG,E)--eR8J'^^Iq9NV+!#!844U;$[1	#J/ /:oonb.Q(*v%/{A.(:&"&&q/K^K FF4O
  #%WJ%W"W[l"l+q0+5	> ""9<N"NRU!U%):::Q I.s%   F/7F&A(F	 F	FFc                     	 |dk(  r|dk(  r|r	|r|r|r|ryy|r'|r%|r#|r|r|dk\  ry|dk(  ryy	| j                         ryyy	# t        $ r}t        d
|        Y d}~yd}~ww xY w)u   
        Классифицирует кошелек на основе фильтров и количества токенов с покупкой в валидном MC.
        rB   z
GOLD FRESHFRESHrC   GOLDSILVER
NORMALPlUSNORMALTRASHzERROR in classification: NERROR)r   r1   r*   )	rP   
len_tokenslen_tokens_with_buy_in_valid_mcis_tokens_per_hour_validis_hold_time_validis_min_buy_validis_migration_validis_created_tokens_validr5   s	            r$   classificationzFilters.classification  s    
	Q2a7).FK[`r  xO+ "&>CS%*A6!;%8A='  ..0+#  	-aS12	s&   A A A A 	A#AA#c                    | j                  |      }|| _        |d   D cg c]  }|d   	 }}| j                  |      }|| _        t	        |d         }t	        |d   D cg c]  }|j                  d      s| c}      }| j                  |      }	| j                  |      }
| j                  |      }| j                  ||      }| j                  ||      }|||	|
|||d}|S c c}w c c}w )z*
        Args:
            wallet
        r<   r;   r   )r   r   max_tokens_per_hourhold_time_percentmin_buy_percentr   created_tokens_percent)r   r   rU   r9   r/   r,   r   r   r   r   r   )rP   r   r   r   
token_listr9   r   r;   r   r   r   r   r   r   metricss                  r$   wallet_metricszFilters.wallet_metrics6  s    ??G*>KH>UV{k'*V
V@@L&x01
*--PXBY.z]b]f]fgx]yu.z*{'"::=I @@O22=A 66}kR!%!@!@P[!\ %/N#6!2.!2&<
 / W /{s   C% C*7C*c           	         |d   }|d   }|d   }|d   }|d   }|d   }|d   }t         }	|dk  r	d	}
d	}d	}d	}nt        }
t        }t        }t        }||	k  }||
k\  }||k\  }||k\  }||k  }| j                  |||||||      }||||||||d
S )Nr   r   r   r   r   r   r   rC   2   )r   r   r   r   r   r   r   r   )MAX_TOKENS_PER_HOURMIN_HOLD_TIME_PERCENTMIN_NORMAL_BUYS_PERCENT#MIN_TOKENS_BEFORE_MIGRATION_PERCENTMAX_CREATED_PERCENT_PERCENTr   )rP   r   r   r   r   r   r   r   r   passed_max_tokens_per_hourpassed_hold_time_percentpassed_min_buy_percentpassed_migration_percentpassed_created_tokens_percentr   r   r   r   r   r   s                       r$   apply_filterszFilters.apply_filtersY  s   *1,*?
*12S*T'*12G*H*12E*F*12C*D*12E*F*12J*K%8"*q0.0$.0".0$.0).C$.E".Q$.I) $7:T#T .2JJ*.DD.2JJ#9=Z#Z""+$#
 %/N#6!2.!2&<

 
	
r@   N)r   r   r   r   r   r.   r   r   r   r   ADMISSION_PERCENTPROFIT_PERCENT_FOR_NORMALSr   r   r   r  r   r@   r$   r   r     s     6 6p $% $ $L 4 4l 0! 0!d , ,d 4EXr 0;jB F5
r@   r   )collectionsr   clickhouse_driverr   asynciosysr   r   r+   abspathr   dirname__file__API.coingeckoAPIr   
API.jupAPIr   utils.config	utils.StMr   r
   r   r   r@   r$   <module>r     st    # $  
 	 RWW__X-F MN O )   "M M`o
f o
r@   