o
    rÏiv  ã                   @   s˜  d Z ddlZddlmZmZmZmZ ddlmZ ddl	m
Z
 ddlmZ ddlmZ ddlZddlmZ ejejd	� e e¡Zd
ZdZdZdZdZdZe d¡ZddddddœZG dd„ dƒZ edkrÊe !d¡ e !d¡ e !d¡ e ƒ Z"e !d¡ e !de"j#j$j%› �¡ e !de"j#j$j&› �¡ e !de"j# 'e"j#j$j(d ¡› d!�¡ e !d"¡ e !d#e› �¡ e !d$e)eƒ› �¡ e !d%¡ e !d&¡ e !d'¡ dS dS )(ze
Client ApolloX V2 On-Chain
Utilise Web3 pour interagir avec les smart contracts de futures on-chain
é    N)ÚDictÚListÚOptionalÚTuple)ÚDecimal)ÚWeb3)ÚAccount)ÚLocalAccount)Úget_position_manager)Úlevelz!https://bsc-dataseed.binance.org/é8   Ú*0x1b6F2d3844C6ae7D56ceb3C3643b9060ba28FEb0Ú*0x7B2d74D4C65D5720Fb765adA374cc44a66928e08Ú*0x55d398326f99059fF775485246999027B3197955Ú*0xe9e7CEA3DedcA5984780Bafc599bD69ADd087D56a_  [
    {
        "inputs": [
            {
                "components": [
                    {"internalType": "address", "name": "pairBase", "type": "address"},
                    {"internalType": "bool", "name": "isLong", "type": "bool"},
                    {"internalType": "address", "name": "tokenIn", "type": "address"},
                    {"internalType": "uint96", "name": "amountIn", "type": "uint96"},
                    {"internalType": "uint80", "name": "qty", "type": "uint80"},
                    {"internalType": "uint64", "name": "price", "type": "uint64"},
                    {"internalType": "uint64", "name": "stopLoss", "type": "uint64"},
                    {"internalType": "uint64", "name": "takeProfit", "type": "uint64"},
                    {"internalType": "uint24", "name": "broker", "type": "uint24"}
                ],
                "internalType": "struct IBook.OpenDataInput",
                "name": "data",
                "type": "tuple"
            }
        ],
        "name": "openMarketTrade",
        "outputs": [{"internalType": "bytes32", "name": "tradeHash", "type": "bytes32"}],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [{"internalType": "bytes32", "name": "tradeHash", "type": "bytes32"}],
        "name": "closeTrade",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {"internalType": "bytes32", "name": "tradeHash", "type": "bytes32"},
            {"internalType": "uint96", "name": "amount", "type": "uint96"}
        ],
        "name": "addMargin",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [
            {"internalType": "bytes32", "name": "tradeHash", "type": "bytes32"},
            {"internalType": "uint64", "name": "takeProfit", "type": "uint64"},
            {"internalType": "uint64", "name": "stopLoss", "type": "uint64"}
        ],
        "name": "updateTradeTpAndSl",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    },
    {
        "inputs": [{"internalType": "address", "name": "user", "type": "address"}],
        "name": "getPositionsV2",
        "outputs": [
            {
                "components": [
                    {"internalType": "address", "name": "user", "type": "address"},
                    {"internalType": "uint32", "name": "userOpenTradeIndex", "type": "uint32"},
                    {"internalType": "uint64", "name": "entryPrice", "type": "uint64"},
                    {"internalType": "address", "name": "pairBase", "type": "address"},
                    {"internalType": "address", "name": "tokenIn", "type": "address"},
                    {"internalType": "uint96", "name": "margin", "type": "uint96"},
                    {"internalType": "uint64", "name": "stopLoss", "type": "uint64"},
                    {"internalType": "uint64", "name": "takeProfit", "type": "uint64"},
                    {"internalType": "uint24", "name": "broker", "type": "uint24"},
                    {"internalType": "bool", "name": "isLong", "type": "bool"},
                    {"internalType": "uint96", "name": "openFee", "type": "uint96"},
                    {"internalType": "int256", "name": "longAccFundingFeePerShare", "type": "int256"},
                    {"internalType": "uint96", "name": "executionFee", "type": "uint96"},
                    {"internalType": "uint40", "name": "timestamp", "type": "uint40"},
                    {"internalType": "uint80", "name": "qty", "type": "uint80"},
                    {"internalType": "uint40", "name": "holdingFeeRate", "type": "uint40"},
                    {"internalType": "uint256", "name": "openBlock", "type": "uint256"}
                ],
                "internalType": "struct ITrading.OpenTrade[]",
                "name": "",
                "type": "tuple[]"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [{"internalType": "bytes32", "name": "tradeHash", "type": "bytes32"}],
        "name": "getPositionByHashV2",
        "outputs": [
            {
                "components": [
                    {"internalType": "address", "name": "user", "type": "address"},
                    {"internalType": "uint32", "name": "userOpenTradeIndex", "type": "uint32"},
                    {"internalType": "uint64", "name": "entryPrice", "type": "uint64"},
                    {"internalType": "address", "name": "pairBase", "type": "address"},
                    {"internalType": "address", "name": "tokenIn", "type": "address"},
                    {"internalType": "uint96", "name": "margin", "type": "uint96"},
                    {"internalType": "uint64", "name": "stopLoss", "type": "uint64"},
                    {"internalType": "uint64", "name": "takeProfit", "type": "uint64"},
                    {"internalType": "uint24", "name": "broker", "type": "uint24"},
                    {"internalType": "bool", "name": "isLong", "type": "bool"},
                    {"internalType": "uint96", "name": "openFee", "type": "uint96"},
                    {"internalType": "int256", "name": "longAccFundingFeePerShare", "type": "int256"},
                    {"internalType": "uint96", "name": "executionFee", "type": "uint96"},
                    {"internalType": "uint40", "name": "timestamp", "type": "uint40"},
                    {"internalType": "uint80", "name": "qty", "type": "uint80"},
                    {"internalType": "uint40", "name": "holdingFeeRate", "type": "uint40"},
                    {"internalType": "uint256", "name": "openBlock", "type": "uint256"}
                ],
                "internalType": "struct ITrading.OpenTrade",
                "name": "",
                "type": "tuple"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [{"internalType": "bytes32", "name": "tradeHash", "type": "bytes32"}],
        "name": "getPendingTrade",
        "outputs": [
            {
                "components": [
                    {"internalType": "address", "name": "user", "type": "address"},
                    {"internalType": "uint64", "name": "price", "type": "uint64"},
                    {"internalType": "address", "name": "pairBase", "type": "address"},
                    {"internalType": "uint96", "name": "margin", "type": "uint96"},
                    {"internalType": "uint64", "name": "stopLoss", "type": "uint64"},
                    {"internalType": "uint64", "name": "takeProfit", "type": "uint64"},
                    {"internalType": "uint24", "name": "broker", "type": "uint24"},
                    {"internalType": "bool", "name": "isLong", "type": "bool"},
                    {"internalType": "uint80", "name": "qty", "type": "uint80"},
                    {"internalType": "uint256", "name": "blockNumber", "type": "uint256"}
                ],
                "internalType": "struct ITrading.PendingTrade",
                "name": "",
                "type": "tuple"
            }
        ],
        "stateMutability": "view",
        "type": "function"
    },
    {
        "inputs": [{"internalType": "bytes32", "name": "tradeHash", "type": "bytes32"}],
        "name": "cancelPendingTrade",
        "outputs": [],
        "stateMutability": "nonpayable",
        "type": "function"
    }
]Ú*0x7130d2a12b9bcbfae4f2634d864a1ee1ce3ead9cÚ*0xD89aE81e55b1Bd46591CB5555209fdF8fFb43b76Ú*0x2170ed0880ac9a755fd29b2688956bd959f933f8Ú*0xbb4CdB9CBd36B01bD1cBaEBF2De08d9173bc095cÚ*0x570A5D26f7765Ecb712C0924E4De545B89fd43dF)ÚBTCÚBTCUSD_DEGENÚETHÚBNBÚSOLc                   @   sÌ   e Zd ZdZdefdedefdd„Zdefdd	„Zdefd
d„Z	de
e fdd„Z		ddedededededededee fdd„Zdedee fdd„Zdedefdd„Zdedededefdd„ZdS ) ÚApolloXV2ClientzC
    Client pour interagir avec ApolloX V2 on-chain perpetuals
    NÚprivate_keyÚrpc_urlc              
   C   sî   t t  |¡ƒ| _| j ¡ stdƒ‚t d| jjj› d�¡ d| _	|r[t
 |¡| _	t d| j	j› �¡ zt| j	jdd�| _W n% tyZ } zt d|› �¡ d| _W Y d}~nd}~ww t d	¡ d| _| jjjt  t¡td
�| _t d¡ dS )u•   
        Initialise le client Web3

        Args:
            private_key: ClÃ© privÃ©e du wallet (avec 0x)
            rpc_url: URL RPC BSC
        u)   Impossible de se connecter au rÃ©seau BSCu    âœ… ConnectÃ© Ã  BSC (chain_id: ú)Nu   âœ… Wallet chargÃ©: zpositions.json)Úwallet_addressÚstorage_fileu)   âš ï¸�  Position manager non disponible: u0   âš ï¸�  Aucune clÃ© privÃ©e - mode lecture seule©ÚaddressÚabiu!   âœ… Client ApolloX V2 initialisÃ©)r   ÚHTTPProviderÚw3Úis_connectedÚConnectionErrorÚloggerÚinfoÚethÚchain_idÚaccountr   Úfrom_keyr"   r
   Úposition_managerÚ	ExceptionÚwarningÚcontractÚto_checksum_addressÚAPOLLOX_V2_CONTRACTÚAPOLLOX_V2_ABI)Úselfr   r   Úe© r7   úM/var/www/html/HyperOracle/crypto_trader/apollo_degen_bot/apollox_v2_client.pyÚ__init__Ç   s2   
þ€þ
þzApolloXV2Client.__init__Úreturnc                 C   s.   | j sdS | jj | j j¡}t| j |d¡ƒS )u#   RÃ©cupÃ¨re la balance BNB du walletç        Úether)r,   r%   r*   Úget_balancer"   ÚfloatÚfrom_wei)r5   Úbalance_weir7   r7   r8   r=   ó   s   zApolloXV2Client.get_balancec                 C   sL   | j sdS t d¡}| jjjt t¡|d�}|j	 
| j j¡ ¡ }t|d ƒS )u   RÃ©cupÃ¨re la balance USDTr;   z–[{"constant":true,"inputs":[{"name":"_owner","type":"address"}],"name":"balanceOf","outputs":[{"name":"balance","type":"uint256"}],"type":"function"}]r!   ç ÈNgmÁ«C)r,   ÚjsonÚloadsr%   r*   r1   r   r2   ÚUSDT_BSCÚ	functionsÚ	balanceOfr"   Úcallr>   )r5   Ú	erc20_abiÚusdt_contractÚbalancer7   r7   r8   Úget_usdt_balanceû   s   
þz ApolloXV2Client.get_usdt_balancec                 C   s  | j sg S zl| jj | j j¡ ¡ }g }|D ]Y}z8| jj |¡ ¡ }| |d  ¡ |d |d |d |d d |d d |d	 d
 |d d
 |d d
 dœ	¡ W q t	yn } zt
 d| ¡ › d|› �¡ W Y d}~qd}~ww |W S  t	y� } zt
 d|› �¡ g W  Y d}~S d}~ww )u!   RÃ©cupÃ¨re les positions ouvertesr   é   é   é   é   rA   é   ç    _ Bé   ç    „×—Aé   é   )	Ú	tradeHashÚuserÚpairBaseÚisLongÚmarginÚqtyÚ
entryPriceÚstopLossÚ
takeProfitu   Erreur rÃ©cupÃ©ration position z: NzErreur get_positions: )r,   r1   rE   ÚgetPositionsV2r"   rG   ÚgetPositionByHashV2ÚappendÚhexr/   r(   r0   Úerror)r5   Útrade_hashesÚ	positionsÚ
trade_hashÚpositionr6   r7   r7   r8   Úget_positions  s<   





÷€þ€þzApolloXV2Client.get_positionsr   ÚpairÚis_longÚ
margin_usdÚleverageÚpriceÚ	stop_lossÚtake_profitc           !      C   sl  | j s
t d¡ dS �z|}|}	t t |d¡¡}
t|d ƒ}t|| | d ƒ}d}|r4|d|  }n|d|  }t|d ƒ}|rK|d	 }|d
 }n|d }|d }t|d ƒ}t|d ƒ}t d¡ t d|d›d|d›�¡ t d|d›d|	d›�¡ t d|d›d|d›d�¡ t d¡ |
|t t	¡|||||df	}| j
jj}t d| j
 |d¡d›d�¡ | jj |¡ | j jd|| j
j | j j¡tdœ¡}| j  |¡}| j
j |j¡}t d| ¡ › �¡ | j
jj|dd�}|d  dk�rÅt d!|d" › �¡ d}d#}|d$ D ]B}|d%  ¡ t ¡ k�rGt|d& ƒd'k�rG|d& d  ¡  ¡ }t d(|› �¡ || ¡ k�rG|d& d  ¡ }t d)|› �¡  n�qt d*|› �¡ |�s]t d+¡ | ¡ }t d,| jdu› �¡ | j�r½t d-¡ z&t d.¡ | jj|| ¡ ||
|||||| | ||	|d/ d0� t d1¡ W n% t �y¼ } zt d2|› �¡ tjd3|› �d4d5� W Y d}~nd}~ww t d6¡ |W S t d7¡ t d8| ¡ › �¡ t d9| d"d:¡› �¡ z| j
jj!||d/ d;� W W dS  t �y } zt d<t"|ƒ› �¡ W Y d}~W dS d}~ww  t �y5 } zt d=|› �¡ ddl#} t |  $¡ ¡ W Y d}~dS d}~ww )>u¿  
        Ouvre une position on-chain

        IMPORTANT: SL/TP sont gÃ©rÃ©s cÃ´tÃ© BOT, pas on-chain
        Le contrat reÃ§oit des valeurs trÃ¨s larges (jamais atteintes)
        Le bot ferme la position quand le vrai SL/TP est atteint

        Args:
            pair: 'BTC', 'ETH', etc.
            is_long: True pour LONG, False pour SHORT
            margin_usd: Montant de margin en USD
            leverage: Leverage souhaitÃ©
            price: Prix d'entrÃ©e (pour vÃ©rification)
            stop_loss: Prix de stop-loss BOT (stockÃ© pour gestion bot)
            take_profit: Prix de take-profit BOT (stockÃ© pour gestion bot)

        Returns:
            Trade hash ou None si erreur
        õ   Pas de wallet configurÃ©NÚ0xrA   rQ   gü©ñÒMbP?rL   rS   gš™™™™™é?g       @g333333ó?g      à?u   ðŸ”� OPEN POSITION:z   Price: $ú.2fu    â†’ Acceptable: $u      ðŸ¤– BOT SL: $z | BOT TP: $u      ðŸ“¡ On-chain SL: $z | On-chain TP: $z (larges, jamais atteints)u#      â†’ Le BOT gÃ¨re les vrais SL/TPr   u   â›½ Gas price: Úgweiú gweii ¡ ©ÚfromÚgasÚgasPriceÚnonceÚchainIdu   âœ… Transaction envoyÃ©e: éx   ©ÚtimeoutÚstatusu    âœ… Position ouverte! Gas used: ÚgasUsedÚ@0a6da83417411689fd88436e7fa57a7cf1cf635a35194c0658314d4a037382afÚlogsr"   ÚtopicsrM   u   ðŸ”� Checking event sig: u   ðŸ“� Trade Hash extrait: u2   ðŸ”� DEBUG: AprÃ¨s extraction trade_hash, valeur: uA   âš ï¸�  Trade hash non trouvÃ© dans les logs, utilisation TX hashu@   ðŸ”� DEBUG: Avant sauvegarde position, position_manager existe: u.   ðŸ”� DEBUG: EntrÃ© dans le if position_manageru$   ðŸ”� DEBUG: Avant appel add_positionÚblockNumber)rf   Útx_hashÚsymbolÚpair_addressrj   rZ   rl   Úentry_pricer[   rn   ro   Úblock_numberu/   ðŸ”� DEBUG: AprÃ¨s appel add_position, succÃ¨s!u$   âš ï¸�  Erreur sauvegarde position: u)   ðŸ”� DEBUG: Exception dans add_position: T)Úexc_infou#   ðŸ”� DEBUG: Avant return trade_hashu   â�Œ Transaction failedú   TX Hash: ú   Gas used: úN/A©Úblock_identifierú   Revert reason: u   â�Œ Erreur open_position: )%r,   r(   rc   r   r2   ÚPAIRSÚgetÚintr)   rD   r%   r*   Ú	gas_pricer?   r1   rE   ÚopenMarketTradeÚbuild_transactionr"   Úget_transaction_countÚBSC_CHAIN_IDÚsign_transactionÚsend_raw_transactionÚraw_transactionrb   Úwait_for_transaction_receiptÚlowerr3   Úlenr0   r.   Úadd_positionr/   rG   ÚstrÚ	tracebackÚ
format_exc)!r5   ri   rj   rk   rl   rm   rn   ro   Úbot_stop_lossÚbot_take_profitr†   Ú	amount_inr[   ÚSLIPPAGE_PCTÚacceptable_priceÚ	price_intÚ
onchain_slÚ
onchain_tpÚsl_intÚtp_intÚ	open_datar“   ÚtxÚ	signed_txr„   Úreceiptrf   Ú
target_sigÚlogÚ	event_sigr6   Úrevert_errorr    r7   r7   r8   Úopen_position1  sà   



÷
û	€



ô €þ

ý€ý€üzApolloXV2Client.open_positionrf   c                 C   s¬  zºt  | dd¡¡}| jj |¡ ¡ }|d dkr)t d|dd… › d�¡ W dS ||d |d	 |d
 |d |d |d |d |d d |d d |d d |d |d |d |d dœ}t d¡ t d|d dd… › d�¡ t d|d › �¡ t d|d r„dnd› �¡ t d |d! d" d#›d$�¡ t d%|d& d'›�¡ t d(|d) d'›�¡ t d*|d+ d'›�¡ |W S  t	yÕ } zt 
d,|› �¡ W Y d}~dS d}~ww )-uá   
        RÃ©cupÃ¨re l'Ã©tat d'une position on-chain

        Args:
            trade_hash: Hash de la position (bytes32 en hex)

        Returns:
            Dict avec les infos de la position ou None si n'existe pas
        rq   Ú rP   r   u   âš ï¸�  Position Né
   z&... n'existe pas on-chain (margin = 0)rL   rN   rO   é	   é   rM   rQ   rR   rT   é   é   é   )rV   rW   ÚuserOpenTradeIndexrX   ÚtokenInrY   rZ   r[   r\   r]   r^   ÚopenFeeÚexecutionFeeÚ	timestampÚ	openBlocku   ðŸ“Š Position on-chain:z   Trade Hash: rV   z...z	   User: rW   z	   Side: rY   ÚLONGÚSHORTz   Margin: rZ   rA   z.4fz USDTz   Entry: $r\   rr   z   SL: $r]   z   TP: $r^   u   â�Œ Erreur get_position_state: )ÚbytesÚfromhexÚreplacer1   rE   r`   rG   r(   r)   r/   rc   )r5   rf   Útrade_hash_bytesrg   Úresultr6   r7   r7   r8   Úget_position_stateé  sH   



ñ
€þz"ApolloXV2Client.get_position_statec              
   C   sº  | j s
t d¡ dS �z*t d¡ |  |¡}|rAt d¡ |d  ¡ | j j ¡ kr@t d|d › �¡ t d| j j› �¡ W dS n
t d¡ t d	¡ t d
¡ t 	| 
dd¡¡}| jjj}| jj |¡ | j jd|| jj | j j¡tdœ¡}| j  |¡}| jj |j¡}t d| ¡ › �¡ | jjj|dd�}|d dkrÝt d|d › �¡ | jrÚz| jj|| ¡ d|d d� W W dS  tyÙ }	 zt d|	› �¡ W Y d}	~	W dS d}	~	ww W dS t d¡ t d| ¡ › �¡ t d| dd¡› �¡ t d |› �¡ z| jjj||d d!� W n t�y* }
 zt d"t|
ƒ› �¡ W Y d}
~
nd}
~
ww t d#|› �¡ W dS  t�y\ }	 zt d$|	› �¡ ddl}t |  ¡ ¡ W Y d}	~	dS d}	~	ww )%už   
        Ferme une position

        Args:
            trade_hash: Hash de la position (bytes32 en hex)

        Returns:
            True si succÃ¨s
        rp   Fu4   ðŸ”� VÃ©rification Ã©tat position avant fermeture...u   âœ… Position trouvÃ©e on-chainrW   u!   â�Œ Cette position appartient Ã  z   Notre adresse: uM   âš ï¸�  Impossible de vÃ©rifier l'Ã©tat on-chain (possiblement problÃ¨me ABI)u(      Tentative de fermeture quand mÃªme...u$   ðŸ“¡ Envoi transaction closeTrade...rq   rµ   ià“ ru   u    âœ… Close transaction envoyÃ©e: r{   r|   r~   rL   u    âœ… Position fermÃ©e! Gas used: r   r   rƒ   )rf   Úclose_tx_hashÚ
exit_pricerˆ   u.   âš ï¸�  Erreur mise Ã  jour position fermÃ©e: NTu'   â�Œ Close transaction failed (reverted)rŠ   r‹   rŒ   z   Trade hash: r�   r�   z   Receipt: u   â�Œ Erreur close_position: )!r,   r(   rc   r)   rÉ   rœ   r"   r0   rÄ   rÅ   rÆ   r%   r*   r“   r1   rE   Ú
closeTrader•   r–   r—   r˜   r™   rš   rb   r›   r.   Úclose_positionr/   r‘   rG   rŸ   r    r¡   )r5   rf   Úposition_staterÇ   r“   r­   r®   r„   r¯   r6   r³   r    r7   r7   r8   rÍ   4  s‚   




ý



û	ü	ý€ý
 €ÿ€üzApolloXV2Client.close_positionc              
   C   sä   | j sdS zQt | dd¡¡}t|d ƒ}t|d ƒ}| jj |||¡ | j j	d| j
jj| j
j | j j	¡tdœ¡}| j  |¡}| j
j |j¡}	| j
jj|	dd�}
|
d	 d
kW S  tyq } zt d|› �¡ W Y d}~dS d}~ww )u$   Met Ã  jour stop-loss et take-profitFrq   rµ   rS   i@ ru   r{   r|   r~   rL   u   â�Œ Erreur update_sl_tp: N)r,   rÄ   rÅ   rÆ   r’   r1   rE   ÚupdateTradeTpAndSlr•   r"   r%   r*   r“   r–   r—   r˜   r™   rš   r›   r/   r(   rc   )r5   rf   rn   ro   rÇ   rª   r«   r­   r®   r„   r¯   r6   r7   r7   r8   Úupdate_sl_tp•  s4   ÿûþ
€þzApolloXV2Client.update_sl_tp)r   r   )Ú__name__Ú
__module__Ú__qualname__Ú__doc__ÚBSC_RPC_URLrŸ   r9   r>   r=   rK   r   r   rh   Úboolr’   r   r´   rÉ   rÍ   rÐ   r7   r7   r7   r8   r   Â   s:    ,-øþýüûúùø	
÷ 9Kar   Ú__main__zP================================================================================u$   ðŸ§ª TEST CLIENT APOLLOX V2 ON-CHAINu   
ðŸ“Š Infos rÃ©seau:z   Chain ID: z   Latest block: z   Gas price: rs   rt   u   
ðŸ“� Contrat ApolloX V2:z   Address: z   Fonctions disponibles: u   
âœ… Client prÃªt!u.   
âš ï¸�  Pour trader, fournir une private key:z0   client = ApolloXV2Client(private_key='0x...'))*rÔ   ÚloggingÚtypingr   r   r   r   Údecimalr   Úweb3r   Úeth_accountr   Úeth_account.signers.localr	   rB   r.   r
   ÚbasicConfigÚINFOÚ	getLoggerrÑ   r(   rÕ   r—   r3   ÚAPOLLOX_ORACLE_CONTRACTrD   ÚBUSD_BSCrC   r4   r�   r   r)   Úclientr%   r*   r+   rˆ   r?   r“   r�   r7   r7   r7   r8   Ú<module>   sZ    

 û	   u



"


í