11from __future__ import annotations
22
3- from typing import Any , Iterable , List , Optional , Type , TypeVar , Union
3+ from typing import Any , Iterable , List , Optional , Type , Union
44
55from eth_typing import URI
66from typing_extensions import Protocol
77from web3 import HTTPProvider
88from web3 .types import RPCEndpoint , RPCResponse
9-
10- from ankr import types
119from ankr .exceptions import APIError
1210
13- TRequest = TypeVar ("TRequest" , bound = types .RPCModel )
14- TReply = TypeVar ("TReply" )
15- TRequestPaginated = TypeVar ("TRequestPaginated" , bound = types .RPCRequestPaginated )
16- TReplyPaginated = TypeVar ("TReplyPaginated" , bound = types .RPCReplyPaginated )
17-
1811
1912class MultichainHTTPProvider (HTTPProvider ):
2013 def __init__ (
@@ -27,8 +20,26 @@ def __init__(
2720 endpoint_uri = endpoint_uri or "https://rpc.ankr.com/multichain/"
2821 super ().__init__ (endpoint_uri + api_key , request_kwargs , session )
2922
23+ def clean_nones (self , value ):
24+ """
25+ Recursively remove all None values from dictionaries and lists, and returns
26+ the result as a new dictionary or list.
27+ """
28+ if isinstance (value , list ):
29+ return [self .clean_nones (x ) for x in value if x is not None ]
30+ elif isinstance (value , dict ):
31+ return {
32+ key : self .clean_nones (val )
33+ for key , val in value .items ()
34+ if val is not None
35+ }
36+ else :
37+ return value
38+
3039 def make_request (self , method : RPCEndpoint , params : Any ) -> RPCResponse :
31- response = super ().make_request (method , params )
40+ response = super ().make_request (
41+ method , self .clean_nones (params .to_dict ().copy ())
42+ )
3243 if response .get ("error" ):
3344 raise APIError (response ["error" ])
3445 if "result" not in response :
@@ -38,29 +49,27 @@ def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
3849 def call_method (
3950 self ,
4051 rpc : str ,
41- request : TRequest ,
42- reply_type : Type [TReply ],
43- ) -> TReply :
44- request_dict = request .dict (by_alias = True , exclude_none = True )
45- response = self .make_request (RPCEndpoint (rpc ), request_dict )
46- reply = reply_type (** response ["result" ])
52+ request : Any ,
53+ reply : Any ,
54+ ) -> Any :
55+ response = self .make_request (RPCEndpoint (rpc ), request )
56+ reply = reply .from_dict (** response ["result" ])
4757 return reply
4858
4959 def call_method_paginated (
5060 self ,
5161 * ,
5262 rpc : str ,
53- request : TRequestPaginated ,
54- reply_type : Type [ TReplyPaginated ] ,
63+ request : Any ,
64+ reply : Any ,
5565 iterable_name : str ,
56- iterable_type : Type [TReply ],
66+ iterable_type : Type [Any ],
5767 limit : Optional [int ] = None ,
58- ) -> Iterable [TReply ]:
59- request_dict = request .dict (by_alias = True , exclude_none = True )
60- response = self .make_request (RPCEndpoint (rpc ), request_dict )
61- reply = reply_type (** response ["result" ])
68+ ) -> Iterable [Any ]:
69+ response = self .make_request (RPCEndpoint (rpc ), request )
70+ reply = reply .from_dict (** response ["result" ])
6271
63- items : List [TReply ] = getattr (reply , iterable_name ) or []
72+ items : List [Any ] = getattr (reply , iterable_name ) or []
6473
6574 if limit :
6675 if limit <= len (items ):
@@ -70,12 +79,12 @@ def call_method_paginated(
7079
7180 yield from items
7281
73- if reply .next_page_token :
74- request .page_token = reply .next_page_token
82+ if reply .nextPageToken :
83+ request .pageToken = reply .nextPageToken
7584 yield from self .call_method_paginated (
7685 rpc = RPCEndpoint (rpc ),
7786 request = request ,
78- reply_type = reply_type ,
87+ reply = reply ,
7988 iterable_name = iterable_name ,
8089 iterable_type = iterable_type ,
8190 limit = limit ,
0 commit comments