
    (i_                     8   d Z ddlZddlZddlmZ ddlmZmZmZ ddl	m
Z
mZmZ ddlmZ ddlmZmZmZ dd	lmZ dd
lmZmZ ddlmZmZ ddlmZmZmZmZm Z m!Z!m"Z"m#Z#m$Z$m%Z%m&Z& ddl'm(Z(m)Z)m*Z*m+Z+m,Z,m-Z-m.Z.m/Z/m0Z0m1Z1 ddl2m3Z3m4Z4m5Z5m6Z6 erddl7m8Z8  G d d      Z9y)z
RFQ (Request for Quote) client for the Polymarket CLOB API.

This module provides the RfqClient class which handles all RFQ operations
including creating requests, quotes, and executing trades.
    N)	urlencode)OptionalAnyTYPE_CHECKING   )RequestArgs	OrderArgsPartialCreateOrderOptions)create_level_2_headers)getpostdelete)ROUNDING_CONFIG)round_normal
round_down)BUYSELL)CREATE_RFQ_REQUESTCANCEL_RFQ_REQUESTGET_RFQ_REQUESTSCREATE_RFQ_QUOTECANCEL_RFQ_QUOTEGET_RFQ_REQUESTER_QUOTESGET_RFQ_QUOTER_QUOTESGET_RFQ_BEST_QUOTERFQ_REQUESTS_ACCEPTRFQ_QUOTE_APPROVE
RFQ_CONFIG   )
RfqUserRequestRfqUserQuoteCancelRfqRequestParamsCancelRfqQuoteParamsAcceptQuoteParamsApproveOrderParamsGetRfqRequestsParamsGetRfqQuotesParamsGetRfqBestQuoteParams	MatchType)parse_unitsparse_rfq_requests_paramsparse_rfq_quotes_paramsCOLLATERAL_TOKEN_DECIMALS)
ClobClientc                   J   e Zd ZdZddZddZddededed	edef
d
Z	dedefdZ
	 d dedee   defdZdedefdZ	 d dee   defdZ	 d dedee   defdZd dee   defdZd dee   defdZ	 d dee   defdZdedefdZdedefdZdedefdZdefdZ dedefdZ!y)!	RfqClienta  
    RFQ client for creating and managing RFQ requests and quotes.

    This client is typically accessed via the parent ClobClient's `rfq` attribute:

        client = ClobClient(host, chain_id, key, creds)
        response = client.rfq.create_rfq_request(user_request)
    c                 n    || _         t        j                  | j                  j                        | _        y)z
        Initialize the RFQ client.

        Args:
            parent: The parent ClobClient instance providing auth and config.
        N)_parentlogging	getLogger	__class____name__logger)selfparents     N/var/www/br/venv/lib/python3.12/site-packages/py_clob_client/rfq/rfq_client.py__init__zRfqClient.__init__C   s'     ''(?(?@    returnNc                 8    | j                   j                          y)z
        Verify that L2 authentication is available.

        Raises:
            PolyException: If signer or creds are not configured.
        N)r2   assert_level_2_auth)r8   s    r:   _ensure_l2_authzRfqClient._ensure_l2_authM   s     	((*r<   methodendpointbodyserialized_bodyc                     t        |||      }|||_        t        | j                  j                  | j                  j
                  |      S )a  
        Create L2 authentication headers for a request.

        Args:
            method: HTTP method (GET, POST, PUT, DELETE)
            endpoint: API endpoint path
            body: Optional request body

        Returns:
            Dictionary of authentication headers.
        )rA   request_pathrC   )r   rD   r   r2   signercreds)r8   rA   rB   rC   rD   request_argss         r:   _get_l2_headerszRfqClient._get_l2_headersV   sJ     #&xdS&+:L(%LLLL
 	
r<   c                 6    | j                   j                   | S )zBuild full URL from endpoint.)r2   host)r8   rB   s     r:   
_build_urlzRfqClient._build_urll   s    ,,##$XJ//r<   user_requestoptionsc                 2   |j                   }|j                  }|j                  }|j                  }| j                  j                  ||r|j                  nd      }t        |t              st        |      n|}t        |   }	t        ||	j                        }
t        ||	j                        }t        |	j                        }t        |	j                        }t        |	j                        }|
d| d}|d| d}t        |      }t        |      }| j                  j                  j                   }|t"        k(  r2t%        |t&              }||z  }|d| d}t%        |t&              }|}d}n1||z  }|d| d}t%        |t&              }t%        |t&              }d}|}| j)                          ||t        |      t        |      |d}t+        j,                  |dd      }| j/                  d	t0        ||      }t3        | j5                  t0              ||
      S )a.  
        Create and post an RFQ request from a user request.

        This method:
        1. Resolves the tick size for the token
        2. Rounds price and size according to tick size rules
        3. Calculates amount_in and amount_out based on side
        4. Posts the request to the server

        Args:
            user_order: Simplified order with token_id, price, side, size
            options: Optional tick size override

        Returns:
            Response dict with request_id on success.

        Example:
            >>> response = client.rfq.create_rfq_request(
            ...     RfqUserRequest(
            ...         token_id="123...",
            ...         price=0.5,
            ...         side="BUY",
            ...         size=40,
            ...     )
            ... )
        N.f0)assetInassetOutamountIn	amountOutuserType,:F
separatorsensure_asciiPOSTheadersdata)token_idpricesidesizer2   _ClobClient__resolve_tick_size	tick_size
isinstancestrr   r   r   intamountfloatbuildersig_typer   r*   r-   r@   jsondumpsrJ   r   r   rM   )r8   rN   rO   rc   rd   re   rf   rh   tick_size_strround_configrounded_pricerounded_sizeprice_decimalssize_decimalsamount_decimalsrounded_price_strrounded_size_strsize_num	price_num	user_type	amount_inusdc_amountusdc_amount_str
amount_outasset_in	asset_outrC   rD   ra   s                                r:   create_rfq_requestzRfqClient.create_rfq_requestt   s+   >  ((""     LL??!(Gd
	 /9C.HIi&}5 %UL,>,>?!$(9(9: \//0L--.l112,Q~.>a,?@*1]O1*<= )*+,	 LL((11	 3; $$46OPI"Y.K!,Q.?q,@ AO$_6OPJHI
 #Y.K!,Q.?q,@ AO#O5NOI$%57PQJH I 	  !IZ!
 **TjuU&&v/A4YDOO$67__r<   paramsc                     | j                          d|j                  i}t        j                  |dd      }| j	                  dt
        ||      }t        | j                  t
              ||      S )z
        Cancel an RFQ request.

        Args:
            params: Contains request_id to cancel.

        Returns:
            "OK" on success.
        	requestIdrY   Fr\   DELETEr`   )r@   
request_idrp   rq   rJ   r   r   rM   r8   r   rC   rD   ra   s        r:   cancel_rfq_requestzRfqClient.cancel_rfq_request   sc     	V../**TjuU&&x1CT?[doo&897Q`aar<   c                     | j                          | j                  dt              }t        |      }| j	                  t              }|r| dt        |d       }t        ||      S )z
        Get RFQ requests with optional filtering.

        Args:
            params: Optional filter parameters.

        Returns:
            Paginated response with RFQ requests.
        GET?Tdoseqra   )r@   rJ   r   r+   rM   r   r   r8   r   ra   query_paramsurls        r:   get_rfq_requestszRfqClient.get_rfq_requests   sh     	&&u.>?08 oo./ E9\>?@C3((r<   
user_quotec                 L   |j                   }|j                  }|j                  }|j                  }|j                  }| j
                  j                  ||r|j                  nd      }t        |t              st        |      n|}	t        |	   }
t        ||
j                        }t        ||
j                        }t        |
j                        }t        |
j                        }t        |
j                        }|d| d}|d| d}t        |      }t        |      }| j
                  j                   j"                  }|t$        k(  r2t'        |t(              }||z  }|d| d}t'        |t(              }|}d}n1||z  }|d| d}t'        |t(              }t'        |t(              }d}|}| j+                          |||t        |      t        |      |d}t-        j.                  |dd      }| j1                  d	t2        ||      }t5        | j7                  t2              ||
      S )a  
        Create and post an RFQ quote in response to an RFQ request.

        This method:
        1. Fetches the RFQ request to get token_id
        2. Resolves the tick size for the token
        3. Rounds price and size according to tick size rules
        4. Calculates amount_in and amount_out based on side
        5. Posts the quote to the server

        Args:
            user_quote: Simplified quote with request_id, token_id, price, side, size
            options: Optional tick size override

        Returns:
            Response dict with quote_id on success.

        Example:
            >>> response = client.rfq.create_rfq_quote(
            ...     RfqUserQuote(
            ...         request_id="019a83a9-f4c7-7c96-9139-2da2b2d934ef",
            ...         token_id="123...",
            ...         price=0.5,
            ...         side="SELL",
            ...         size=100.0,
            ...     )
            ... )
        NrQ   rR   rS   )r   rT   rU   rV   rW   rX   rY   Fr\   r_   r`   )r   rc   rd   re   rf   r2   rg   rh   ri   rj   r   r   r   rk   rl   rm   rn   ro   r   r*   r-   r@   rp   rq   rJ   r   r   rM   )r8   r   rO   r   rc   rd   re   rf   rh   rr   rs   rt   ru   rv   rw   rx   ry   rz   r{   r|   r}   r~   r   r   r   r   r   rC   rD   ra   s                                 r:   create_rfq_quotezRfqClient.create_rfq_quote  s6   D  **
&&   LL??!(Gd
	 /9C.HIi&}5 %UL,>,>?!$(9(9: \//0L--.l112,Q~.>a,?@*1]O1*<= )*+,	 LL((11	 3; $$46OPI"Y.K!,Q.?q,@ AO$_6OPJHI
 #Y.K!,Q.?q,@ AO#O5NOI$%57PQJH I 	 $!IZ!
 **TjuU&&v/?WDOO$45w_]]r<   c                     | j                          | j                  dt              }t        |      }| j	                  t              }|r| dt        |d       }t        ||      S )a!  
        Get quotes on requests created by the authenticated user (requester view).

        Returns quotes that others have made on your RFQ requests.

        Args:
            params: Optional filter parameters.

        Returns:
            Paginated response with RFQ quotes.
        r   r   Tr   r   )r@   rJ   r   r,   rM   r   r   r   s        r:   get_rfq_requester_quotesz"RfqClient.get_rfq_requester_quotesz  sf     	&&u.FG.v6 oo67E9\>?@C3((r<   c                     | j                          | j                  dt              }t        |      }| j	                  t              }|r| dt        |d       }t        ||      S )a  
        Get quotes created by the authenticated user (quoter view).

        Returns quotes that you have made on others' RFQ requests.

        Args:
            params: Optional filter parameters.

        Returns:
            Paginated response with RFQ quotes.
        r   r   Tr   r   )r@   rJ   r   r,   rM   r   r   r   s        r:   get_rfq_quoter_quoteszRfqClient.get_rfq_quoter_quotes  sf     	&&u.CD.v6 oo34E9\>?@C3((r<   c                     | j                          | j                  dt              }| j                  t              }|r(|j                  r| dt        d|j                  i       }t        ||      S )z
        Get the best quote for an RFQ request.

        Args:
            params: Contains request_id.

        Returns:
            Single quote object representing the best quote.
        r   r   r   r   )r@   rJ   r   rM   r   r   r   )r8   r   ra   r   s       r:   get_rfq_best_quotezRfqClient.get_rfq_best_quote  sk     	&&u.@Aoo01f''E9k63D3D%EFGHC3((r<   c                     | j                          d|j                  i}t        j                  |dd      }| j	                  dt
        ||      }t        | j                  t
              ||      S )z
        Cancel an RFQ quote.

        Args:
            params: Contains quote_id to cancel.

        Returns:
            "OK" on success.
        quoteIdrY   Fr\   r   r`   )r@   quote_idrp   rq   rJ   r   r   rM   r   s        r:   cancel_rfq_quotezRfqClient.cancel_rfq_quote  s`     	6??+**TjuU&&x1A4Ydoo&67__r<   c           	         | j                          | j                  t        |j                  g            }|j	                  d      rt        |d         dk(  rt        d      |d   d   }| j                  |      }|j	                  d      }|d   }t        |d         }|d   }t        |||||j                  	      }	| j                  j                  |	      }
|
st        d
      |
j                         }i d|j                  d|j                  d| j                  j                  j                   dt#        |d         d|d   d|d   d|d   d|d   d|d   d|d   dt#        |d         d|d   d|d   d|dt#        |d         d|d   }| j$                  j'                  d|j	                  d      |j	                  d      |j	                  d      |j	                  d             t)        j*                  |dd      }| j-                  dt.        ||      }t1        | j3                  t.              ||      S ) a]  
        Accept an RFQ quote (requester side).

        This method:
        1. Fetches the RFQ quote details
        2. Creates a signed order matching the quote
        3. Submits the acceptance with the order

        Args:
            params: Contains request_id, quote_id, and expiration.

        Returns:
            "OK" on success.
        	quote_idsrb   r   RFQ quote not foundrd   re   rf   tokenrc   rd   rf   re   
expirationError creating orderr   r   ownersaltmakerrG   takertokenIdmakerAmounttakerAmountr   nonce
feeRateBpssignatureType	signaturez=Accept payload: requestId=%s, quoteId=%s, tokenId=%s, side=%srY   Fr\   r_   r`   )r@   r   r'   r   r   len	Exception#_get_request_order_creation_payloadrm   r	   r   r2   create_orderdictr   rH   api_keyrk   r7   debugrp   rq   rJ   r   r   rM   )r8   r   resp	rfq_quoteorder_creation_payloadrd   re   rf   r   
order_argsorder
order_dictaccept_payloadrD   ra   s                  r:   accept_rfq_quotezRfqClient.accept_rfq_quote  s    	,,&//):;
 xx3tF|#4#9122LO	!%!I!I)!T&**73%f-+F34&w/((

 ))*5233ZZ\

**
v
 T\\''//

 C
6*+
 Z(
 j*
 Z(
 z),
 :m4
 :m4
 #j67
 Z(
 *\2
 D
  SO!<=!
" K0#
( 	K{+y)y)v&	
 **^
Y^_&&v/BNTcdOO/0 
 	
r<   c                 P   | j                          | j                  t        |j                  g            }|j	                  d      rt        |d         dk(  rt        d      |d   d   }|j	                  dt              }|t        k(  r|j	                  d      }n|j	                  d      }|j	                  d      }|j	                  d	      }t        |t        |      t        |      ||j                  
      }| j                  j                  |      }	|	st        d      |	j                         }
i d|j                  d|j                  d| j                  j                  j                   dt#        |
d         d|
d   d|
d   d|
d   d|
d   d|
d   d|
d   dt#        |
d         d|
d   d|
d   d|dt#        |
d         d|
d   }t%        j&                  |dd      }| j)                  dt*        ||      }t-        | j/                  t*              ||      S ) a`  
        Approve an RFQ order (quoter side).

        This method:
        1. Fetches the RFQ quote details
        2. Creates a signed order based on quote parameters
        3. Submits the approval with the order

        Args:
            params: Contains request_id, quote_id, and expiration.

        Returns:
            "OK" on success.
        r   rb   r   r   re   sizeInsizeOutr   rd   r   r   r   r   r   r   r   rG   r   r   r   r   r   r   r   r   r   rY   Fr\   r_   r`   )r@   r   r'   r   r   r   r   r   r	   rm   r   r2   r   r   r   rH   r   rk   rp   rq   rJ   r   r   rM   )r8   r   
rfq_quotesr   re   rf   rc   rd   r   r   r   approve_payloadrD   ra   s                 r:   approve_rfq_orderzRfqClient.approve_rfq_order&  s    	 //&//):;

 ~~f%Z-?)@A)E122v&q)	 }}VS) 3;==*D==+D==)g&,t((

 ))*5233 ZZ\

**
v
 T\\''//

 C
6*+
 Z(
 j*
 Z(
 z),
 :m4
 :m4
 #j67
 Z(
 *\2
 D
  SO!<=!
" K0#
& **_Z_`&&v/@/SbcOO-. 
 	
r<   c                     | j                          | j                  dt              }t        | j	                  t              |      S )z
        Get RFQ configuration from the server.

        Returns:
            Configuration object with RFQ system parameters.
        r   r   )r@   rJ   r   r   rM   )r8   ra   s     r:   
rfq_configzRfqClient.rfq_config}  s8     	&&uj94??:.@@r<   quotec                    |j                  dt        j                        }t        |t              r|nt        t	        |            }|j                  dt
              }|t        j                  k(  r|j                  d      }|st        d      |t
        k(  rt        nt
        }|t
        k(  r|j                  d      n|j                  d      }|t        d      |j                  d      }|t        d	      t        |      }||||d
S |t        j                  t        j                  fv r|j                  d      }|st        d      |t
        k(  r|j                  d      n|j                  d      }|t        d      |j                  d      }|t        d      t        |      }d|z
  }||||d
S t        d|       )z]
        Build the order creation payload for an RFQ request based on quote details.
        	matchTypere   r   z%missing token for COMPLEMENTARY matchr   r   z.missing sizeIn/sizeOut for COMPLEMENTARY matchrd   z%missing price for COMPLEMENTARY match)r   re   rf   rd   
complementz-missing complement token for MINT/MERGE matchz+missing sizeIn/sizeOut for MINT/MERGE matchz"missing price for MINT/MERGE matchr   zinvalid match type: )r   r)   COMPLEMENTARYri   rj   r   r   r   rm   MINTMERGE)r8   r   raw_match_type
match_typere   r   rf   rd   s           r:   r   z-RfqClient._get_request_order_creation_payload  s    ;	0G0GH .)4 3~./ 	 yy%000 IIg&E GHH3;4CD+/3;599Y'EIIh<OD| PQQIIg&E} GHH%LE	  INNIOO<< IIl+E OPP*.#+599X&599Y;OD| MNNIIg&E} DEE%LE IE	  2>2BCDDr<   )r9   r.   )r=   N)NN)N)"r6   
__module____qualname____doc__r;   r@   rj   r   r   rJ   rM   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:   r0   r0   9   s   A+
c 
S 
 
]` 
lp 
,03 03 0 8<g`$g` 34g` 
	g`Rb)? bC b$ 8<)34)	)B 8<l^ l^ 34l^ 
	l^\)x8J/K )W[ )0)H5G,H )TX )2 9=)45)	),`'; ` `*O
'8 O
S O
bQ
(: Q
s Q
n
AD 
A9E 9E$ 9Er<   r0   ):r   r3   rp   urllib.parser   typingr   r   r   
clob_typesr   r	   r
   headers.headersr   http_helpers.helpersr   r   r   order_builder.builderr   order_builder.helpersr   r   order_builder.constantsr   r   	endpointsr   r   r   r   r   r   r   r   r   r   r   	rfq_typesr    r!   r"   r#   r$   r%   r&   r'   r(   r)   rfq_helpersr*   r+   r,   r-   clientr.   r0   r   r<   r:   <module>r      sv      " / / J J 4 4 4 3 < /       #I
E I
Er<   