1
1
from __future__ import annotations
2
2
3
- from typing import Any , Iterable , List , Optional , Type , TypeVar , Union
3
+ from typing import Any , Iterable , List , Optional , Type , Union
4
4
5
5
from eth_typing import URI
6
6
from typing_extensions import Protocol
7
7
from web3 import HTTPProvider
8
8
from web3 .types import RPCEndpoint , RPCResponse
9
-
10
- from ankr import types
11
9
from ankr .exceptions import APIError
12
10
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
-
18
11
19
12
class MultichainHTTPProvider (HTTPProvider ):
20
13
def __init__ (
@@ -27,8 +20,26 @@ def __init__(
27
20
endpoint_uri = endpoint_uri or "https://rpc.ankr.com/multichain/"
28
21
super ().__init__ (endpoint_uri + api_key , request_kwargs , session )
29
22
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
+
30
39
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
+ )
32
43
if response .get ("error" ):
33
44
raise APIError (response ["error" ])
34
45
if "result" not in response :
@@ -38,29 +49,27 @@ def make_request(self, method: RPCEndpoint, params: Any) -> RPCResponse:
38
49
def call_method (
39
50
self ,
40
51
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" ])
47
57
return reply
48
58
49
59
def call_method_paginated (
50
60
self ,
51
61
* ,
52
62
rpc : str ,
53
- request : TRequestPaginated ,
54
- reply_type : Type [ TReplyPaginated ] ,
63
+ request : Any ,
64
+ reply : Any ,
55
65
iterable_name : str ,
56
- iterable_type : Type [TReply ],
66
+ iterable_type : Type [Any ],
57
67
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" ])
62
71
63
- items : List [TReply ] = getattr (reply , iterable_name ) or []
72
+ items : List [Any ] = getattr (reply , iterable_name ) or []
64
73
65
74
if limit :
66
75
if limit <= len (items ):
@@ -70,12 +79,12 @@ def call_method_paginated(
70
79
71
80
yield from items
72
81
73
- if reply .next_page_token :
74
- request .page_token = reply .next_page_token
82
+ if reply .nextPageToken :
83
+ request .pageToken = reply .nextPageToken
75
84
yield from self .call_method_paginated (
76
85
rpc = RPCEndpoint (rpc ),
77
86
request = request ,
78
- reply_type = reply_type ,
87
+ reply = reply ,
79
88
iterable_name = iterable_name ,
80
89
iterable_type = iterable_type ,
81
90
limit = limit ,
0 commit comments