agent0-sdk 1.2.0__py3-none-any.whl → 1.4.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- agent0_sdk/__init__.py +6 -1
- agent0_sdk/core/agent.py +232 -180
- agent0_sdk/core/contracts.py +13 -7
- agent0_sdk/core/feedback_manager.py +98 -55
- agent0_sdk/core/indexer.py +73 -19
- agent0_sdk/core/models.py +4 -3
- agent0_sdk/core/sdk.py +42 -14
- agent0_sdk/core/subgraph_client.py +9 -3
- agent0_sdk/core/transaction_handle.py +71 -0
- agent0_sdk/core/value_encoding.py +3 -3
- agent0_sdk/core/web3_client.py +44 -4
- {agent0_sdk-1.2.0.dist-info → agent0_sdk-1.4.1.dist-info}/METADATA +26 -10
- agent0_sdk-1.4.1.dist-info/RECORD +21 -0
- {agent0_sdk-1.2.0.dist-info → agent0_sdk-1.4.1.dist-info}/WHEEL +1 -1
- agent0_sdk-1.2.0.dist-info/RECORD +0 -20
- {agent0_sdk-1.2.0.dist-info → agent0_sdk-1.4.1.dist-info}/licenses/LICENSE +0 -0
- {agent0_sdk-1.2.0.dist-info → agent0_sdk-1.4.1.dist-info}/top_level.txt +0 -0
agent0_sdk/__init__.py
CHANGED
|
@@ -24,16 +24,21 @@ from .core.models import (
|
|
|
24
24
|
try:
|
|
25
25
|
from .core.sdk import SDK
|
|
26
26
|
from .core.agent import Agent
|
|
27
|
+
from .core.transaction_handle import TransactionHandle, TransactionMined
|
|
27
28
|
_sdk_available = True
|
|
28
29
|
except ImportError:
|
|
29
30
|
SDK = None
|
|
30
31
|
Agent = None
|
|
32
|
+
TransactionHandle = None
|
|
33
|
+
TransactionMined = None
|
|
31
34
|
_sdk_available = False
|
|
32
35
|
|
|
33
|
-
__version__ = "1.
|
|
36
|
+
__version__ = "1.4.1"
|
|
34
37
|
__all__ = [
|
|
35
38
|
"SDK",
|
|
36
39
|
"Agent",
|
|
40
|
+
"TransactionHandle",
|
|
41
|
+
"TransactionMined",
|
|
37
42
|
"AgentId",
|
|
38
43
|
"ChainId",
|
|
39
44
|
"Address",
|
agent0_sdk/core/agent.py
CHANGED
|
@@ -23,6 +23,8 @@ if TYPE_CHECKING:
|
|
|
23
23
|
|
|
24
24
|
logger = logging.getLogger(__name__)
|
|
25
25
|
|
|
26
|
+
from .transaction_handle import TransactionHandle
|
|
27
|
+
|
|
26
28
|
|
|
27
29
|
class Agent:
|
|
28
30
|
"""Represents an individual agent with its registration data."""
|
|
@@ -79,6 +81,27 @@ class Agent:
|
|
|
79
81
|
"""Get agent wallet address (read-only)."""
|
|
80
82
|
return self.registration_file.walletAddress
|
|
81
83
|
|
|
84
|
+
def getWallet(self) -> Optional[Address]:
|
|
85
|
+
"""Read the verified agent wallet from the Identity Registry (on-chain).
|
|
86
|
+
|
|
87
|
+
This calls the contract function `getAgentWallet(agentId)` and returns:
|
|
88
|
+
- the wallet address if set and non-zero
|
|
89
|
+
- None if unset/cleared (zero address)
|
|
90
|
+
"""
|
|
91
|
+
if not self.agentId:
|
|
92
|
+
raise ValueError("Agent must be registered before reading wallet from chain.")
|
|
93
|
+
|
|
94
|
+
agent_id_int = int(self.agentId.split(":")[-1]) if ":" in self.agentId else int(self.agentId)
|
|
95
|
+
wallet = self.sdk.web3_client.call_contract(self.sdk.identity_registry, "getAgentWallet", agent_id_int)
|
|
96
|
+
|
|
97
|
+
if not wallet or not isinstance(wallet, str):
|
|
98
|
+
return None
|
|
99
|
+
|
|
100
|
+
if wallet.lower() == "0x0000000000000000000000000000000000000000":
|
|
101
|
+
return None
|
|
102
|
+
|
|
103
|
+
return wallet
|
|
104
|
+
|
|
82
105
|
@property
|
|
83
106
|
def walletChainId(self) -> Optional[int]:
|
|
84
107
|
"""Get agent wallet chain ID (read-only)."""
|
|
@@ -179,11 +202,11 @@ class Agent:
|
|
|
179
202
|
"""Collect all metadata entries for registration.
|
|
180
203
|
|
|
181
204
|
Note: agentWallet is now a reserved metadata key and cannot be set via setMetadata().
|
|
182
|
-
It must be set separately using
|
|
205
|
+
It must be set separately using setWallet() with signature verification.
|
|
183
206
|
"""
|
|
184
207
|
metadata_entries = []
|
|
185
208
|
|
|
186
|
-
# Note: agentWallet is no longer set via metadata - it's now reserved and managed via
|
|
209
|
+
# Note: agentWallet is no longer set via metadata - it's now reserved and managed via setWallet()
|
|
187
210
|
|
|
188
211
|
# Add ENS name metadata
|
|
189
212
|
if self.ensEndpoint:
|
|
@@ -491,7 +514,7 @@ class Agent:
|
|
|
491
514
|
self.registration_file.updatedAt = int(time.time())
|
|
492
515
|
return self
|
|
493
516
|
|
|
494
|
-
def
|
|
517
|
+
def setWallet(
|
|
495
518
|
self,
|
|
496
519
|
new_wallet: Address,
|
|
497
520
|
chainId: Optional[int] = None,
|
|
@@ -499,11 +522,10 @@ class Agent:
|
|
|
499
522
|
new_wallet_signer: Optional[Union[str, Any]] = None,
|
|
500
523
|
deadline: Optional[int] = None,
|
|
501
524
|
signature: Optional[bytes] = None,
|
|
502
|
-
) ->
|
|
503
|
-
"""Set agent wallet address on-chain (
|
|
525
|
+
) -> Optional[TransactionHandle["Agent"]]:
|
|
526
|
+
"""Set agent wallet address on-chain (verified agentWallet).
|
|
504
527
|
|
|
505
|
-
This method is **on-chain only**. The `agentWallet` is a verified attribute
|
|
506
|
-
the IdentityRegistry `setAgentWallet` function.
|
|
528
|
+
This method is **on-chain only**. The `agentWallet` is a verified attribute.
|
|
507
529
|
|
|
508
530
|
EOAs: provide `new_wallet_signer` (private key string or eth-account account) OR ensure the SDK
|
|
509
531
|
signer address matches `new_wallet` so the SDK can auto-sign.\n
|
|
@@ -517,7 +539,7 @@ class Agent:
|
|
|
517
539
|
deadline: Signature deadline timestamp. Defaults to now+60s (must be <= now+5min per contract).
|
|
518
540
|
signature: Raw signature bytes (intended for ERC-1271 / external signing only)
|
|
519
541
|
"""
|
|
520
|
-
#
|
|
542
|
+
# This API is only meaningful for already-registered agents.
|
|
521
543
|
if not self.agentId:
|
|
522
544
|
raise ValueError(
|
|
523
545
|
"Cannot set agent wallet before the agent is registered on-chain. "
|
|
@@ -555,18 +577,14 @@ class Agent:
|
|
|
555
577
|
|
|
556
578
|
# Check if wallet is already set to this address (skip if same)
|
|
557
579
|
try:
|
|
558
|
-
current_wallet = self.
|
|
559
|
-
self.sdk.identity_registry,
|
|
560
|
-
"getAgentWallet",
|
|
561
|
-
agent_id_int
|
|
562
|
-
)
|
|
580
|
+
current_wallet = self.getWallet()
|
|
563
581
|
if current_wallet and current_wallet.lower() == addr.lower():
|
|
564
582
|
logger.debug(f"Agent wallet is already set to {addr}, skipping on-chain update")
|
|
565
583
|
# Still update local registration file
|
|
566
584
|
self.registration_file.walletAddress = addr
|
|
567
585
|
self.registration_file.walletChainId = chainId
|
|
568
586
|
self.registration_file.updatedAt = int(time.time())
|
|
569
|
-
return
|
|
587
|
+
return None
|
|
570
588
|
except Exception as e:
|
|
571
589
|
logger.debug(f"Could not check current agent wallet: {e}, proceeding with update")
|
|
572
590
|
|
|
@@ -625,7 +643,7 @@ class Agent:
|
|
|
625
643
|
if recovered.lower() != addr.lower():
|
|
626
644
|
raise ValueError(f"Signature verification failed: recovered {recovered} but expected {addr}")
|
|
627
645
|
|
|
628
|
-
#
|
|
646
|
+
# Submit on-chain tx (tx sender is SDK signer: owner/operator)
|
|
629
647
|
try:
|
|
630
648
|
txHash = self.sdk.web3_client.transact_contract(
|
|
631
649
|
self.sdk.identity_registry,
|
|
@@ -635,21 +653,61 @@ class Agent:
|
|
|
635
653
|
deadline,
|
|
636
654
|
signature
|
|
637
655
|
)
|
|
638
|
-
|
|
639
|
-
# Wait for transaction
|
|
640
|
-
receipt = self.sdk.web3_client.wait_for_transaction(txHash)
|
|
641
|
-
logger.debug(f"Agent wallet set on-chain: {txHash}")
|
|
642
|
-
|
|
643
656
|
except Exception as e:
|
|
644
657
|
raise ValueError(f"Failed to set agent wallet on-chain: {e}")
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
648
|
-
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
|
|
658
|
+
|
|
659
|
+
def _apply(_receipt: Dict[str, Any]) -> "Agent":
|
|
660
|
+
self.registration_file.walletAddress = addr
|
|
661
|
+
self.registration_file.walletChainId = chainId
|
|
662
|
+
self.registration_file.updatedAt = int(time.time())
|
|
663
|
+
self._last_registered_wallet = addr
|
|
664
|
+
return self
|
|
665
|
+
|
|
666
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
667
|
+
|
|
668
|
+
def unsetWallet(self) -> Optional[TransactionHandle["Agent"]]:
|
|
669
|
+
"""Unset agent wallet address on-chain (verified agentWallet).
|
|
670
|
+
|
|
671
|
+
This method is **on-chain only** and requires the agent to be registered.
|
|
672
|
+
It unsets the on-chain value and clears the local
|
|
673
|
+
`walletAddress` / `walletChainId` fields.
|
|
674
|
+
"""
|
|
675
|
+
if not self.agentId:
|
|
676
|
+
raise ValueError(
|
|
677
|
+
"Cannot unset agent wallet before the agent is registered on-chain. "
|
|
678
|
+
"Call agent.register(...) / agent.registerIPFS() first to obtain agentId."
|
|
679
|
+
)
|
|
680
|
+
|
|
681
|
+
# Parse agent ID (tokenId is always the last segment)
|
|
682
|
+
agent_id_int = int(self.agentId.split(":")[-1]) if ":" in self.agentId else int(self.agentId)
|
|
683
|
+
|
|
684
|
+
# Optional short-circuit if already unset (best-effort).
|
|
685
|
+
try:
|
|
686
|
+
current_wallet = self.getWallet()
|
|
687
|
+
if current_wallet is None:
|
|
688
|
+
self.registration_file.walletAddress = None
|
|
689
|
+
self.registration_file.walletChainId = None
|
|
690
|
+
self.registration_file.updatedAt = int(time.time())
|
|
691
|
+
return None
|
|
692
|
+
except Exception:
|
|
693
|
+
pass
|
|
694
|
+
|
|
695
|
+
try:
|
|
696
|
+
txHash = self.sdk.web3_client.transact_contract(
|
|
697
|
+
self.sdk.identity_registry,
|
|
698
|
+
"unsetAgentWallet",
|
|
699
|
+
agent_id_int
|
|
700
|
+
)
|
|
701
|
+
except Exception as e:
|
|
702
|
+
raise ValueError(f"Failed to unset agent wallet on-chain: {e}")
|
|
703
|
+
|
|
704
|
+
def _apply(_receipt: Dict[str, Any]) -> "Agent":
|
|
705
|
+
self.registration_file.walletAddress = None
|
|
706
|
+
self.registration_file.walletChainId = None
|
|
707
|
+
self.registration_file.updatedAt = int(time.time())
|
|
708
|
+
return self
|
|
709
|
+
|
|
710
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
653
711
|
|
|
654
712
|
def setENS(self, name: str, version: str = "1.0") -> 'Agent':
|
|
655
713
|
"""Set ENS name both on-chain and in registration file."""
|
|
@@ -716,121 +774,112 @@ class Agent:
|
|
|
716
774
|
return self.registration_file
|
|
717
775
|
|
|
718
776
|
# Registration (on-chain)
|
|
719
|
-
def registerIPFS(self) -> RegistrationFile:
|
|
720
|
-
"""Register agent on-chain with IPFS flow (mint -> pin -> set URI) or update existing registration.
|
|
777
|
+
def registerIPFS(self) -> TransactionHandle[RegistrationFile]:
|
|
778
|
+
"""Register agent on-chain with IPFS flow (mint -> pin -> set URI) or update existing registration.
|
|
779
|
+
|
|
780
|
+
Submitted-by-default: returns a TransactionHandle immediately after the first tx is submitted.
|
|
781
|
+
"""
|
|
721
782
|
# Validate basic info
|
|
722
783
|
if not self.registration_file.name or not self.registration_file.description:
|
|
723
784
|
raise ValueError("Agent must have name and description before registration")
|
|
724
785
|
|
|
725
786
|
if self.registration_file.agentId:
|
|
726
|
-
# Agent already registered
|
|
727
|
-
logger.debug("Agent already registered, updating registration file")
|
|
728
|
-
|
|
729
|
-
# Upload updated registration file to IPFS
|
|
787
|
+
# Agent already registered: upload -> submit setAgentURI; do metadata best-effort after confirmation.
|
|
730
788
|
ipfsCid = self.sdk.ipfs_client.addRegistrationFile(
|
|
731
789
|
self.registration_file,
|
|
732
790
|
chainId=self.sdk.chain_id(),
|
|
733
|
-
identityRegistryAddress=self.sdk.identity_registry.address
|
|
791
|
+
identityRegistryAddress=self.sdk.identity_registry.address,
|
|
734
792
|
)
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
# Only send transactions for dirty (changed) metadata to save gas
|
|
738
|
-
if self._dirty_metadata:
|
|
739
|
-
metadata_entries = self._collectMetadataForRegistration()
|
|
740
|
-
agentId = int(self.agentId.split(":")[-1])
|
|
741
|
-
for entry in metadata_entries:
|
|
742
|
-
# Only send transaction if this metadata key is dirty
|
|
743
|
-
if entry["key"] in self._dirty_metadata:
|
|
744
|
-
txHash = self.sdk.web3_client.transact_contract(
|
|
745
|
-
self.sdk.identity_registry,
|
|
746
|
-
"setMetadata",
|
|
747
|
-
agentId,
|
|
748
|
-
entry["key"],
|
|
749
|
-
entry["value"]
|
|
750
|
-
)
|
|
751
|
-
try:
|
|
752
|
-
self.sdk.web3_client.wait_for_transaction(txHash, timeout=30)
|
|
753
|
-
except Exception as e:
|
|
754
|
-
logger.warning(f"Transaction timeout for {entry['key']}: {e}")
|
|
755
|
-
logger.debug(f"Updated metadata on-chain: {entry['key']}")
|
|
756
|
-
else:
|
|
757
|
-
logger.debug("No metadata changes detected, skipping metadata updates")
|
|
758
|
-
|
|
759
|
-
# Update agent URI on-chain
|
|
760
|
-
agentId = int(self.agentId.split(":")[-1])
|
|
793
|
+
|
|
794
|
+
agentId_int = int(self.agentId.split(":")[-1])
|
|
761
795
|
txHash = self.sdk.web3_client.transact_contract(
|
|
762
796
|
self.sdk.identity_registry,
|
|
763
797
|
"setAgentURI",
|
|
764
|
-
|
|
765
|
-
f"ipfs://{ipfsCid}"
|
|
798
|
+
agentId_int,
|
|
799
|
+
f"ipfs://{ipfsCid}",
|
|
766
800
|
)
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
|
|
776
|
-
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
|
|
780
|
-
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
|
|
784
|
-
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
801
|
+
|
|
802
|
+
def _apply(_receipt: Dict[str, Any]) -> RegistrationFile:
|
|
803
|
+
# Best-effort metadata updates (may involve additional txs)
|
|
804
|
+
if self._dirty_metadata:
|
|
805
|
+
metadata_entries = self._collectMetadataForRegistration()
|
|
806
|
+
for entry in metadata_entries:
|
|
807
|
+
if entry["key"] in self._dirty_metadata:
|
|
808
|
+
try:
|
|
809
|
+
h = self.sdk.web3_client.transact_contract(
|
|
810
|
+
self.sdk.identity_registry,
|
|
811
|
+
"setMetadata",
|
|
812
|
+
agentId_int,
|
|
813
|
+
entry["key"],
|
|
814
|
+
entry["value"],
|
|
815
|
+
)
|
|
816
|
+
self.sdk.web3_client.wait_for_transaction(h, timeout=30)
|
|
817
|
+
except Exception as e:
|
|
818
|
+
logger.warning(f"Metadata update failed or timed out for {entry['key']} (tx sent): {e}")
|
|
819
|
+
|
|
820
|
+
self.registration_file.agentURI = f"ipfs://{ipfsCid}"
|
|
821
|
+
self.registration_file.updatedAt = int(time.time())
|
|
822
|
+
self._last_registered_wallet = self.walletAddress
|
|
823
|
+
self._last_registered_ens = self.ensEndpoint
|
|
824
|
+
self._dirty_metadata.clear()
|
|
825
|
+
return self.registration_file
|
|
826
|
+
|
|
827
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
828
|
+
|
|
829
|
+
# First time registration: tx1=register(no URI) -> wait -> upload -> tx2=setAgentURI -> wait
|
|
830
|
+
metadata_entries = self._collectMetadataForRegistration()
|
|
831
|
+
txHash = self.sdk.web3_client.transact_contract(
|
|
832
|
+
self.sdk.identity_registry,
|
|
833
|
+
"register",
|
|
834
|
+
"",
|
|
835
|
+
metadata_entries,
|
|
836
|
+
)
|
|
837
|
+
|
|
838
|
+
def _apply_first(receipt: Dict[str, Any]) -> RegistrationFile:
|
|
839
|
+
agentId_minted = self._extractAgentIdFromReceipt(receipt)
|
|
840
|
+
self.registration_file.agentId = f"{self.sdk.chain_id()}:{agentId_minted}"
|
|
841
|
+
self.registration_file.updatedAt = int(time.time())
|
|
842
|
+
|
|
790
843
|
ipfsCid = self.sdk.ipfs_client.addRegistrationFile(
|
|
791
844
|
self.registration_file,
|
|
792
845
|
chainId=self.sdk.chain_id(),
|
|
793
|
-
identityRegistryAddress=self.sdk.identity_registry.address
|
|
846
|
+
identityRegistryAddress=self.sdk.identity_registry.address,
|
|
794
847
|
)
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
agentId = int(self.agentId.split(":")[-1])
|
|
798
|
-
txHash = self.sdk.web3_client.transact_contract(
|
|
848
|
+
|
|
849
|
+
txHash2 = self.sdk.web3_client.transact_contract(
|
|
799
850
|
self.sdk.identity_registry,
|
|
800
851
|
"setAgentURI",
|
|
801
|
-
|
|
802
|
-
f"ipfs://{ipfsCid}"
|
|
852
|
+
agentId_minted,
|
|
853
|
+
f"ipfs://{ipfsCid}",
|
|
803
854
|
)
|
|
804
|
-
|
|
805
|
-
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
logger.warning(f"URI set timeout (transaction sent: {txHash}): {e}")
|
|
809
|
-
|
|
810
|
-
# Clear dirty flags after successful registration
|
|
855
|
+
self.sdk.web3_client.wait_for_transaction(txHash2, timeout=30)
|
|
856
|
+
|
|
857
|
+
self.registration_file.agentURI = f"ipfs://{ipfsCid}"
|
|
858
|
+
self.registration_file.updatedAt = int(time.time())
|
|
811
859
|
self._last_registered_wallet = self.walletAddress
|
|
812
860
|
self._last_registered_ens = self.ensEndpoint
|
|
813
861
|
self._dirty_metadata.clear()
|
|
814
|
-
|
|
815
862
|
return self.registration_file
|
|
816
863
|
|
|
817
|
-
|
|
818
|
-
|
|
864
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply_first)
|
|
865
|
+
|
|
866
|
+
def register(self, agentUri: str) -> TransactionHandle[RegistrationFile]:
|
|
867
|
+
"""Register agent on-chain with direct URI (submitted-by-default)."""
|
|
819
868
|
# Validate basic info
|
|
820
869
|
if not self.registration_file.name or not self.registration_file.description:
|
|
821
870
|
raise ValueError("Agent must have name and description before registration")
|
|
822
871
|
|
|
823
872
|
if self.registration_file.agentId:
|
|
824
|
-
#
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
873
|
+
# Update URI on-chain for existing agent
|
|
874
|
+
updated = self.updateRegistration(agentURI=agentUri)
|
|
875
|
+
if isinstance(updated, TransactionHandle):
|
|
876
|
+
return updated
|
|
877
|
+
# Should not happen (agentURI was provided), but keep a safe fallback.
|
|
878
|
+
raise RuntimeError("Expected updateRegistration to return a TransactionHandle when agentURI is provided")
|
|
879
|
+
|
|
880
|
+
return self._registerWithUri(agentUri)
|
|
832
881
|
|
|
833
|
-
def _registerWithoutUri(self, idem: Optional[IdemKey] = None) -> RegistrationFile:
|
|
882
|
+
def _registerWithoutUri(self, idem: Optional[IdemKey] = None) -> TransactionHandle[RegistrationFile]:
|
|
834
883
|
"""Register without URI (IPFS flow step 1) with metadata."""
|
|
835
884
|
# Collect metadata for registration
|
|
836
885
|
metadata_entries = self._collectMetadataForRegistration()
|
|
@@ -843,19 +892,15 @@ class Agent:
|
|
|
843
892
|
metadata_entries
|
|
844
893
|
)
|
|
845
894
|
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
# Update registration file
|
|
853
|
-
self.registration_file.agentId = f"{self.sdk.chain_id()}:{agentId}"
|
|
854
|
-
self.registration_file.updatedAt = int(time.time())
|
|
855
|
-
|
|
856
|
-
return self.registration_file
|
|
895
|
+
def _apply(receipt: Dict[str, Any]) -> RegistrationFile:
|
|
896
|
+
agentId = self._extractAgentIdFromReceipt(receipt)
|
|
897
|
+
self.registration_file.agentId = f"{self.sdk.chain_id()}:{agentId}"
|
|
898
|
+
self.registration_file.updatedAt = int(time.time())
|
|
899
|
+
return self.registration_file
|
|
857
900
|
|
|
858
|
-
|
|
901
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
902
|
+
|
|
903
|
+
def _registerWithUri(self, agentURI: URI, idem: Optional[IdemKey] = None) -> TransactionHandle[RegistrationFile]:
|
|
859
904
|
"""Register with direct URI and metadata."""
|
|
860
905
|
# Update registration file
|
|
861
906
|
self.registration_file.agentURI = agentURI
|
|
@@ -872,17 +917,13 @@ class Agent:
|
|
|
872
917
|
metadata_entries
|
|
873
918
|
)
|
|
874
919
|
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
|
|
878
|
-
|
|
879
|
-
|
|
880
|
-
|
|
881
|
-
|
|
882
|
-
self.registration_file.agentId = f"{self.sdk.chain_id()}:{agentId}"
|
|
883
|
-
self.registration_file.updatedAt = int(time.time())
|
|
884
|
-
|
|
885
|
-
return self.registration_file
|
|
920
|
+
def _apply(receipt: Dict[str, Any]) -> RegistrationFile:
|
|
921
|
+
agentId = self._extractAgentIdFromReceipt(receipt)
|
|
922
|
+
self.registration_file.agentId = f"{self.sdk.chain_id()}:{agentId}"
|
|
923
|
+
self.registration_file.updatedAt = int(time.time())
|
|
924
|
+
return self.registration_file
|
|
925
|
+
|
|
926
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
886
927
|
|
|
887
928
|
def _extractAgentIdFromReceipt(self, receipt: Dict[str, Any]) -> int:
|
|
888
929
|
"""Extract agent ID from transaction receipt."""
|
|
@@ -927,7 +968,7 @@ class Agent:
|
|
|
927
968
|
self,
|
|
928
969
|
agentURI: Optional[URI] = None,
|
|
929
970
|
idem: Optional[IdemKey] = None,
|
|
930
|
-
) -> RegistrationFile:
|
|
971
|
+
) -> Union[RegistrationFile, TransactionHandle[RegistrationFile]]:
|
|
931
972
|
"""Update registration after edits."""
|
|
932
973
|
if not self.registration_file.agentId:
|
|
933
974
|
raise ValueError("Agent must be registered before updating")
|
|
@@ -941,15 +982,19 @@ class Agent:
|
|
|
941
982
|
|
|
942
983
|
# Update on-chain URI if needed
|
|
943
984
|
if agentURI is not None:
|
|
944
|
-
|
|
985
|
+
agentId_int = int(self.registration_file.agentId.split(":")[-1])
|
|
945
986
|
txHash = self.sdk.web3_client.transact_contract(
|
|
946
987
|
self.sdk.identity_registry,
|
|
947
988
|
"setAgentURI",
|
|
948
|
-
|
|
949
|
-
agentURI
|
|
989
|
+
agentId_int,
|
|
990
|
+
agentURI,
|
|
950
991
|
)
|
|
951
|
-
|
|
952
|
-
|
|
992
|
+
|
|
993
|
+
def _apply(_receipt: Dict[str, Any]) -> RegistrationFile:
|
|
994
|
+
return self.registration_file
|
|
995
|
+
|
|
996
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
997
|
+
|
|
953
998
|
return self.registration_file
|
|
954
999
|
|
|
955
1000
|
def setAgentUri(self, uri: str) -> 'Agent':
|
|
@@ -969,11 +1014,11 @@ class Agent:
|
|
|
969
1014
|
to: Address,
|
|
970
1015
|
approve_operator: bool = False,
|
|
971
1016
|
idem: Optional[IdemKey] = None,
|
|
972
|
-
) -> Dict[str, Any]:
|
|
1017
|
+
) -> TransactionHandle[Dict[str, Any]]:
|
|
973
1018
|
"""Transfer agent ownership.
|
|
974
1019
|
|
|
975
1020
|
Note: When an agent is transferred, the agentWallet is automatically reset
|
|
976
|
-
to the zero address on-chain. The new owner must call
|
|
1021
|
+
to the zero address on-chain. The new owner must call setWallet() to
|
|
977
1022
|
set a new wallet address with EIP-712 signature verification.
|
|
978
1023
|
"""
|
|
979
1024
|
if not self.registration_file.agentId:
|
|
@@ -989,22 +1034,22 @@ class Agent:
|
|
|
989
1034
|
to,
|
|
990
1035
|
agentId
|
|
991
1036
|
)
|
|
992
|
-
|
|
993
|
-
receipt = self.sdk.web3_client.wait_for_transaction(txHash)
|
|
994
|
-
|
|
995
|
-
# Note: agentWallet will be reset to zero address by the contract
|
|
996
|
-
# Update local state to reflect this
|
|
997
|
-
self.registration_file.walletAddress = None
|
|
998
|
-
self._last_registered_wallet = None
|
|
999
|
-
|
|
1000
|
-
return {
|
|
1001
|
-
"txHash": txHash,
|
|
1002
|
-
"agentId": self.registration_file.agentId,
|
|
1003
|
-
"from": self.sdk.web3_client.account.address,
|
|
1004
|
-
"to": to
|
|
1005
|
-
}
|
|
1006
1037
|
|
|
1007
|
-
|
|
1038
|
+
def _apply(_receipt: Dict[str, Any]) -> Dict[str, Any]:
|
|
1039
|
+
# Note: agentWallet will be reset to zero address by the contract
|
|
1040
|
+
self.registration_file.walletAddress = None
|
|
1041
|
+
self._last_registered_wallet = None
|
|
1042
|
+
self.registration_file.updatedAt = int(time.time())
|
|
1043
|
+
return {
|
|
1044
|
+
"txHash": txHash,
|
|
1045
|
+
"agentId": self.registration_file.agentId,
|
|
1046
|
+
"from": self.sdk.web3_client.account.address,
|
|
1047
|
+
"to": to,
|
|
1048
|
+
}
|
|
1049
|
+
|
|
1050
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
1051
|
+
|
|
1052
|
+
def addOperator(self, operator: Address, idem: Optional[IdemKey] = None) -> TransactionHandle[Dict[str, Any]]:
|
|
1008
1053
|
"""Add operator (setApprovalForAll)."""
|
|
1009
1054
|
if not self.registration_file.agentId:
|
|
1010
1055
|
raise ValueError("Agent must be registered before adding operators")
|
|
@@ -1015,12 +1060,14 @@ class Agent:
|
|
|
1015
1060
|
operator,
|
|
1016
1061
|
True
|
|
1017
1062
|
)
|
|
1018
|
-
|
|
1019
|
-
receipt = self.sdk.web3_client.wait_for_transaction(txHash)
|
|
1020
|
-
|
|
1021
|
-
return {"txHash": txHash, "operator": operator}
|
|
1022
1063
|
|
|
1023
|
-
|
|
1064
|
+
return TransactionHandle(
|
|
1065
|
+
web3_client=self.sdk.web3_client,
|
|
1066
|
+
tx_hash=txHash,
|
|
1067
|
+
compute_result=lambda _receipt: {"txHash": txHash, "operator": operator},
|
|
1068
|
+
)
|
|
1069
|
+
|
|
1070
|
+
def removeOperator(self, operator: Address, idem: Optional[IdemKey] = None) -> TransactionHandle[Dict[str, Any]]:
|
|
1024
1071
|
"""Remove operator."""
|
|
1025
1072
|
if not self.registration_file.agentId:
|
|
1026
1073
|
raise ValueError("Agent must be registered before removing operators")
|
|
@@ -1031,18 +1078,20 @@ class Agent:
|
|
|
1031
1078
|
operator,
|
|
1032
1079
|
False
|
|
1033
1080
|
)
|
|
1034
|
-
|
|
1035
|
-
receipt = self.sdk.web3_client.wait_for_transaction(txHash)
|
|
1036
|
-
|
|
1037
|
-
return {"txHash": txHash, "operator": operator}
|
|
1038
1081
|
|
|
1039
|
-
|
|
1082
|
+
return TransactionHandle(
|
|
1083
|
+
web3_client=self.sdk.web3_client,
|
|
1084
|
+
tx_hash=txHash,
|
|
1085
|
+
compute_result=lambda _receipt: {"txHash": txHash, "operator": operator},
|
|
1086
|
+
)
|
|
1087
|
+
|
|
1088
|
+
def transfer(self, newOwnerAddress: str) -> TransactionHandle[Dict[str, Any]]:
|
|
1040
1089
|
"""Transfer agent ownership to a new address.
|
|
1041
1090
|
|
|
1042
1091
|
Only the current owner can transfer the agent.
|
|
1043
1092
|
|
|
1044
1093
|
Note: When an agent is transferred, the agentWallet is automatically reset
|
|
1045
|
-
to the zero address on-chain. The new owner must call
|
|
1094
|
+
to the zero address on-chain. The new owner must call setWallet() to
|
|
1046
1095
|
set a new wallet address with EIP-712 signature verification.
|
|
1047
1096
|
|
|
1048
1097
|
Args:
|
|
@@ -1097,17 +1146,20 @@ class Agent:
|
|
|
1097
1146
|
checksum_address,
|
|
1098
1147
|
token_id
|
|
1099
1148
|
)
|
|
1100
|
-
|
|
1101
|
-
|
|
1102
|
-
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
|
|
1106
|
-
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
|
|
1149
|
+
|
|
1150
|
+
def _apply(_receipt: Dict[str, Any]) -> Dict[str, Any]:
|
|
1151
|
+
logger.debug(f"Agent {self.registration_file.agentId} successfully transferred to {checksum_address}")
|
|
1152
|
+
self.registration_file.walletAddress = None
|
|
1153
|
+
self._last_registered_wallet = None
|
|
1154
|
+
self.registration_file.updatedAt = int(time.time())
|
|
1155
|
+
return {
|
|
1156
|
+
"txHash": txHash,
|
|
1157
|
+
"from": currentOwner,
|
|
1158
|
+
"to": checksum_address,
|
|
1159
|
+
"agentId": self.registration_file.agentId,
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
return TransactionHandle(web3_client=self.sdk.web3_client, tx_hash=txHash, compute_result=_apply)
|
|
1111
1163
|
|
|
1112
1164
|
def activate(self, idem: Optional[IdemKey] = None) -> RegistrationFile:
|
|
1113
1165
|
"""Activate agent (soft "undelete")."""
|