Skip to content
Merged
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
46 changes: 32 additions & 14 deletions bindings/maa.go
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,19 @@ import (
// declares. The Python side emits this shape; see trufnetwork_sdk_py.client.MAANumericArg.
const maaTypeKey = "__tn_type__"

// MAACreateRule submits maa_create_rule (the caller becomes the restricted agent) and returns the tx
// hash. bodyHashesHex is parallel to namespaces/actions; an empty element is an unpinned (NULL) entry.
// maaWriteResult JSON-encodes a write's tx hash together with the address/id the underlying Go SDK
// derives for it, matching the {tx_hash, <key>} shape the Python client reads back.
func maaWriteResult(txHash, key string, raw []byte) (string, error) {
out, err := json.Marshal(map[string]string{"tx_hash": txHash, key: "0x" + hex.EncodeToString(raw)})
if err != nil {
return "", errors.Wrap(err, "marshal maa write result")
}
return string(out), nil
}

// MAACreateRule registers an agent-wallet rule (the caller becomes the restricted agent) by delegating
// to the Go SDK's CreateAgentRule, and returns JSON {tx_hash, rule_id} (rule_id 0x-hex, derived by the
// Go SDK). bodyHashesHex is parallel to namespaces/actions; an empty element is an unpinned (NULL) entry.
func MAACreateRule(
client *tnclient.Client,
salt []byte,
Expand All @@ -39,12 +50,6 @@ func MAACreateRule(
actions []string,
bodyHashesHex []string,
) (string, error) {
ctx := context.Background()
act, err := client.LoadActions()
if err != nil {
return "", errors.Wrap(err, "load actions")
}

bodyHashes := make([][]byte, len(bodyHashesHex))
for i, h := range bodyHashesHex {
if h == "" {
Expand All @@ -59,27 +64,40 @@ func MAACreateRule(
bodyHashes[i] = decoded
}

txHash, err := act.ExecuteProcedure(ctx, "maa_create_rule", [][]any{
{salt, feeMode, feeBps, feeFlat, namespaces, actions, bodyHashes},
ctx := context.Background()
act, err := client.LoadActions()
if err != nil {
return "", errors.Wrap(err, "load actions")
}
ruleID, txHash, err := act.CreateAgentRule(ctx, types.MAACreateRuleInput{
Salt: salt,
FeeMode: feeMode,
FeeBps: feeBps,
FeeFlat: feeFlat,
Namespaces: namespaces,
Actions: actions,
BodyHashes: bodyHashes,
})
if err != nil {
return "", errors.Wrap(err, "maa_create_rule")
}
return txHash.String(), nil
return maaWriteResult(txHash, "rule_id", ruleID)
}

// MAAJoin submits maa_join (the caller becomes the unrestricted owner/funder) and returns the tx hash.
// MAAJoin joins an existing rule as the unrestricted owner/funder by delegating to the Go SDK's
// JoinAgentAddress (which resolves the rule and derives the wallet), and returns JSON
// {tx_hash, maa_address} (maa_address 0x-hex).
func MAAJoin(client *tnclient.Client, ruleID []byte) (string, error) {
ctx := context.Background()
act, err := client.LoadActions()
if err != nil {
return "", errors.Wrap(err, "load actions")
}
txHash, err := act.ExecuteProcedure(ctx, "maa_join", [][]any{{ruleID}})
maaAddress, txHash, err := act.JoinAgentAddress(ctx, ruleID)
if err != nil {
return "", errors.Wrap(err, "maa_join")
}
return txHash.String(), nil
return maaWriteResult(txHash, "maa_address", maaAddress)
}

// MAAExec submits a maa_exec transaction: run one allow-listed inner action AS the agent wallet. The
Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ require (
github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9
github.com/pkg/errors v0.9.1
github.com/trufnetwork/kwil-db/core v0.4.3-0.20260615121733-0d71bd259558
github.com/trufnetwork/sdk-go v0.7.3-0.20260615130252-00f0a043ec8d
github.com/trufnetwork/sdk-go v0.7.3-0.20260622120135-f266b733466c
google.golang.org/genproto v0.0.0-20251111163417-95abcf5c77ba
)

Expand Down
4 changes: 2 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -60,8 +60,8 @@ github.com/trufnetwork/kwil-db v0.10.3-0.20260615121733-0d71bd259558 h1:I49YGUiU
github.com/trufnetwork/kwil-db v0.10.3-0.20260615121733-0d71bd259558/go.mod h1:LiBAC48uZl2B0IiLtD2hpOce7RNfpuDdghVAOc3u1Qo=
github.com/trufnetwork/kwil-db/core v0.4.3-0.20260615121733-0d71bd259558 h1:m7a9HITFMXJF22QznIKoAdeiH8eZxWPU8IRzgcyNMo8=
github.com/trufnetwork/kwil-db/core v0.4.3-0.20260615121733-0d71bd259558/go.mod h1:HnOsh9+BN13LJCjiH0+XKaJzyjWKf+H9AofFFp90KwQ=
github.com/trufnetwork/sdk-go v0.7.3-0.20260615130252-00f0a043ec8d h1:Qd4vNPoprahvfp+UNNGtgaXUlHwFrgxsWBhMqGQs0Bc=
github.com/trufnetwork/sdk-go v0.7.3-0.20260615130252-00f0a043ec8d/go.mod h1:CivlBpc5RcYwyo8EysoAZWXXfmTtigfkR5VctivwSHc=
github.com/trufnetwork/sdk-go v0.7.3-0.20260622120135-f266b733466c h1:CfoiZyqRH8VCLSQPrm77ntxgQgOfi/b99nGIukQR2eI=
github.com/trufnetwork/sdk-go v0.7.3-0.20260622120135-f266b733466c/go.mod h1:CivlBpc5RcYwyo8EysoAZWXXfmTtigfkR5VctivwSHc=
go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto=
go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
Expand Down
50 changes: 20 additions & 30 deletions src/trufnetwork_sdk_py/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,6 @@

from pydantic import BaseModel

from .utils import compute_rules_hash, derive_maa_address, derive_rule_id

T = TypeVar("T")

Expand Down Expand Up @@ -3495,8 +3494,8 @@ def maa_create_rule(
) -> MAACreateRuleResult:
"""
Register an agent-wallet rule. The caller (signer) becomes the restricted agent. Returns the
locally-derived rule_id (the handle a funder passes to join_agent_address) and the tx hash. The
rule is immutable once created; no funds move here.
rule_id (the handle a funder passes to join_agent_address; derived by the underlying Go SDK) and
the tx hash. The rule is immutable once created; no funds move here.

body_hashes is parallel to namespaces/actions; each element may be bytes, a 0x-hex string, or
None (unpinned). salt may be bytes, a 0x-hex string, or None.
Expand All @@ -3511,44 +3510,35 @@ def maa_create_rule(
salt_bytes = self._maa_to_bytes(salt)
fee_flat_str = str(fee_flat) if fee_flat is not None else "0"

# Derive the rule_id locally (caller = the restricted agent) so it is known before the tx lands.
restricted = self._maa_to_bytes(truf_sdk.GetCurrentAccount(self.client))
rules_hash = compute_rules_hash(fee_mode, int(fee_bps), fee_flat_str, ns, acts, body_hashes_hex)
rule_id = derive_rule_id(restricted, rules_hash, salt_bytes)

tx_hash = truf_sdk.MAACreateRule(
self.client,
go.Slice_byte(list(salt_bytes)),
fee_mode,
int(fee_bps),
fee_flat_str,
go.Slice_string(ns),
go.Slice_string(acts),
go.Slice_string(body_hashes_hex),
result = json.loads(
truf_sdk.MAACreateRule(
self.client,
go.Slice_byte(list(salt_bytes)),
fee_mode,
int(fee_bps),
fee_flat_str,
go.Slice_string(ns),
go.Slice_string(acts),
go.Slice_string(body_hashes_hex),
)
)
if wait:
self.wait_for_tx(tx_hash)
return {"tx_hash": tx_hash, "rule_id": "0x" + rule_id.hex()}
self.wait_for_tx(result["tx_hash"])
return {"tx_hash": result["tx_hash"], "rule_id": result["rule_id"]}

def join_agent_address(self, rule_id: bytes | str, wait: bool = True) -> MAAJoinResult:
"""
Join an existing rule as the unrestricted owner/funder. The caller (signer) becomes the owner.
Returns the locally-derived MAA address (the wallet to fund) and the tx hash. The rule's
restricted creator is looked up on-chain to derive the address.
Returns the MAA address (the wallet to fund; derived by the underlying Go SDK, which looks up
the rule's restricted creator on-chain) and the tx hash.
"""
rid = self._maa_to_bytes(rule_id)
if len(rid) != 32:
raise ValueError(f"rule_id must be 32 bytes, got {len(rid)}")
rule = self.maa_get_rule(rid)
if rule is None:
raise ValueError("unknown rule_id")
unrestricted = self._maa_to_bytes(truf_sdk.GetCurrentAccount(self.client))
maa_address = derive_maa_address(unrestricted, rule["restricted_addr"], rid)

tx_hash = truf_sdk.MAAJoin(self.client, go.Slice_byte(list(rid)))
result = json.loads(truf_sdk.MAAJoin(self.client, go.Slice_byte(list(rid))))
if wait:
self.wait_for_tx(tx_hash)
return {"tx_hash": tx_hash, "maa_address": "0x" + maa_address.hex()}
self.wait_for_tx(result["tx_hash"])
return {"tx_hash": result["tx_hash"], "maa_address": result["maa_address"]}

def execute_agent_action(
self,
Expand Down
Loading