Skip to content

feat: derive, register, and read agent wallets#121

Merged
MicBun merged 4 commits into
mainfrom
feat/maa-agent-wallets
Jun 10, 2026
Merged

feat: derive, register, and read agent wallets#121
MicBun merged 4 commits into
mainfrom
feat/maa-agent-wallets

Conversation

@MicBun

@MicBun MicBun commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

resolves: https://github.com/truflation/website/issues/4085

Adds Modular Agent Address (MAA) support to the Python SDK so developers can build and operate agent wallets entirely from the client.

What this enables

  • Derive an agent-wallet address off-chain from its rule — before the wallet exists on-chain — so a funder knows where to send funds.
  • Register an agent rule and join an agent address.
  • Read agent rules, allowed actions, instances, owned/rule wallets, and events.

Pieces

  • src/trufnetwork_sdk_py/utils.py — pure derivation: compute_rules_hashderive_rule_idderive_maa_address / derive_maa_address_hex. Byte-exact mirror of the node precompiles and the Go/JS SDKs (eth_hash keccak256, frozen RULES_PREIMAGE layout, last-write-wins dedup, canonical bytewise sort).
  • src/trufnetwork_sdk_py/client.pyTNClient methods over the on-chain actions: maa_create_rule, join_agent_address, and the read getters (maa_get_rule, maa_get_allowed_actions, maa_get_instance, maa_list_by_restricted, maa_list_by_unrestricted, maa_list_instances_by_rule, maa_get_events, maa_is_known), plus result/row TypedDicts.
  • bindings/maa.go — gopy bindings that submit the rule actions and return reads as JSON {column_names, values} (no gopy interface{} conversion).
  • pyproject.toml — adds eth-hash[pycryptodome] for keccak.

Tests

  • 9 pure unit tests (tests/test_maa.py) asserting the frozen golden vectors A/B byte-for-byte, plus canonicalization (order-independence, last-write-wins dedup), the dedup-key no-collision invariant, and input validation. No network required.

The golden vectors are identical across the node and all three SDKs — a one-byte mismatch would derive a different wallet and send funds astray, so they are kept in lockstep.

Summary by CodeRabbit

  • New Features

    • Added Modular Agent Address (MAA) functionality for agent wallet operations, including rule creation, joining agent addresses, and querying MAA instance data.
    • Added utility functions for deriving MAA addresses and computing rule hashes for address derivation.
  • Tests

    • Added comprehensive test suite validating MAA derivation functions and error handling.

@coderabbitai

coderabbitai Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Warning

Review limit reached

@MicBun, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 16 minutes and 1 second. Learn how PR review limits work.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 1aa28ab3-e040-419d-8223-88ba82e1cb18

📥 Commits

Reviewing files that changed from the base of the PR and between 9ccafe0 and cac56fc.

📒 Files selected for processing (13)
  • bindings/maa.go
  • src/trufnetwork_sdk_py/client.py
  • tests/helpers/skips.py
  • tests/test_allow_zeros.py
  • tests/test_batch_operations.py
  • tests/test_bulk_inserter.py
  • tests/test_cache_support.py
  • tests/test_list_streams.py
  • tests/test_permissions.py
  • tests/test_role_management.py
  • tests/test_sequential_inserts.py
  • tests/test_tnclient.py
  • tests/test_transaction_ledger.py
📝 Walkthrough

Walkthrough

This PR implements a complete Modular Agent Addresses (MAA) feature for agent-wallet operations. It adds off-chain cryptographic utilities for rule hash and address derivation, Go bindings for on-chain transaction/read execution, Python SDK methods orchestrating these layers, package-level exports, and comprehensive unit tests validating correctness.

Changes

Modular Agent Addresses (Migration 048)

Layer / File(s) Summary
Off-chain MAA derivation utilities
src/trufnetwork_sdk_py/utils.py, tests/test_maa.py
Implements compute_rules_hash() with canonical entry deduplication/sorting and fee validation, derive_rule_id() combining restricted address and salt, and derive_maa_address() generating deterministic wallet addresses. Tests validate golden vectors, behavioral properties (ordering invariance, last-occurrence-wins dedup), and input constraint enforcement.
Go transaction and read bindings
bindings/maa.go
Low-level Go functions MAACreateRule() and MAAJoin() for on-chain operations, plus read wrappers (MAAGetRule, MAAGetAllowedActions, MAAGetInstance, MAAListByRestricted, MAAListByUnrestricted, MAAListInstancesByRule, MAAGetEvents, MAAIsKnown) that convert results to JSON strings. Handles hex decoding and error wrapping.
Python SDK client API
src/trufnetwork_sdk_py/client.py
Adds TNClient methods: maa_create_rule() validates inputs, derives rule ID locally, submits transaction, optionally waits, returns { tx_hash, rule_id }; join_agent_address() derives MAA address locally and returns { tx_hash, maa_address }; read methods (maa_get_rule, maa_get_allowed_actions, etc.) parse JSON responses into typed dicts. Includes internal normalization helpers and result mapping.
SDK package exports and dependencies
pyproject.toml, src/trufnetwork_sdk_py/__init__.py
Adds eth-hash[pycryptodome]>=0.5.0 dependency. Defines TypedDict types for rule/instance/event results and re-exports utility functions (compute_rules_hash, derive_rule_id, derive_maa_address) for public API access.

Sequence Diagram

sequenceDiagram
  participant App
  participant TNClient
  participant Utils
  participant GoBindings
  participant OnChainProcedure
  
  App->>TNClient: maa_create_rule(fee_mode, namespaces, ...)
  TNClient->>Utils: compute_rules_hash(...)
  Utils-->>TNClient: rules_hash
  TNClient->>Utils: derive_rule_id(restricted, rules_hash, salt)
  Utils-->>TNClient: rule_id
  TNClient->>GoBindings: MAACreateRule(rule_id, ...)
  GoBindings->>OnChainProcedure: call maa_create_rule
  OnChainProcedure-->>GoBindings: tx_hash
  GoBindings-->>TNClient: tx_hash
  TNClient-->>App: MAACreateRuleResult { tx_hash, rule_id }
  
  App->>TNClient: join_agent_address(rule_id)
  TNClient->>Utils: derive_maa_address(unrestricted, restricted, rule_id)
  Utils-->>TNClient: maa_address
  TNClient->>GoBindings: MAAJoin(rule_id)
  GoBindings->>OnChainProcedure: call maa_join
  OnChainProcedure-->>GoBindings: tx_hash
  GoBindings-->>TNClient: tx_hash
  TNClient-->>App: MAAJoinResult { tx_hash, maa_address }
Loading

🎯 3 (Moderate) | ⏱️ ~25 minutes

🐰 A wallet for agents, deterministic and true,
Hashed rules and addresses, derived right through,
Off-chain and on-chain in harmony blend,
Migration forty-eight, the feature we send! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 78.05% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: derive, register, and read agent wallets' accurately and concisely summarizes the main changes: adding MAA support for derivation (utils.py), registration (client.py), and read operations (client.py + bindings).
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/maa-agent-wallets

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
src/trufnetwork_sdk_py/utils.py (1)

103-103: 💤 Low value

Consider adding strict=True to zip() for defensive consistency.

The length validation on line 78 already guarantees equal-length lists, so this is not a bug. However, adding strict=True provides an explicit contract and catches any future refactoring that might bypass the validation.

♻️ Suggested change
-    for ns, act, bh in zip(ns_list, act_list, bh_list):
+    for ns, act, bh in zip(ns_list, act_list, bh_list, strict=True):
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/trufnetwork_sdk_py/utils.py` at line 103, The loop using zip over
ns_list, act_list, bh_list should be made defensive by enabling strict mode:
update the zip call inside the function containing the line "for ns, act, bh in
zip(ns_list, act_list, bh_list)" to use zip(..., strict=True) so any future
length mismatch raises immediately; locate the loop in utils.py (the function
that iterates ns_list/act_list/bh_list) and add the strict=True argument to the
zip invocation.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@bindings/maa.go`:
- Around line 44-45: MAACreateRule currently strips only the lowercase "0x"
prefix before hex.DecodeString which causes uppercase "0X"-prefixed hashes to
fail; update MAACreateRule to normalize both prefix variants by removing either
"0x" or "0X" (e.g., test HasPrefix for both and strip the first two chars or
call TrimPrefix for both variants) before calling hex.DecodeString so the
decoded, derr := hex.DecodeString(...) call succeeds for uppercase-prefixed
inputs.

In `@src/trufnetwork_sdk_py/client.py`:
- Around line 3658-3663: The _maa_rows function currently uses zip(cols, row)
which silently truncates when a row's length doesn't match cols; update
_maa_rows to validate shapes first: after parsing cols and vals, iterate rows
and for each row check len(row) == len(cols) and if not raise a clear ValueError
(or custom exception) including the function name, row index, expected column
count, actual row length and the offending row content, otherwise build the dict
with dict(zip(cols, row)); this ensures mismatched row/column shapes fail fast
instead of producing corrupted dicts.

---

Nitpick comments:
In `@src/trufnetwork_sdk_py/utils.py`:
- Line 103: The loop using zip over ns_list, act_list, bh_list should be made
defensive by enabling strict mode: update the zip call inside the function
containing the line "for ns, act, bh in zip(ns_list, act_list, bh_list)" to use
zip(..., strict=True) so any future length mismatch raises immediately; locate
the loop in utils.py (the function that iterates ns_list/act_list/bh_list) and
add the strict=True argument to the zip invocation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 74537601-cc4b-4339-bc23-e1137068e96b

📥 Commits

Reviewing files that changed from the base of the PR and between f41e6d5 and 9ccafe0.

⛔ Files ignored due to path filters (1)
  • go.sum is excluded by !**/*.sum
📒 Files selected for processing (6)
  • bindings/maa.go
  • pyproject.toml
  • src/trufnetwork_sdk_py/__init__.py
  • src/trufnetwork_sdk_py/client.py
  • src/trufnetwork_sdk_py/utils.py
  • tests/test_maa.py

Comment thread bindings/maa.go Outdated
Comment thread src/trufnetwork_sdk_py/client.py Outdated
@holdex

holdex Bot commented Jun 10, 2026

Copy link
Copy Markdown

Time Submission Status

Member # Time Running Total Status Last Update
MicBun 4h ✅ Submitted Jun 10, 2026, 5:26 AM

Submit or update total time with:

@holdex pr submit-time 2h

Add time on top of previous submission with:

@holdex pr add-time 1h30m

See available commands to help comply with our Guidelines.

@MicBun MicBun self-assigned this Jun 10, 2026
@MicBun

MicBun commented Jun 10, 2026

Copy link
Copy Markdown
Contributor Author

@holdex pr submit-time 4h

@MicBun MicBun merged commit 53aec08 into main Jun 10, 2026
6 checks passed
@MicBun MicBun deleted the feat/maa-agent-wallets branch June 10, 2026 06:05
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant