Skip to content

Commit 6635164

Browse files
committed
refactor(Client): use the _new_ new Safe multichain API tx-service
1 parent 23ad574 commit 6635164

3 files changed

Lines changed: 44 additions & 13 deletions

File tree

ape_safe/client/__init__.py

Lines changed: 43 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import json
2+
import os
23
from collections.abc import Iterator
34
from datetime import datetime
45
from functools import reduce
@@ -32,6 +33,7 @@
3233

3334
if TYPE_CHECKING:
3435
from ape.api import AccountAPI
36+
from requests import Response
3537

3638
APE_SAFE_VERSION = get_package_version(__name__)
3739
APE_SAFE_USER_AGENT = f"Ape-Safe/{APE_SAFE_VERSION} {USER_AGENT}"
@@ -40,7 +42,31 @@
4042
assert len(ORIGIN) <= 200 # NOTE: Must be less than 200 chars
4143

4244
# URL for the multichain client gateway
43-
SAFE_CLIENT_GATEWAY_URL = "https://safe-client.safe.global"
45+
SAFE_CLIENT_GATEWAY_URL = "https://api.safe.global/tx-service"
46+
GATEWAY_API_KEY = os.environ.get("APE_SAFE_GATEWAY_API_KEY")
47+
EIP3770_BLOCKCHAIN_NAMES_BY_CHAIN_ID = {
48+
1: "eth", # Ethereum Mainnet
49+
11155111: "sep", # Ethereum Sepolia
50+
10: "oeth", # Optimism Mainnet
51+
42161: "arb1", # Arbitrum One Mainnet
52+
56: "bnb", # Binance Smart Chain
53+
146: "sonic",
54+
5000: "mantle",
55+
43114: "avax",
56+
1313161554: "aurora",
57+
8453: "base", # Base Mainnet
58+
84532: "basesep", # Base Sepolia
59+
42220: "celo", # Celo Mainnet
60+
100: "gno", # Gnosis Chain
61+
59144: "linea", # Linea Mainnet
62+
137: "pol", # Polygon
63+
534352: "scr", # Scroll
64+
130: "unichain", # Unichain Mainnet
65+
480: "wc", # Worldchain Mainnet
66+
324: "zksync", # zkSync Mainnet
67+
57073: "ink", # Ink Mainnet
68+
800094: "berachain", # Berachain Mainnet
69+
}
4470

4571

4672
class SafeClient(BaseSafeClient):
@@ -55,15 +81,27 @@ def __init__(
5581

5682
if override_url:
5783
base_url = override_url
58-
self.use_client_gateway = False
5984
elif chain_id:
60-
base_url = SAFE_CLIENT_GATEWAY_URL
61-
self.use_client_gateway = True
85+
if chain_id not in EIP3770_BLOCKCHAIN_NAMES_BY_CHAIN_ID:
86+
raise ValueError(f"Chain ID {chain_id} is not a supported chain.")
87+
88+
elif not GATEWAY_API_KEY:
89+
raise ValueError("Must provide API key via 'APE_SAFE_GATEWAY_API_KEY='.")
90+
91+
base_url = (
92+
f"{SAFE_CLIENT_GATEWAY_URL}/{EIP3770_BLOCKCHAIN_NAMES_BY_CHAIN_ID[chain_id]}/api"
93+
)
6294
else:
6395
raise ValueError("Must provide one of chain_id or override_url.")
6496

6597
super().__init__(base_url)
6698

99+
def _request(self, method: str, url: str, json: Optional[dict] = None, **kwargs) -> "Response":
100+
# NOTE: Add authorization header
101+
headers = kwargs.pop("headers", {})
102+
headers.update(dict(Authorization=f"Bearer {GATEWAY_API_KEY}"))
103+
return super()._request(method, url, json=json, headers=headers, **kwargs)
104+
67105
@property
68106
def safe_details(self) -> SafeDetails:
69107
response = self._get(f"/safes/{self.address}")
@@ -77,7 +115,7 @@ def _all_transactions(self) -> Iterator[SafeApiTxData]:
77115
Get all transactions from safe, both confirmed and unconfirmed
78116
"""
79117

80-
url = f"/safes/{self.address}/multisig-transactions/raw"
118+
url = f"/safes/{self.address}/multisig-transactions"
81119
while url:
82120
response = self._get(url)
83121
data = response.json()

ape_safe/client/base.py

Lines changed: 0 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -166,13 +166,6 @@ def _request(self, method: str, url: str, json: Optional[dict] = None, **kwargs)
166166
if url.startswith(self.base_url):
167167
api_url = url
168168

169-
elif (
170-
hasattr(self, "use_client_gateway")
171-
and self.use_client_gateway
172-
and hasattr(self, "chain_id")
173-
):
174-
api_url = f"{self.base_url}/{api_version}/chains/{self.chain_id}{url}"
175-
176169
else:
177170
api_url = f"{self.base_url}/{api_version}{url}"
178171

ape_safe/client/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ class SafeDetails(BaseModel):
2929
nonce: int
3030
threshold: int
3131
owners: list[Address]
32-
master_copy: Address = Field(alias="implementation")
32+
master_copy: Address = Field(alias="masterCopy")
3333
modules: list[Address] = []
3434
fallback_handler: Address = Field(alias="fallbackHandler")
3535
guard: AddressType

0 commit comments

Comments
 (0)