Skip to content

Commit e2044d5

Browse files
authored
fix(client): add rate limiter to Safe Transaction Gateway session (#100)
1 parent a624453 commit e2044d5

3 files changed

Lines changed: 23 additions & 13 deletions

File tree

ape_safe/client/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
from eth_utils import to_hex
1212
from pydantic import TypeAdapter
1313

14-
from ape_safe.client.base import BaseSafeClient
14+
from ape_safe.client.base import BaseSafeClient, RequestsClient
1515
from ape_safe.client.mock import MockSafeClient
1616
from ape_safe.client.types import (
1717
DelegateInfo,
@@ -71,7 +71,9 @@
7171
}
7272

7373

74-
class SafeClient(BaseSafeClient):
74+
class SafeClient(RequestsClient):
75+
"""Client to use to communicate with Safe Client Gateway Service"""
76+
7577
def __init__(
7678
self,
7779
address: AddressType,
@@ -158,8 +160,14 @@ def post_transaction(
158160
tx_data = UnexecutedTxData.from_safe_tx(safe_tx, self.safe_details.threshold)
159161
signature = HexBytes(
160162
reduce(
161-
lambda raw_sig, next_sig: raw_sig
162-
+ (next_sig.encode_rsv() if isinstance(next_sig, MessageSignature) else next_sig),
163+
lambda raw_sig, next_sig: (
164+
raw_sig
165+
+ (
166+
next_sig.encode_rsv()
167+
if isinstance(next_sig, MessageSignature)
168+
else next_sig
169+
)
170+
),
163171
order_by_signer(signatures),
164172
b"",
165173
)
@@ -278,6 +286,7 @@ def remove_delegate(self, delegate: "AddressType", delegator: "AccountAPI"):
278286

279287
__all__ = [
280288
"ExecutedTxData",
289+
"BaseSafeClient",
281290
"MockSafeClient",
282291
"OperationType",
283292
"SafeApiTxData",

ape_safe/client/base.py

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,11 @@
55
from typing import TYPE_CHECKING, Optional, Union
66

77
import certifi
8-
import requests
98
import urllib3
109
from ape.types import AddressType, HexBytes, MessageSignature
1110
from eth_utils import keccak
1211
from requests.adapters import HTTPAdapter
12+
from requests_ratelimiter import LimiterSession
1313

1414
from ape_safe.client.types import (
1515
ExecutedTxData,
@@ -24,7 +24,7 @@
2424

2525
if TYPE_CHECKING:
2626
from ape.api import AccountAPI
27-
from requests import Response
27+
from requests import Response, Session
2828

2929
DEFAULT_HEADERS = {
3030
"Accept": "application/json",
@@ -33,10 +33,7 @@
3333

3434

3535
class BaseSafeClient(ABC):
36-
def __init__(self, base_url: str):
37-
self.base_url = base_url
38-
39-
"""Abstract methods"""
36+
"""All custom SafeClient instances should implement this"""
4037

4138
@property
4239
@abstractmethod
@@ -135,11 +132,14 @@ def add_delegate(self, delegate: AddressType, label: str, delegator: "AccountAPI
135132
@abstractmethod
136133
def remove_delegate(self, delegate: AddressType, delegator: "AccountAPI"): ...
137134

138-
"""Request methods"""
135+
136+
class RequestsClient(BaseSafeClient):
137+
def __init__(self, base_url: str):
138+
self.base_url = base_url
139139

140140
@cached_property
141-
def session(self) -> requests.Session:
142-
session = requests.Session()
141+
def session(self) -> "Session":
142+
session = LimiterSession(per_second=5)
143143
adapter = HTTPAdapter(
144144
pool_connections=10, # Doing all the connections to the same url
145145
pool_maxsize=100, # Number of concurrent connections

setup.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@
6868
"eth-utils>=2.1.0,<6",
6969
"pydantic>=2.10.2,<3",
7070
"requests>=2.31.0,<3",
71+
"requests-ratelimiter>=0.7,<1",
7172
],
7273
entry_points={
7374
"ape_cli_subcommands": [

0 commit comments

Comments
 (0)