agent0-sdk 0.2.0__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 +52 -0
- agent0_sdk/core/agent.py +860 -0
- agent0_sdk/core/contracts.py +490 -0
- agent0_sdk/core/endpoint_crawler.py +270 -0
- agent0_sdk/core/feedback_manager.py +923 -0
- agent0_sdk/core/indexer.py +1016 -0
- agent0_sdk/core/ipfs_client.py +355 -0
- agent0_sdk/core/models.py +311 -0
- agent0_sdk/core/sdk.py +842 -0
- agent0_sdk/core/subgraph_client.py +813 -0
- agent0_sdk/core/web3_client.py +192 -0
- agent0_sdk-0.2.0.dist-info/METADATA +308 -0
- agent0_sdk-0.2.0.dist-info/RECORD +27 -0
- agent0_sdk-0.2.0.dist-info/WHEEL +5 -0
- agent0_sdk-0.2.0.dist-info/licenses/LICENSE +22 -0
- agent0_sdk-0.2.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +1 -0
- tests/config.py +46 -0
- tests/conftest.py +22 -0
- tests/test_feedback.py +417 -0
- tests/test_models.py +224 -0
- tests/test_real_public_servers.py +103 -0
- tests/test_registration.py +267 -0
- tests/test_registrationIpfs.py +227 -0
- tests/test_sdk.py +238 -0
- tests/test_search.py +271 -0
- tests/test_transfer.py +255 -0
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test Endpoint Crawler with Real Public MCP and A2A Servers
|
|
3
|
+
Tests against actual public servers provided by the user.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import sys
|
|
8
|
+
import os
|
|
9
|
+
|
|
10
|
+
# Configure logging: root logger at WARNING to suppress noisy dependencies
|
|
11
|
+
logging.basicConfig(
|
|
12
|
+
level=logging.WARNING,
|
|
13
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
14
|
+
datefmt='%Y-%m-%d %H:%M:%S',
|
|
15
|
+
handlers=[logging.StreamHandler(sys.stdout)]
|
|
16
|
+
)
|
|
17
|
+
|
|
18
|
+
# Set debug level ONLY for agent0_sdk
|
|
19
|
+
logging.getLogger('agent0_sdk').setLevel(logging.DEBUG)
|
|
20
|
+
logging.getLogger('agent0_sdk.core').setLevel(logging.DEBUG)
|
|
21
|
+
|
|
22
|
+
sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', 'src'))
|
|
23
|
+
|
|
24
|
+
from agent0_sdk.core.endpoint_crawler import EndpointCrawler
|
|
25
|
+
import json
|
|
26
|
+
|
|
27
|
+
def main():
|
|
28
|
+
print("๐งช Testing Endpoint Crawler with Real Public Servers")
|
|
29
|
+
print("=" * 70)
|
|
30
|
+
|
|
31
|
+
crawler = EndpointCrawler(timeout=10) # Longer timeout for real servers
|
|
32
|
+
|
|
33
|
+
# Real public endpoints
|
|
34
|
+
test_cases = [
|
|
35
|
+
{
|
|
36
|
+
"type": "A2A",
|
|
37
|
+
"endpoint": "https://hello-world-gxfr.onrender.com",
|
|
38
|
+
"description": "Real A2A Hello World Server"
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"type": "MCP",
|
|
42
|
+
"endpoint": "https://mcp.atlassian.com/v1/forge/mcp",
|
|
43
|
+
"description": "Atlassian MCP Server (requires authentication, will fail gracefully)"
|
|
44
|
+
}
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
successful_tests = []
|
|
48
|
+
failed_tests = []
|
|
49
|
+
|
|
50
|
+
for i, test_case in enumerate(test_cases, 1):
|
|
51
|
+
print(f"\n๐ Test {i}: {test_case['type']} Endpoint")
|
|
52
|
+
print("-" * 70)
|
|
53
|
+
print(f"URL: {test_case['endpoint']}")
|
|
54
|
+
print(f"Description: {test_case['description']}")
|
|
55
|
+
print()
|
|
56
|
+
|
|
57
|
+
if test_case['type'] == 'A2A':
|
|
58
|
+
capabilities = crawler.fetch_a2a_capabilities(test_case['endpoint'])
|
|
59
|
+
if capabilities:
|
|
60
|
+
print("โ
SUCCESS! Fetched A2A capabilities:")
|
|
61
|
+
print(json.dumps(capabilities, indent=2))
|
|
62
|
+
successful_tests.append(test_case)
|
|
63
|
+
else:
|
|
64
|
+
print("โ Failed to fetch A2A capabilities")
|
|
65
|
+
failed_tests.append(test_case)
|
|
66
|
+
|
|
67
|
+
elif test_case['type'] == 'MCP':
|
|
68
|
+
capabilities = crawler.fetch_mcp_capabilities(test_case['endpoint'])
|
|
69
|
+
if capabilities:
|
|
70
|
+
print("โ
SUCCESS! Fetched MCP capabilities:")
|
|
71
|
+
print(json.dumps(capabilities, indent=2))
|
|
72
|
+
successful_tests.append(test_case)
|
|
73
|
+
else:
|
|
74
|
+
print("โ Failed to fetch MCP capabilities")
|
|
75
|
+
failed_tests.append(test_case)
|
|
76
|
+
|
|
77
|
+
# Summary
|
|
78
|
+
print("\n" + "=" * 70)
|
|
79
|
+
print("๐ Summary")
|
|
80
|
+
print("-" * 70)
|
|
81
|
+
print(f"โ
Successful: {len(successful_tests)}")
|
|
82
|
+
print(f"โ Failed: {len(failed_tests)}")
|
|
83
|
+
|
|
84
|
+
if successful_tests:
|
|
85
|
+
print("\nโ
Successfully tested endpoints:")
|
|
86
|
+
for test in successful_tests:
|
|
87
|
+
print(f" - {test['type']}: {test['endpoint']}")
|
|
88
|
+
|
|
89
|
+
if failed_tests:
|
|
90
|
+
print("\nโ ๏ธ Failed endpoints:")
|
|
91
|
+
for test in failed_tests:
|
|
92
|
+
print(f" - {test['type']}: {test['endpoint']}")
|
|
93
|
+
|
|
94
|
+
print("\n" + "=" * 70)
|
|
95
|
+
if successful_tests:
|
|
96
|
+
print("๐ Endpoint crawler is working with real public servers!")
|
|
97
|
+
else:
|
|
98
|
+
print("โ ๏ธ No capabilities fetched. Check endpoints or network connection.")
|
|
99
|
+
print("=" * 70)
|
|
100
|
+
|
|
101
|
+
if __name__ == "__main__":
|
|
102
|
+
main()
|
|
103
|
+
|
|
@@ -0,0 +1,267 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test for Agent Registration with HTTP URI
|
|
3
|
+
Creates an agent, registers it with a mock HTTP URI, updates it, and verifies data integrity.
|
|
4
|
+
|
|
5
|
+
Flow:
|
|
6
|
+
1. Register agent on-chain with mock URI (obtain agentId)
|
|
7
|
+
2. Prepare registration file with obtained agentId
|
|
8
|
+
3. Print registration file JSON for developer to host
|
|
9
|
+
4. Update agent and verify consistency
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
import logging
|
|
13
|
+
import time
|
|
14
|
+
import random
|
|
15
|
+
import json
|
|
16
|
+
import sys
|
|
17
|
+
|
|
18
|
+
# Configure logging: root logger at WARNING to suppress noisy dependencies
|
|
19
|
+
logging.basicConfig(
|
|
20
|
+
level=logging.WARNING,
|
|
21
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
22
|
+
datefmt='%Y-%m-%d %H:%M:%S',
|
|
23
|
+
handlers=[logging.StreamHandler(sys.stdout)]
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
# Set debug level ONLY for agent0_sdk
|
|
27
|
+
logging.getLogger('agent0_sdk').setLevel(logging.DEBUG)
|
|
28
|
+
logging.getLogger('agent0_sdk.core').setLevel(logging.DEBUG)
|
|
29
|
+
|
|
30
|
+
from agent0_sdk import SDK
|
|
31
|
+
from config import CHAIN_ID, RPC_URL, AGENT_PRIVATE_KEY, print_config
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
def generateRandomData():
|
|
35
|
+
"""Generate random test data for the agent."""
|
|
36
|
+
randomSuffix = random.randint(1000, 9999)
|
|
37
|
+
timestamp = int(time.time())
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
'name': f"Test Agent {randomSuffix}",
|
|
41
|
+
'description': f"Created at {timestamp}",
|
|
42
|
+
'image': f"https://example.com/image_{randomSuffix}.png",
|
|
43
|
+
'mcpEndpoint': f"https://api.example.com/mcp/{randomSuffix}",
|
|
44
|
+
'mcpVersion': f"2025-06-{random.randint(1, 28)}",
|
|
45
|
+
'a2aEndpoint': f"https://api.example.com/a2a/{randomSuffix}.json",
|
|
46
|
+
'a2aVersion': f"0.{random.randint(30, 35)}",
|
|
47
|
+
'ensName': f"test{randomSuffix}.eth",
|
|
48
|
+
'ensVersion': f"1.{random.randint(0, 9)}",
|
|
49
|
+
'walletAddress': f"0x{'a' * 40}",
|
|
50
|
+
'walletChainId': random.choice([1, 11155111, 8453, 137, 42161]),
|
|
51
|
+
'active': True,
|
|
52
|
+
'x402support': False,
|
|
53
|
+
'reputation': random.choice([True, False]),
|
|
54
|
+
'cryptoEconomic': random.choice([True, False]),
|
|
55
|
+
'teeAttestation': random.choice([True, False])
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
|
|
59
|
+
def main():
|
|
60
|
+
print("๐งช Testing Agent Registration with HTTP URI")
|
|
61
|
+
print_config()
|
|
62
|
+
|
|
63
|
+
# SDK Configuration - no IPFS
|
|
64
|
+
sdkConfig = {
|
|
65
|
+
'chainId': CHAIN_ID,
|
|
66
|
+
'rpcUrl': RPC_URL
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
sdk = SDK(signer=AGENT_PRIVATE_KEY, **sdkConfig)
|
|
70
|
+
testData = generateRandomData()
|
|
71
|
+
|
|
72
|
+
# Step 1: Register agent on-chain with mock HTTP URI
|
|
73
|
+
print("\n๐ Step 1: Register Agent on-Chain with Mock URI")
|
|
74
|
+
print("-" * 60)
|
|
75
|
+
|
|
76
|
+
agent = sdk.createAgent(
|
|
77
|
+
name=testData['name'],
|
|
78
|
+
description=testData['description'],
|
|
79
|
+
image=testData['image']
|
|
80
|
+
)
|
|
81
|
+
|
|
82
|
+
# Register with mock URI to get agentId
|
|
83
|
+
mockUri = "https://example.com/agents/registration.json"
|
|
84
|
+
agent.register(mockUri)
|
|
85
|
+
agentId = agent.agentId
|
|
86
|
+
print(f"โ
Registered: ID={agentId}")
|
|
87
|
+
print(f" Mock URI: {mockUri}")
|
|
88
|
+
|
|
89
|
+
# Step 2: Configure agent with all details
|
|
90
|
+
print("\n๐ Step 2: Configure Agent Details")
|
|
91
|
+
print("-" * 60)
|
|
92
|
+
print(f"โ
Created: {testData['name']}")
|
|
93
|
+
|
|
94
|
+
agent.setMCP(testData['mcpEndpoint'], testData['mcpVersion'])
|
|
95
|
+
agent.setA2A(testData['a2aEndpoint'], testData['a2aVersion'])
|
|
96
|
+
agent.setENS(testData['ensName'], testData['ensVersion'])
|
|
97
|
+
agent.setAgentWallet(testData['walletAddress'], testData['walletChainId'])
|
|
98
|
+
agent.setActive(testData['active'])
|
|
99
|
+
agent.setX402Support(testData['x402support'])
|
|
100
|
+
agent.setTrust(
|
|
101
|
+
reputation=testData['reputation'],
|
|
102
|
+
cryptoEconomic=testData['cryptoEconomic'],
|
|
103
|
+
teeAttestation=testData['teeAttestation']
|
|
104
|
+
)
|
|
105
|
+
|
|
106
|
+
# Step 3: Get registration file and print it
|
|
107
|
+
print("\n๐ Step 3: Registration File for Hosting")
|
|
108
|
+
print("-" * 60)
|
|
109
|
+
|
|
110
|
+
registrationFile = agent.getRegistrationFile()
|
|
111
|
+
registrationJson = json.dumps(registrationFile.to_dict(), indent=2)
|
|
112
|
+
|
|
113
|
+
print("Registration file JSON (host this at the URL you specified):")
|
|
114
|
+
print("\n" + registrationJson)
|
|
115
|
+
|
|
116
|
+
# Save to file
|
|
117
|
+
filename = f"agent_registration_{agentId.replace(':', '_')}.json"
|
|
118
|
+
with open(filename, 'w') as f:
|
|
119
|
+
f.write(registrationJson)
|
|
120
|
+
print(f"\nโ
Saved to: {filename}")
|
|
121
|
+
|
|
122
|
+
capturedState = {
|
|
123
|
+
'agentId': agent.agentId,
|
|
124
|
+
'agentURI': agent.agentURI,
|
|
125
|
+
'name': agent.name,
|
|
126
|
+
'description': agent.description,
|
|
127
|
+
'image': agent.image,
|
|
128
|
+
'walletAddress': agent.walletAddress,
|
|
129
|
+
'walletChainId': agent.walletChainId,
|
|
130
|
+
'active': agent.active,
|
|
131
|
+
'x402support': agent.x402support,
|
|
132
|
+
'mcpEndpoint': agent.mcpEndpoint,
|
|
133
|
+
'a2aEndpoint': agent.a2aEndpoint,
|
|
134
|
+
'ensEndpoint': agent.ensEndpoint,
|
|
135
|
+
'metadata': agent.metadata.copy()
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
# Step 4: Update agent
|
|
139
|
+
print("\n๐ Step 4: Update Agent")
|
|
140
|
+
print("-" * 60)
|
|
141
|
+
|
|
142
|
+
agent.updateInfo(
|
|
143
|
+
name=testData['name'] + " UPDATED",
|
|
144
|
+
description=testData['description'] + " - UPDATED",
|
|
145
|
+
image=f"https://example.com/image_{random.randint(1000, 9999)}_updated.png"
|
|
146
|
+
)
|
|
147
|
+
agent.setMCP(f"https://api.example.com/mcp/{random.randint(10000, 99999)}", f"2025-06-{random.randint(1, 28)}")
|
|
148
|
+
agent.setA2A(f"https://api.example.com/a2a/{random.randint(10000, 99999)}.json", f"0.{random.randint(30, 35)}")
|
|
149
|
+
agent.setAgentWallet(f"0x{'b' * 40}", random.choice([1, 11155111, 8453, 137, 42161]))
|
|
150
|
+
agent.setENS(f"{testData['ensName']}.updated", f"1.{random.randint(0, 9)}")
|
|
151
|
+
agent.setActive(False)
|
|
152
|
+
agent.setX402Support(True)
|
|
153
|
+
agent.setTrust(
|
|
154
|
+
reputation=random.choice([True, False]),
|
|
155
|
+
cryptoEconomic=random.choice([True, False]),
|
|
156
|
+
teeAttestation=random.choice([True, False])
|
|
157
|
+
)
|
|
158
|
+
agent.setMetadata({
|
|
159
|
+
"testKey": "testValue",
|
|
160
|
+
"timestamp": int(time.time()),
|
|
161
|
+
"customField": "customValue",
|
|
162
|
+
"anotherField": "anotherValue",
|
|
163
|
+
"numericField": random.randint(1000, 9999)
|
|
164
|
+
})
|
|
165
|
+
|
|
166
|
+
# Update registration file and re-register
|
|
167
|
+
registrationFileUpdated = agent.getRegistrationFile()
|
|
168
|
+
registrationJsonUpdated = json.dumps(registrationFileUpdated.to_dict(), indent=2)
|
|
169
|
+
|
|
170
|
+
filenameUpdated = f"agent_registration_{agentId.replace(':', '_')}_updated.json"
|
|
171
|
+
with open(filenameUpdated, 'w') as f:
|
|
172
|
+
f.write(registrationJsonUpdated)
|
|
173
|
+
|
|
174
|
+
agent.register(mockUri)
|
|
175
|
+
print(f"โ
Updated & re-registered")
|
|
176
|
+
print(f" Updated registration file: {filenameUpdated}")
|
|
177
|
+
|
|
178
|
+
# Capture updated state
|
|
179
|
+
updatedState = {
|
|
180
|
+
'name': agent.name,
|
|
181
|
+
'description': agent.description,
|
|
182
|
+
'image': agent.image,
|
|
183
|
+
'walletAddress': agent.walletAddress,
|
|
184
|
+
'walletChainId': agent.walletChainId,
|
|
185
|
+
'active': agent.active,
|
|
186
|
+
'x402support': agent.x402support,
|
|
187
|
+
'mcpEndpoint': agent.mcpEndpoint,
|
|
188
|
+
'a2aEndpoint': agent.a2aEndpoint,
|
|
189
|
+
'ensEndpoint': agent.ensEndpoint,
|
|
190
|
+
'metadata': agent.metadata.copy()
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
# Step 5: Reload and verify
|
|
194
|
+
print("\n๐ Step 5: Reload and Verify")
|
|
195
|
+
print("-" * 60)
|
|
196
|
+
|
|
197
|
+
reloadedAgentId = agent.agentId
|
|
198
|
+
del agent
|
|
199
|
+
print("โณ Waiting for blockchain transaction to be mined (15 seconds)...")
|
|
200
|
+
time.sleep(15)
|
|
201
|
+
reloadedAgent = sdk.loadAgent(reloadedAgentId)
|
|
202
|
+
print(f"โ
Reloaded from blockchain")
|
|
203
|
+
|
|
204
|
+
reloadedState = {
|
|
205
|
+
'name': reloadedAgent.name,
|
|
206
|
+
'description': reloadedAgent.description,
|
|
207
|
+
'image': reloadedAgent.image,
|
|
208
|
+
'walletAddress': reloadedAgent.walletAddress,
|
|
209
|
+
'walletChainId': reloadedAgent.walletChainId,
|
|
210
|
+
'active': reloadedAgent.active,
|
|
211
|
+
'x402support': reloadedAgent.x402support,
|
|
212
|
+
'mcpEndpoint': reloadedAgent.mcpEndpoint,
|
|
213
|
+
'a2aEndpoint': reloadedAgent.a2aEndpoint,
|
|
214
|
+
'ensEndpoint': reloadedAgent.ensEndpoint,
|
|
215
|
+
'metadata': reloadedAgent.metadata.copy()
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
expectedState = updatedState
|
|
219
|
+
expectedState['walletAddress'] = f"0x{'b' * 40}"
|
|
220
|
+
expectedState['walletChainId'] = sdk.chainId
|
|
221
|
+
|
|
222
|
+
allMatch = True
|
|
223
|
+
for field, expected in expectedState.items():
|
|
224
|
+
actual = reloadedState.get(field)
|
|
225
|
+
|
|
226
|
+
# Handle type casting for metadata fields
|
|
227
|
+
if field == 'metadata' and isinstance(actual, dict) and isinstance(expected, dict):
|
|
228
|
+
normalized_actual = {}
|
|
229
|
+
for k, v in actual.items():
|
|
230
|
+
if k in expected:
|
|
231
|
+
expected_val = expected[k]
|
|
232
|
+
if isinstance(expected_val, int):
|
|
233
|
+
try:
|
|
234
|
+
normalized_actual[k] = int(v) if isinstance(v, str) else v
|
|
235
|
+
except (ValueError, TypeError):
|
|
236
|
+
normalized_actual[k] = v
|
|
237
|
+
elif isinstance(expected_val, float):
|
|
238
|
+
try:
|
|
239
|
+
normalized_actual[k] = float(v) if isinstance(v, str) else v
|
|
240
|
+
except (ValueError, TypeError):
|
|
241
|
+
normalized_actual[k] = v
|
|
242
|
+
else:
|
|
243
|
+
normalized_actual[k] = v
|
|
244
|
+
else:
|
|
245
|
+
normalized_actual[k] = v
|
|
246
|
+
actual = normalized_actual
|
|
247
|
+
|
|
248
|
+
if actual == expected:
|
|
249
|
+
print(f"โ
{field}: {actual}")
|
|
250
|
+
else:
|
|
251
|
+
print(f"โ {field}: expected={expected}, got={actual}")
|
|
252
|
+
allMatch = False
|
|
253
|
+
|
|
254
|
+
if allMatch:
|
|
255
|
+
print("\nโ
ALL CHECKS PASSED")
|
|
256
|
+
else:
|
|
257
|
+
print("\nโ SOME CHECKS FAILED")
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
if __name__ == "__main__":
|
|
261
|
+
try:
|
|
262
|
+
main()
|
|
263
|
+
except Exception as e:
|
|
264
|
+
print(f"\nโ Error: {e}")
|
|
265
|
+
import traceback
|
|
266
|
+
traceback.print_exc()
|
|
267
|
+
exit(1)
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Real Test for Agent Registration with IPFS Pin (using Pinata)
|
|
3
|
+
Creates an agent, updates it on-chain, deletes it, reloads it, and verifies data integrity.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import logging
|
|
7
|
+
import time
|
|
8
|
+
import random
|
|
9
|
+
import sys
|
|
10
|
+
|
|
11
|
+
# Configure logging: root logger at WARNING to suppress noisy dependencies
|
|
12
|
+
logging.basicConfig(
|
|
13
|
+
level=logging.WARNING,
|
|
14
|
+
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
|
|
15
|
+
datefmt='%Y-%m-%d %H:%M:%S',
|
|
16
|
+
handlers=[logging.StreamHandler(sys.stdout)]
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Set debug level ONLY for agent0_sdk
|
|
20
|
+
logging.getLogger('agent0_sdk').setLevel(logging.DEBUG)
|
|
21
|
+
logging.getLogger('agent0_sdk.core').setLevel(logging.DEBUG)
|
|
22
|
+
|
|
23
|
+
from agent0_sdk import SDK
|
|
24
|
+
from config import CHAIN_ID, RPC_URL, AGENT_PRIVATE_KEY, PINATA_JWT, print_config
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
def generateRandomData():
|
|
28
|
+
"""Generate random test data for the agent."""
|
|
29
|
+
randomSuffix = random.randint(1000, 9999)
|
|
30
|
+
timestamp = int(time.time())
|
|
31
|
+
|
|
32
|
+
return {
|
|
33
|
+
'name': f"Test Agent {randomSuffix}",
|
|
34
|
+
'description': f"Created at {timestamp}",
|
|
35
|
+
'image': f"https://example.com/image_{randomSuffix}.png",
|
|
36
|
+
'mcpEndpoint': f"https://api.example.com/mcp/{randomSuffix}",
|
|
37
|
+
'mcpVersion': f"2025-06-{random.randint(1, 28)}",
|
|
38
|
+
'a2aEndpoint': f"https://api.example.com/a2a/{randomSuffix}.json",
|
|
39
|
+
'a2aVersion': f"0.{random.randint(30, 35)}",
|
|
40
|
+
'ensName': f"test{randomSuffix}.eth",
|
|
41
|
+
'ensVersion': f"1.{random.randint(0, 9)}",
|
|
42
|
+
'walletAddress': f"0x{'a' * 40}",
|
|
43
|
+
'walletChainId': random.choice([1, 11155111, 8453, 137, 42161]), # Mainnet, Sepolia, Base, Polygon, Arbitrum
|
|
44
|
+
'active': True,
|
|
45
|
+
'x402support': False,
|
|
46
|
+
'reputation': random.choice([True, False]),
|
|
47
|
+
'cryptoEconomic': random.choice([True, False]),
|
|
48
|
+
'teeAttestation': random.choice([True, False])
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def main():
|
|
53
|
+
print("๐งช Testing Agent Registration with IPFS Pin")
|
|
54
|
+
print_config()
|
|
55
|
+
|
|
56
|
+
# SDK Configuration with Pinata IPFS
|
|
57
|
+
sdkConfig = {
|
|
58
|
+
'chainId': CHAIN_ID,
|
|
59
|
+
'rpcUrl': RPC_URL,
|
|
60
|
+
'ipfs': 'pinata',
|
|
61
|
+
'pinataJwt': PINATA_JWT
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
sdk = SDK(signer=AGENT_PRIVATE_KEY, **sdkConfig)
|
|
65
|
+
testData = generateRandomData()
|
|
66
|
+
|
|
67
|
+
agent = sdk.createAgent(
|
|
68
|
+
name=testData['name'],
|
|
69
|
+
description=testData['description'],
|
|
70
|
+
image=testData['image']
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
agent.setMCP(testData['mcpEndpoint'], testData['mcpVersion'])
|
|
74
|
+
agent.setA2A(testData['a2aEndpoint'], testData['a2aVersion'])
|
|
75
|
+
agent.setENS(testData['ensName'], testData['ensVersion'])
|
|
76
|
+
agent.setAgentWallet(testData['walletAddress'], testData['walletChainId'])
|
|
77
|
+
agent.setActive(testData['active'])
|
|
78
|
+
agent.setX402Support(testData['x402support'])
|
|
79
|
+
agent.setTrust(
|
|
80
|
+
reputation=testData['reputation'],
|
|
81
|
+
cryptoEconomic=testData['cryptoEconomic'],
|
|
82
|
+
teeAttestation=testData['teeAttestation']
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
print(f"\nโ
Created: {testData['name']}")
|
|
86
|
+
|
|
87
|
+
agent.registerIPFS()
|
|
88
|
+
agentId = agent.agentId
|
|
89
|
+
print(f"โ
Registered: ID={agentId}")
|
|
90
|
+
|
|
91
|
+
capturedState = {
|
|
92
|
+
'agentId': agent.agentId,
|
|
93
|
+
'agentURI': agent.agentURI,
|
|
94
|
+
'name': agent.name,
|
|
95
|
+
'description': agent.description,
|
|
96
|
+
'image': agent.image,
|
|
97
|
+
'walletAddress': agent.walletAddress,
|
|
98
|
+
'walletChainId': agent.walletChainId,
|
|
99
|
+
'active': agent.active,
|
|
100
|
+
'x402support': agent.x402support,
|
|
101
|
+
'mcpEndpoint': agent.mcpEndpoint,
|
|
102
|
+
'a2aEndpoint': agent.a2aEndpoint,
|
|
103
|
+
'ensEndpoint': agent.ensEndpoint,
|
|
104
|
+
'metadata': agent.metadata.copy()
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
agent.updateInfo(
|
|
108
|
+
name=testData['name'] + " UPDATED",
|
|
109
|
+
description=testData['description'] + " - UPDATED",
|
|
110
|
+
image=f"https://example.com/image_{random.randint(1000, 9999)}_updated.png"
|
|
111
|
+
)
|
|
112
|
+
agent.setMCP(f"https://api.example.com/mcp/{random.randint(10000, 99999)}", f"2025-06-{random.randint(1, 28)}")
|
|
113
|
+
agent.setA2A(f"https://api.example.com/a2a/{random.randint(10000, 99999)}.json", f"0.{random.randint(30, 35)}")
|
|
114
|
+
agent.setAgentWallet(f"0x{'b' * 40}", random.choice([1, 11155111, 8453, 137, 42161]))
|
|
115
|
+
agent.setENS(f"{testData['ensName']}.updated", f"1.{random.randint(0, 9)}")
|
|
116
|
+
agent.setActive(False)
|
|
117
|
+
agent.setX402Support(True)
|
|
118
|
+
agent.setTrust(
|
|
119
|
+
reputation=random.choice([True, False]),
|
|
120
|
+
cryptoEconomic=random.choice([True, False]),
|
|
121
|
+
teeAttestation=random.choice([True, False])
|
|
122
|
+
)
|
|
123
|
+
agent.setMetadata({
|
|
124
|
+
"testKey": "testValue",
|
|
125
|
+
"timestamp": int(time.time()),
|
|
126
|
+
"customField": "customValue",
|
|
127
|
+
"anotherField": "anotherValue",
|
|
128
|
+
"numericField": random.randint(1000, 9999)
|
|
129
|
+
})
|
|
130
|
+
|
|
131
|
+
agent.registerIPFS()
|
|
132
|
+
print(f"โ
Updated & re-registered")
|
|
133
|
+
|
|
134
|
+
# Capture updated state before deletion
|
|
135
|
+
updatedState = {
|
|
136
|
+
'name': agent.name,
|
|
137
|
+
'description': agent.description,
|
|
138
|
+
'image': agent.image,
|
|
139
|
+
'walletAddress': agent.walletAddress,
|
|
140
|
+
'walletChainId': agent.walletChainId,
|
|
141
|
+
'active': agent.active,
|
|
142
|
+
'x402support': agent.x402support,
|
|
143
|
+
'mcpEndpoint': agent.mcpEndpoint,
|
|
144
|
+
'a2aEndpoint': agent.a2aEndpoint,
|
|
145
|
+
'ensEndpoint': agent.ensEndpoint,
|
|
146
|
+
'metadata': agent.metadata.copy()
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
reloadedAgentId = agent.agentId
|
|
150
|
+
del agent
|
|
151
|
+
# Wait for blockchain transaction to be mined (Sepolia takes ~15 seconds)
|
|
152
|
+
print("โณ Waiting for blockchain transaction to be mined (15 seconds)...")
|
|
153
|
+
time.sleep(15)
|
|
154
|
+
reloadedAgent = sdk.loadAgent(reloadedAgentId)
|
|
155
|
+
print(f"โ
Reloaded from blockchain")
|
|
156
|
+
|
|
157
|
+
reloadedState = {
|
|
158
|
+
'name': reloadedAgent.name,
|
|
159
|
+
'description': reloadedAgent.description,
|
|
160
|
+
'image': reloadedAgent.image,
|
|
161
|
+
'walletAddress': reloadedAgent.walletAddress,
|
|
162
|
+
'walletChainId': reloadedAgent.walletChainId,
|
|
163
|
+
'active': reloadedAgent.active,
|
|
164
|
+
'x402support': reloadedAgent.x402support,
|
|
165
|
+
'mcpEndpoint': reloadedAgent.mcpEndpoint,
|
|
166
|
+
'a2aEndpoint': reloadedAgent.a2aEndpoint,
|
|
167
|
+
'ensEndpoint': reloadedAgent.ensEndpoint,
|
|
168
|
+
'metadata': reloadedAgent.metadata.copy()
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
expectedState = updatedState
|
|
172
|
+
|
|
173
|
+
# Override expected values for fields that should match the updated state
|
|
174
|
+
expectedState['walletAddress'] = f"0x{'b' * 40}"
|
|
175
|
+
# When wallet is set on-chain, walletChainId will be the current chain (where the update happened)
|
|
176
|
+
# This is different from the original registration file's chain ID
|
|
177
|
+
expectedState['walletChainId'] = sdk.chainId # Current chain where wallet was updated
|
|
178
|
+
|
|
179
|
+
allMatch = True
|
|
180
|
+
for field, expected in expectedState.items():
|
|
181
|
+
actual = reloadedState.get(field)
|
|
182
|
+
|
|
183
|
+
# Handle type casting for metadata fields (on-chain values are strings)
|
|
184
|
+
if field == 'metadata' and isinstance(actual, dict) and isinstance(expected, dict):
|
|
185
|
+
# Try to cast string values back to their original types
|
|
186
|
+
normalized_actual = {}
|
|
187
|
+
for k, v in actual.items():
|
|
188
|
+
if k in expected:
|
|
189
|
+
expected_val = expected[k]
|
|
190
|
+
# If expected is int or float, try to cast
|
|
191
|
+
if isinstance(expected_val, int):
|
|
192
|
+
try:
|
|
193
|
+
normalized_actual[k] = int(v) if isinstance(v, str) else v
|
|
194
|
+
except (ValueError, TypeError):
|
|
195
|
+
normalized_actual[k] = v
|
|
196
|
+
elif isinstance(expected_val, float):
|
|
197
|
+
try:
|
|
198
|
+
normalized_actual[k] = float(v) if isinstance(v, str) else v
|
|
199
|
+
except (ValueError, TypeError):
|
|
200
|
+
normalized_actual[k] = v
|
|
201
|
+
else:
|
|
202
|
+
normalized_actual[k] = v
|
|
203
|
+
else:
|
|
204
|
+
normalized_actual[k] = v
|
|
205
|
+
actual = normalized_actual
|
|
206
|
+
|
|
207
|
+
if actual == expected:
|
|
208
|
+
print(f"โ
{field}: {actual}")
|
|
209
|
+
else:
|
|
210
|
+
print(f"โ {field}: expected={expected}, got={actual}")
|
|
211
|
+
allMatch = False
|
|
212
|
+
|
|
213
|
+
if allMatch:
|
|
214
|
+
print("\nโ
ALL CHECKS PASSED")
|
|
215
|
+
else:
|
|
216
|
+
print("\nโ SOME CHECKS FAILED")
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
if __name__ == "__main__":
|
|
220
|
+
try:
|
|
221
|
+
main()
|
|
222
|
+
except Exception as e:
|
|
223
|
+
print(f"\nโ Error: {e}")
|
|
224
|
+
import traceback
|
|
225
|
+
traceback.print_exc()
|
|
226
|
+
exit(1)
|
|
227
|
+
|