Skip to content

Commit

Permalink
fix: part of hash fix
Browse files Browse the repository at this point in the history
  • Loading branch information
antazoey committed Nov 29, 2023
1 parent 0b2421f commit 70840ba
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 17 deletions.
12 changes: 12 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,18 @@ txn.add(vault.deposit, amount)
txn(sender=safe)
```

Propose a simple transaction by using `submit=False` as a transaction kwargs so it can await signatures from other signers:

```python
from ape import accounts

safe = accounts.load("my-safe")
other = accounts.load("other")
safe.transfer(other, "1 wei", submit=False)
```

**NOTE**: It may error saying the transaction was not fully signed but that is ok.

You can use the CLI extension to view and sign for pending transactions:

```bash
Expand Down
7 changes: 5 additions & 2 deletions ape_safe/_cli/click_ext.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import click
from ape import accounts
from ape.cli import ApeCliContextObject, ape_cli_context
from click import MissingParameter
from click import MissingParameter, BadOptionUsage

from ape_safe.accounts import SafeContainer

Expand All @@ -28,8 +28,11 @@ def _safe_callback(ctx, param, value):
options = ", ".join(safes.aliases)
raise MissingParameter(message=f"Must specify safe to use (one of '{options}').")

else:
elif value in safes.aliases:
return accounts.load(value)

else:
raise BadOptionUsage("--safe", f"No safe with alias '{value}'")


safe_option = click.option("--safe", callback=_safe_callback)
10 changes: 5 additions & 5 deletions ape_safe/_cli/pending.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ def _list(cli_ctx: SafeCliContext, network, safe) -> None:
"""

_ = network # Needed for NetworkBoundCommand
for safe_tx in safe.client.get_transactions(confirmed=False):
for tx in safe.client.get_transactions(confirmed=False):
rich.print(
f"Transaction {safe_tx.nonce}: "
f"({len(safe_tx.confirmations)}/{safe.confirmations_required}) "
f"safe_tx_hash={safe_tx.safe_tx_hash}"
f"Transaction {tx.nonce}: "
f"({len(tx.confirmations)}/{safe.confirmations_required}) "
f"safe_tx_hash={tx.safe_tx_hash}"
)


Expand Down Expand Up @@ -86,7 +86,7 @@ def approve(cli_ctx: SafeCliContext, network, safe, nonce, execute):
if not txn:
cli_ctx.abort(f"Pending transaction '{nonce}' not found.")

safe_tx = safe.create_safe_tx(**txn.dict())
safe_tx = safe.create_safe_tx(**txn.dict(by_alias=True))
num_confirmations = len(txn.confirmations)
signatures_added = {}

Expand Down
9 changes: 6 additions & 3 deletions ape_safe/_cli/safe_mgmt.py
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,12 @@ def remove(cli_ctx: SafeCliContext, safe):
Stop tracking a locally-tracked Safe
"""

if click.confirm(f"Remove safe {safe.address} ({safe.alias})"):
cli_ctx.safes.delete_account(safe.alias)
cli_ctx.logger.success(f"Safe '{safe.address}' ({safe.alias}) removed.")
alias = safe.alias
address = safe.address

if click.confirm(f"Remove safe {address} ({alias})"):
cli_ctx.safes.delete_account(alias)
cli_ctx.logger.success(f"Safe '{address}' ({alias}) removed.")


@click.command(cls=NetworkBoundCommand)
Expand Down
22 changes: 16 additions & 6 deletions ape_safe/accounts.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from ape.api.address import BaseAddress
from ape.api.networks import LOCAL_NETWORK_NAME, ForkedNetworkAPI
from ape.contracts import ContractInstance
from ape.exceptions import ProviderNotConnectedError
from ape.exceptions import ProviderNotConnectedError, SignatureError
from ape.logging import logger
from ape.managers.accounts import AccountManager, TestAccountManager
from ape.types import AddressType, HexBytes, MessageSignature, SignableMessage
Expand Down Expand Up @@ -169,6 +169,12 @@ def _safe_tx_exec_args(safe_tx: SafeTx) -> List:
return list(safe_tx._body_["message"].values())


def hash_transaction(safe_tx: SafeTx) -> str:
safe_tx.to = safe_tx.to or ZERO_ADDRESS
safe_tx.data = safe_tx.data or b""
return hash_eip712_message(safe_tx).hex()


class SafeAccount(AccountAPI):
account_file_path: Path # NOTE: Cache any relevant data here

Expand Down Expand Up @@ -303,12 +309,13 @@ def create_safe_tx(self, txn: Optional[TransactionAPI] = None, **safe_tx_kwargs)
"gasToken": ZERO_ADDRESS,
"refundReceiver": ZERO_ADDRESS,
}

safe_tx = {**safe_tx, **{k: v for k, v in safe_tx_kwargs.items() if k in safe_tx}}
return self.safe_tx_def(**safe_tx)

def pending_transactions(self) -> Iterator[Tuple[SafeTx, List[SafeTxConfirmation]]]:
for executed_tx in self.client.get_transactions(confirmed=False):
yield self.create_safe_tx(**executed_tx.dict()), executed_tx.confirmations
yield self.create_safe_tx(**executed_tx.dict(by_alias=True)), executed_tx.confirmations

@property
def local_signers(self) -> List[AccountAPI]:
Expand Down Expand Up @@ -457,12 +464,14 @@ def call( # type: ignore[override]
if impersonate:
return self._impersonated_call(txn, **call_kwargs)

return super().call(txn, **call_kwargs)
try:
return super().call(txn, **call_kwargs)
except SignatureError:
# TODO: Create an intermediate receipt object
return None # type: ignore

def get_api_confirmations(self, safe_tx: SafeTx) -> Dict[AddressType, MessageSignature]:
# TODO: This signature is wrong.
safe_tx.to = safe_tx.to or ZERO_ADDRESS
safe_tx_hash = hash_eip712_message(safe_tx).hex()
safe_tx_hash = hash_transaction(safe_tx)
try:
client_confirmations = self.client.get_confirmations(safe_tx_hash)
except SafeClientException:
Expand All @@ -487,6 +496,7 @@ def _contract_approvals(self, safe_tx: SafeTx) -> Mapping[AddressType, MessageSi

def _all_approvals(self, safe_tx: SafeTx) -> Dict[AddressType, MessageSignature]:
approvals = self.get_api_confirmations(safe_tx)

# NOTE: Do this last because it should take precedence
approvals.update(self._contract_approvals(safe_tx))
return approvals
Expand Down
2 changes: 1 addition & 1 deletion ape_safe/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,7 @@ def post_transaction(self, safe_tx: SafeTx, sigs: Dict[AddressType, MessageSigna
)
)
post_dict: Dict = {}
for key, value in tx_data.dict().items():
for key, value in tx_data.dict(by_alias=True).items():
if isinstance(value, HexBytes):
post_dict[key] = value.hex()
elif isinstance(value, OperationType):
Expand Down

0 comments on commit 70840ba

Please sign in to comment.