Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 26 additions & 10 deletions clawmes/delegation/encoding.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,25 @@

from collections.abc import Sequence

from eth_abi import encode as abi_encode
from eth_utils import keccak

from clawmes.delegation.types import SignedDelegation, UnsignedDelegation


# eth-abi / eth-utils are imported lazily: Hermes never auto-installs plugin
# dependencies, and this module is reached from ``import clawmes`` (via
# commands.delegation → compiler), so a module-level import would make the
# whole plugin fail to load — and ``hermes plugins validate`` fail — wherever
# the packages are missing. The wrappers keep every call site unchanged.
def abi_encode(types: Sequence[str], values: Sequence[object]) -> bytes:
from eth_abi import encode

return encode(types, values)


def keccak(*args: object, **kwargs: object) -> bytes:
from eth_utils import keccak as _keccak

return _keccak(*args, **kwargs)

# The Solidity signature of the Delegation tuple (with args) used for the
# permission context, disableDelegation, and getDelegationHash. Caveats
# carry (enforcer, terms, args) on the wire even though args is excluded
Expand Down Expand Up @@ -55,15 +69,17 @@ def selector(signature: str) -> str:
return "0x" + keccak(text=signature)[:4].hex()


# Precomputed selectors (verified against viem toFunctionSelector).
SEL_REDEEM = selector("redeemDelegations(bytes[],bytes32[],bytes[])")
SEL_DISABLE = selector(f"disableDelegation({_DELEGATION_TUPLE})")
SEL_GET_HASH = selector(f"getDelegationHash({_DELEGATION_TUPLE})")
SEL_DISABLED = selector("disabledDelegations(bytes32)")
# Precomputed selectors (verified against viem toFunctionSelector). Kept as
# literals so importing this module does not need eth-utils; each equals
# ``selector(<signature>)`` and tests/delegation/test_encoding.py pins them.
SEL_REDEEM = "0xcef6d209" # redeemDelegations(bytes[],bytes32[],bytes[])
SEL_DISABLE = "0x49934047" # disableDelegation(_DELEGATION_TUPLE)
SEL_GET_HASH = "0x66134607" # getDelegationHash(_DELEGATION_TUPLE)
SEL_DISABLED = "0x2d40d052" # disabledDelegations(bytes32)

# Enforcer read selectors (spentMap / callCounts share the same signature).
SEL_SPENT_MAP = selector("spentMap(address,bytes32)")
SEL_CALL_COUNTS = selector("callCounts(address,bytes32)")
SEL_SPENT_MAP = "0x9dd5d9ab" # spentMap(address,bytes32)
SEL_CALL_COUNTS = "0x19054d89" # callCounts(address,bytes32)


# ─── caveat terms encoders ──────────────────────────────────────────────
Expand Down
20 changes: 20 additions & 0 deletions plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,26 @@ description: Hermes Agent for crypto. Wallet, swaps, DeFi, launches, automation.
author: Clawnch
kind: standalone

# Declared for `hermes plugins validate` / install hints; Hermes never
# auto-installs these. Mirrors [project].dependencies in pyproject.toml
# (plus eth-abi, which clawmes imports directly).
python_dependencies:
- "web3>=7.0.0,<8"
- "eth-account>=0.13.0,<1"
- "eth-abi>=5.0.0,<6"
- "eth-utils>=4.0.0,<6"
- "mnemonic>=0.21,<1"
- "pycryptodome>=3.20.0,<4"
- "keyring>=25.0.0,<26"
- "pydantic>=2.7,<3"
- "httpx>=0.27,<1"
- "tenacity>=8.5,<10"
- "python-dotenv>=1.0,<2"
- "pyyaml>=6.0,<7"
- "rich>=13.7,<15"
- "typing_extensions>=4.12,<5"
- "qrcode>=8.0,<9"

# Informational — the actual surface is registered programmatically in
# register(ctx). This list is the source of truth for what users will see
# in `hermes plugins list`, so it must match what register_all() actually
Expand Down