From 6ff924678757b7e1792e8028c41fdaf727a9258e Mon Sep 17 00:00:00 2001 From: doggie <3859395+fubuloubu@users.noreply.github.com> Date: Wed, 5 Jun 2024 16:05:05 -0400 Subject: [PATCH 1/5] fix: update for API route change --- ape_safe/client/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ape_safe/client/__init__.py b/ape_safe/client/__init__.py index 8bb6b6f..ba697dd 100644 --- a/ape_safe/client/__init__.py +++ b/ape_safe/client/__init__.py @@ -80,7 +80,7 @@ def _all_transactions(self) -> Iterator[SafeApiTxData]: confirmed: Confirmed if True, not confirmed if False, both if None """ - url = f"safes/{self.address}/transactions" + url = f"safes/{self.address}/all-transactions" while url: response = self._get(url) data = response.json() From f7feae641e99a15a44a5c4b0435dcc9dd3a27cbe Mon Sep 17 00:00:00 2001 From: doggie <3859395+fubuloubu@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:45:44 -0400 Subject: [PATCH 2/5] refactor: allow using address or alias --- ape_safe/_cli/safe_mgmt.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ape_safe/_cli/safe_mgmt.py b/ape_safe/_cli/safe_mgmt.py index 6e8e7d1..54700ff 100644 --- a/ape_safe/_cli/safe_mgmt.py +++ b/ape_safe/_cli/safe_mgmt.py @@ -132,12 +132,16 @@ def remove(cli_ctx: SafeCliContext, safe, skip_confirmation): @click.command(cls=ConnectedProviderCommand) @safe_cli_ctx() -@click.argument("address", type=ChecksumAddress) +@click.argument("account") @click.option("--confirmed", is_flag=True, default=None) -def all_txns(cli_ctx: SafeCliContext, address, confirmed): +def all_txns(cli_ctx: SafeCliContext, account, confirmed): """ View and filter all transactions for a given Safe using Safe API """ + if account in cli_ctx.account_manager.aliases: + account = cli_ctx.account_manager.load(account) + + address = cli_ctx.conversion_manager.convert(account, AddressType) # NOTE: Create a client to support non-local safes. client = cli_ctx.safes.create_client(address) From c7e0bc47121ac48752b799258cb1d00c9838af33 Mon Sep 17 00:00:00 2001 From: doggie <3859395+fubuloubu@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:46:33 -0400 Subject: [PATCH 3/5] fix: `/all-transactions` includes incoming transactions now (skip them) --- ape_safe/client/__init__.py | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/ape_safe/client/__init__.py b/ape_safe/client/__init__.py index ba697dd..fb72949 100644 --- a/ape_safe/client/__init__.py +++ b/ape_safe/client/__init__.py @@ -77,7 +77,7 @@ def get_next_nonce(self) -> int: def _all_transactions(self) -> Iterator[SafeApiTxData]: """ - confirmed: Confirmed if True, not confirmed if False, both if None + Get all transactions from safe, both confirmed and unconfirmed """ url = f"safes/{self.address}/all-transactions" @@ -86,13 +86,15 @@ def _all_transactions(self) -> Iterator[SafeApiTxData]: data = response.json() for txn in data.get("results"): - # TODO: Replace with `model_validate()` after ape 0.7. # NOTE: Using construct because of pydantic v2 back import validation error. - if "isExecuted" in txn and txn["isExecuted"]: - yield ExecutedTxData.model_validate(txn) + if "isExecuted" in txn: + if txn["isExecuted"]: + yield ExecutedTxData.model_validate(txn) - else: - yield UnexecutedTxData.model_validate(txn) + else: + yield UnexecutedTxData.model_validate(txn) + + # else it is an incoming transaction url = data.get("next") From a37a9586be6eeaedd3467d3ee52dbfcccaadfbc1 Mon Sep 17 00:00:00 2001 From: doggie <3859395+fubuloubu@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:47:23 -0400 Subject: [PATCH 4/5] fix: just use page request `next` urls directly --- ape_safe/client/base.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ape_safe/client/base.py b/ape_safe/client/base.py index 08e23e6..b751b0f 100644 --- a/ape_safe/client/base.py +++ b/ape_safe/client/base.py @@ -136,10 +136,13 @@ def _http(self): return urllib3.PoolManager(ca_certs=certifi.where()) def _request(self, method: str, url: str, json: Optional[dict] = None, **kwargs) -> Response: - # **WARNING**: The trailing slash in the URL is CRITICAL! - # If you remove it, things will not work as expected. - - api_url = f"{self.transaction_service_url}/api/v1/{url}/" + # NOTE: paged requests include full url already + if url.startswith(f"{self.transaction_service_url}/api/v1/"): + api_url = url + else: + # **WARNING**: The trailing slash in the URL is CRITICAL! + # If you remove it, things will not work as expected. + api_url = f"{self.transaction_service_url}/api/v1/{url}/" do_fail = not kwargs.pop("allow_failure", False) # Use `or 10` to handle when None is explicit. From d55b6649012ce6df7cbf96bef28c37b4f4ca7798 Mon Sep 17 00:00:00 2001 From: doggie <3859395+fubuloubu@users.noreply.github.com> Date: Thu, 6 Jun 2024 10:47:45 -0400 Subject: [PATCH 5/5] fix: accidentally was skipping ExecutedTxData because it was a subclass --- ape_safe/client/base.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ape_safe/client/base.py b/ape_safe/client/base.py index b751b0f..ad50fa2 100644 --- a/ape_safe/client/base.py +++ b/ape_safe/client/base.py @@ -96,7 +96,8 @@ def get_transactions( elif confirmed and not is_confirmed: continue # NOTE: Skip not confirmed transactions - if txn.nonce < next_nonce and isinstance(txn, UnexecutedTxData): + # NOTE: use `type(txn) is ...` because ExecutedTxData is a subclass of UnexecutedTxData + if txn.nonce < next_nonce and type(txn) is UnexecutedTxData: continue # NOTE: Skip orphaned transactions if filter_by_ids and txn.safe_tx_hash not in filter_by_ids: