agentspay 0.1.0 โ 0.2.0
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.
- package/.env.example +40 -0
- package/README.md +35 -4
- package/VERIFICATION_SUMMARY.txt +151 -0
- package/dist/api/server.d.ts.map +1 -1
- package/dist/api/server.js +530 -74
- package/dist/api/server.js.map +1 -1
- package/dist/bsv/crypto.d.ts +65 -0
- package/dist/bsv/crypto.d.ts.map +1 -0
- package/dist/bsv/crypto.js +158 -0
- package/dist/bsv/crypto.js.map +1 -0
- package/dist/bsv/mnee.d.ts +88 -0
- package/dist/bsv/mnee.d.ts.map +1 -0
- package/dist/bsv/mnee.js +173 -0
- package/dist/bsv/mnee.js.map +1 -0
- package/dist/bsv/opreturn.d.ts +22 -0
- package/dist/bsv/opreturn.d.ts.map +1 -0
- package/dist/bsv/opreturn.js +117 -0
- package/dist/bsv/opreturn.js.map +1 -0
- package/dist/bsv/whatsonchain.d.ts +46 -0
- package/dist/bsv/whatsonchain.d.ts.map +1 -0
- package/dist/bsv/whatsonchain.js +98 -0
- package/dist/bsv/whatsonchain.js.map +1 -0
- package/dist/config.d.ts +38 -0
- package/dist/config.d.ts.map +1 -0
- package/dist/config.js +85 -0
- package/dist/config.js.map +1 -0
- package/dist/currency/currency.d.ts +70 -0
- package/dist/currency/currency.d.ts.map +1 -0
- package/dist/currency/currency.js +137 -0
- package/dist/currency/currency.js.map +1 -0
- package/dist/disputes/dispute.d.ts +50 -0
- package/dist/disputes/dispute.d.ts.map +1 -0
- package/dist/disputes/dispute.js +162 -0
- package/dist/disputes/dispute.js.map +1 -0
- package/dist/docs/openapi.yaml +1079 -0
- package/dist/docs/swagger.d.ts +12 -0
- package/dist/docs/swagger.d.ts.map +1 -0
- package/dist/docs/swagger.js +104 -0
- package/dist/docs/swagger.js.map +1 -0
- package/dist/middleware/auth.d.ts +20 -0
- package/dist/middleware/auth.d.ts.map +1 -0
- package/dist/middleware/auth.js +32 -0
- package/dist/middleware/auth.js.map +1 -0
- package/dist/middleware/rateLimit.d.ts +25 -0
- package/dist/middleware/rateLimit.d.ts.map +1 -0
- package/dist/middleware/rateLimit.js +61 -0
- package/dist/middleware/rateLimit.js.map +1 -0
- package/dist/payment/payment.d.ts +79 -9
- package/dist/payment/payment.d.ts.map +1 -1
- package/dist/payment/payment.js +387 -47
- package/dist/payment/payment.js.map +1 -1
- package/dist/registry/db.d.ts.map +1 -1
- package/dist/registry/db.js +110 -3
- package/dist/registry/db.js.map +1 -1
- package/dist/registry/registry.d.ts +1 -1
- package/dist/registry/registry.d.ts.map +1 -1
- package/dist/registry/registry.js +12 -4
- package/dist/registry/registry.js.map +1 -1
- package/dist/types/index.d.ts +34 -0
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/index.js.map +1 -1
- package/dist/utils/validation.d.ts +27 -0
- package/dist/utils/validation.d.ts.map +1 -0
- package/dist/utils/validation.js +164 -0
- package/dist/utils/validation.js.map +1 -0
- package/dist/verification/receipt.d.ts +42 -0
- package/dist/verification/receipt.d.ts.map +1 -0
- package/dist/verification/receipt.js +10 -0
- package/dist/verification/receipt.js.map +1 -0
- package/dist/verification/verification.d.ts +41 -0
- package/dist/verification/verification.d.ts.map +1 -0
- package/dist/verification/verification.js +217 -0
- package/dist/verification/verification.js.map +1 -0
- package/dist/wallet/providerManager.d.ts +32 -0
- package/dist/wallet/providerManager.d.ts.map +1 -0
- package/dist/wallet/providerManager.js +118 -0
- package/dist/wallet/providerManager.js.map +1 -0
- package/dist/wallet/providers/handcash.d.ts +22 -0
- package/dist/wallet/providers/handcash.d.ts.map +1 -0
- package/dist/wallet/providers/handcash.js +214 -0
- package/dist/wallet/providers/handcash.js.map +1 -0
- package/dist/wallet/providers/internal.d.ts +15 -0
- package/dist/wallet/providers/internal.d.ts.map +1 -0
- package/dist/wallet/providers/internal.js +208 -0
- package/dist/wallet/providers/internal.js.map +1 -0
- package/dist/wallet/providers/types.d.ts +50 -0
- package/dist/wallet/providers/types.d.ts.map +1 -0
- package/dist/wallet/providers/types.js +6 -0
- package/dist/wallet/providers/types.js.map +1 -0
- package/dist/wallet/providers/yours.d.ts +18 -0
- package/dist/wallet/providers/yours.d.ts.map +1 -0
- package/dist/wallet/providers/yours.js +122 -0
- package/dist/wallet/providers/yours.js.map +1 -0
- package/dist/wallet/wallet.d.ts +52 -5
- package/dist/wallet/wallet.d.ts.map +1 -1
- package/dist/wallet/wallet.js +223 -34
- package/dist/wallet/wallet.js.map +1 -1
- package/dist/webhooks/delivery.d.ts +37 -0
- package/dist/webhooks/delivery.d.ts.map +1 -0
- package/dist/webhooks/delivery.js +182 -0
- package/dist/webhooks/delivery.js.map +1 -0
- package/dist/webhooks/webhook.d.ts +85 -0
- package/dist/webhooks/webhook.d.ts.map +1 -0
- package/dist/webhooks/webhook.js +271 -0
- package/dist/webhooks/webhook.js.map +1 -0
- package/package.json +74 -54
- package/sdk-python/LICENSE +21 -0
- package/sdk-python/MANIFEST.in +9 -0
- package/sdk-python/README.md +372 -0
- package/sdk-python/agentspay/__init__.py +97 -0
- package/sdk-python/agentspay/client.py +256 -0
- package/sdk-python/agentspay/disputes.py +174 -0
- package/sdk-python/agentspay/exceptions.py +53 -0
- package/sdk-python/agentspay/payments.py +169 -0
- package/sdk-python/agentspay/services.py +198 -0
- package/sdk-python/agentspay/types.py +154 -0
- package/sdk-python/agentspay/wallet.py +113 -0
- package/sdk-python/agentspay/webhooks.py +195 -0
- package/sdk-python/examples/consumer.py +147 -0
- package/sdk-python/examples/provider.py +116 -0
- package/sdk-python/pyproject.toml +61 -0
- package/sdk-python/setup.py +53 -0
- package/sdk-python/tests/test_client.py +221 -0
- package/test-addr.js +29 -0
- package/test-mnee-simple.js +51 -0
- package/test-mnee.js +47 -0
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
AgentPay Consumer Example
|
|
4
|
+
|
|
5
|
+
This example shows how to:
|
|
6
|
+
1. Create a wallet
|
|
7
|
+
2. Search for services
|
|
8
|
+
3. Execute a service
|
|
9
|
+
4. Handle disputes if needed
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
from agentspay import AgentPayClient
|
|
13
|
+
import json
|
|
14
|
+
|
|
15
|
+
# Initialize client
|
|
16
|
+
client = AgentPayClient(
|
|
17
|
+
base_url="http://localhost:3100",
|
|
18
|
+
# api_key="your-api-key" # Optional API key
|
|
19
|
+
)
|
|
20
|
+
|
|
21
|
+
# Step 1: Create a wallet (or use existing one)
|
|
22
|
+
print("Creating wallet...")
|
|
23
|
+
wallet = client.create_wallet()
|
|
24
|
+
print(f"โ Wallet created: {wallet.id}")
|
|
25
|
+
print(f" Address: {wallet.address}")
|
|
26
|
+
|
|
27
|
+
# Check balance
|
|
28
|
+
balance_bsv = client.get_balance(wallet.id, currency="BSV")
|
|
29
|
+
balance_mnee = client.get_balance(wallet.id, currency="MNEE")
|
|
30
|
+
print(f" Balance: {balance_bsv} satoshis (BSV), {balance_mnee} cents (MNEE)")
|
|
31
|
+
|
|
32
|
+
# Step 2: Search for services
|
|
33
|
+
print("\n" + "="*60)
|
|
34
|
+
print("Searching for NLP services...")
|
|
35
|
+
print("="*60)
|
|
36
|
+
|
|
37
|
+
services = client.search_services(
|
|
38
|
+
keyword="nlp",
|
|
39
|
+
category="nlp",
|
|
40
|
+
max_price=5000, # Max 5000 satoshis
|
|
41
|
+
limit=5
|
|
42
|
+
)
|
|
43
|
+
|
|
44
|
+
if not services:
|
|
45
|
+
print("No services found. Make sure there are registered services.")
|
|
46
|
+
exit(1)
|
|
47
|
+
|
|
48
|
+
print(f"\nFound {len(services)} services:\n")
|
|
49
|
+
for i, service in enumerate(services, 1):
|
|
50
|
+
print(f"{i}. {service.name}")
|
|
51
|
+
print(f" Description: {service.description}")
|
|
52
|
+
print(f" Price: {service.price} satoshis ({service.currency})")
|
|
53
|
+
print(f" Category: {service.category}")
|
|
54
|
+
print(f" Provider: {service.agent_id}")
|
|
55
|
+
|
|
56
|
+
# Check provider reputation
|
|
57
|
+
try:
|
|
58
|
+
reputation = client.get_reputation(service.agent_id)
|
|
59
|
+
print(f" Rating: {reputation.rating}/5 ({reputation.total_jobs} jobs, "
|
|
60
|
+
f"{reputation.success_rate * 100:.1f}% success)")
|
|
61
|
+
except:
|
|
62
|
+
print(f" Rating: No reputation data")
|
|
63
|
+
print()
|
|
64
|
+
|
|
65
|
+
# Step 3: Execute a service
|
|
66
|
+
print("="*60)
|
|
67
|
+
print("Executing the first service...")
|
|
68
|
+
print("="*60)
|
|
69
|
+
|
|
70
|
+
selected_service = services[0]
|
|
71
|
+
print(f"\nService: {selected_service.name}")
|
|
72
|
+
print(f"Price: {selected_service.price} satoshis")
|
|
73
|
+
|
|
74
|
+
# Execute with input data
|
|
75
|
+
try:
|
|
76
|
+
result = client.execute(
|
|
77
|
+
service_id=selected_service.id,
|
|
78
|
+
buyer_wallet_id=wallet.id,
|
|
79
|
+
input_data={
|
|
80
|
+
"text": "AgentPay is a decentralized marketplace for AI agent services. "
|
|
81
|
+
"It enables autonomous agents to discover, execute, and pay for "
|
|
82
|
+
"services using Bitcoin SV."
|
|
83
|
+
}
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
print(f"\nโ Execution successful!")
|
|
87
|
+
print(f" Payment ID: {result.payment_id}")
|
|
88
|
+
print(f" Execution Time: {result.execution_time_ms}ms")
|
|
89
|
+
print(f" Status: {result.status}")
|
|
90
|
+
|
|
91
|
+
# Show output
|
|
92
|
+
print(f"\n Output:")
|
|
93
|
+
print(json.dumps(result.output, indent=4))
|
|
94
|
+
|
|
95
|
+
# Show receipt (cryptographic proof)
|
|
96
|
+
if result.receipt:
|
|
97
|
+
print(f"\n Receipt ID: {result.receipt.id}")
|
|
98
|
+
print(f" Input Hash: {result.receipt.input_hash}")
|
|
99
|
+
print(f" Output Hash: {result.receipt.output_hash}")
|
|
100
|
+
print(f" Receipt Hash: {result.receipt.receipt_hash}")
|
|
101
|
+
print(f" Provider Signature: {result.receipt.provider_signature[:32]}...")
|
|
102
|
+
|
|
103
|
+
# Show payment details
|
|
104
|
+
if result.payment:
|
|
105
|
+
payment = result.payment
|
|
106
|
+
print(f"\n Payment Status: {payment.status}")
|
|
107
|
+
print(f" Amount: {payment.amount} satoshis")
|
|
108
|
+
print(f" Platform Fee: {payment.platform_fee} satoshis")
|
|
109
|
+
if payment.tx_id:
|
|
110
|
+
print(f" Transaction ID: {payment.tx_id}")
|
|
111
|
+
|
|
112
|
+
except Exception as e:
|
|
113
|
+
print(f"\nโ Execution failed: {e}")
|
|
114
|
+
exit(1)
|
|
115
|
+
|
|
116
|
+
# Step 4: Example of opening a dispute (if needed)
|
|
117
|
+
print("\n" + "="*60)
|
|
118
|
+
print("Dispute Example (not executing, just showing API)")
|
|
119
|
+
print("="*60)
|
|
120
|
+
print("""
|
|
121
|
+
# If the output is not satisfactory, you can open a dispute:
|
|
122
|
+
|
|
123
|
+
dispute = client.open_dispute(
|
|
124
|
+
payment_id=result.payment_id,
|
|
125
|
+
reason="Output quality does not meet expectations",
|
|
126
|
+
evidence="Expected sentiment analysis but got only keywords. "
|
|
127
|
+
"Screenshots: https://imgur.com/abc123"
|
|
128
|
+
)
|
|
129
|
+
|
|
130
|
+
# Add more evidence later if needed
|
|
131
|
+
client.add_dispute_evidence(
|
|
132
|
+
dispute_id=dispute.id,
|
|
133
|
+
evidence="Additional evidence: server logs showing incorrect processing"
|
|
134
|
+
)
|
|
135
|
+
|
|
136
|
+
# Check dispute status
|
|
137
|
+
dispute_status = client.get_dispute(dispute.id)
|
|
138
|
+
print(f"Dispute status: {dispute_status.status}")
|
|
139
|
+
print(f"Resolution: {dispute_status.resolution}")
|
|
140
|
+
""")
|
|
141
|
+
|
|
142
|
+
print("\n" + "="*60)
|
|
143
|
+
print("Transaction Complete!")
|
|
144
|
+
print("="*60)
|
|
145
|
+
print(f"\nPayment ID: {result.payment_id}")
|
|
146
|
+
print("You can use this payment ID to track the transaction,")
|
|
147
|
+
print("open disputes, or retrieve the receipt at any time.")
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
AgentPay Provider Example
|
|
4
|
+
|
|
5
|
+
This example shows how to:
|
|
6
|
+
1. Create a wallet
|
|
7
|
+
2. Register a service
|
|
8
|
+
3. Handle incoming execution requests (conceptual)
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from agentspay import AgentPayClient
|
|
12
|
+
|
|
13
|
+
# Initialize client
|
|
14
|
+
client = AgentPayClient(
|
|
15
|
+
base_url="http://localhost:3100",
|
|
16
|
+
# api_key="your-api-key" # Optional API key
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# Step 1: Create a wallet for your agent
|
|
20
|
+
print("Creating wallet...")
|
|
21
|
+
wallet = client.create_wallet()
|
|
22
|
+
print(f"โ Wallet created: {wallet.id}")
|
|
23
|
+
print(f" Address: {wallet.address}")
|
|
24
|
+
print(f" Public Key: {wallet.public_key}")
|
|
25
|
+
|
|
26
|
+
# Step 2: Register a service
|
|
27
|
+
print("\nRegistering service...")
|
|
28
|
+
service = client.register_service(
|
|
29
|
+
agent_id=wallet.id,
|
|
30
|
+
name="TextAnalyzer",
|
|
31
|
+
description="Advanced NLP text analysis service",
|
|
32
|
+
price=1000, # 1000 satoshis per execution
|
|
33
|
+
currency="BSV", # or "MNEE"
|
|
34
|
+
endpoint="https://my-agent.com/api/analyze",
|
|
35
|
+
category="nlp",
|
|
36
|
+
method="POST",
|
|
37
|
+
timeout=30, # 30 seconds max execution time
|
|
38
|
+
dispute_window=30, # 30 minutes dispute window
|
|
39
|
+
input_schema={
|
|
40
|
+
"type": "object",
|
|
41
|
+
"properties": {
|
|
42
|
+
"text": {"type": "string"}
|
|
43
|
+
},
|
|
44
|
+
"required": ["text"]
|
|
45
|
+
}
|
|
46
|
+
)
|
|
47
|
+
|
|
48
|
+
print(f"โ Service registered: {service.id}")
|
|
49
|
+
print(f" Name: {service.name}")
|
|
50
|
+
print(f" Price: {service.price} satoshis")
|
|
51
|
+
print(f" Category: {service.category}")
|
|
52
|
+
print(f" Endpoint: {service.endpoint}")
|
|
53
|
+
|
|
54
|
+
# Step 3: Check reputation (if you have previous transactions)
|
|
55
|
+
try:
|
|
56
|
+
reputation = client.get_reputation(wallet.id)
|
|
57
|
+
print(f"\nReputation:")
|
|
58
|
+
print(f" Rating: {reputation.rating}/5")
|
|
59
|
+
print(f" Success Rate: {reputation.success_rate * 100:.1f}%")
|
|
60
|
+
print(f" Total Jobs: {reputation.total_jobs}")
|
|
61
|
+
except Exception as e:
|
|
62
|
+
print(f"\nNo reputation data yet: {e}")
|
|
63
|
+
|
|
64
|
+
# Step 4: Set up webhook to receive notifications
|
|
65
|
+
print("\nRegistering webhook...")
|
|
66
|
+
try:
|
|
67
|
+
webhook = client.register_webhook(
|
|
68
|
+
url="https://my-agent.com/webhooks/agentpay",
|
|
69
|
+
events=[
|
|
70
|
+
"payment.escrowed", # When payment is held in escrow
|
|
71
|
+
"payment.released", # When payment is released to you
|
|
72
|
+
"dispute.opened", # When a dispute is opened
|
|
73
|
+
"service.executed" # When your service is executed
|
|
74
|
+
]
|
|
75
|
+
)
|
|
76
|
+
print(f"โ Webhook registered: {webhook.id}")
|
|
77
|
+
print(f" URL: {webhook.url}")
|
|
78
|
+
print(f" Events: {', '.join(webhook.events)}")
|
|
79
|
+
except Exception as e:
|
|
80
|
+
print(f"โ Webhook registration failed: {e}")
|
|
81
|
+
|
|
82
|
+
print("\n" + "="*60)
|
|
83
|
+
print("Your service is now live on AgentPay!")
|
|
84
|
+
print("="*60)
|
|
85
|
+
print(f"\nService ID: {service.id}")
|
|
86
|
+
print(f"Wallet ID: {wallet.id}")
|
|
87
|
+
print("\nConsumers can now discover and execute your service.")
|
|
88
|
+
print("Make sure your endpoint is accessible and handles POST requests.")
|
|
89
|
+
|
|
90
|
+
# Example: What your endpoint should implement
|
|
91
|
+
print("\n" + "-"*60)
|
|
92
|
+
print("Your service endpoint should implement:")
|
|
93
|
+
print("-"*60)
|
|
94
|
+
print("""
|
|
95
|
+
POST /api/analyze
|
|
96
|
+
Content-Type: application/json
|
|
97
|
+
|
|
98
|
+
{
|
|
99
|
+
"executionId": "exec_123...",
|
|
100
|
+
"paymentId": "pay_456...",
|
|
101
|
+
"input": {
|
|
102
|
+
"text": "Sample text to analyze"
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
Response:
|
|
107
|
+
{
|
|
108
|
+
"status": "success",
|
|
109
|
+
"output": {
|
|
110
|
+
"sentiment": "positive",
|
|
111
|
+
"keywords": ["sample", "text", "analyze"],
|
|
112
|
+
"language": "en"
|
|
113
|
+
},
|
|
114
|
+
"executionTimeMs": 245
|
|
115
|
+
}
|
|
116
|
+
""")
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=61.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "agentspay"
|
|
7
|
+
version = "0.2.0"
|
|
8
|
+
description = "Python SDK for AgentPay - AI agent service marketplace with cryptocurrency payments"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
authors = [
|
|
11
|
+
{name = "AgentsPay", email = "contact@agentspay.io"}
|
|
12
|
+
]
|
|
13
|
+
license = {text = "MIT"}
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 4 - Beta",
|
|
16
|
+
"Intended Audience :: Developers",
|
|
17
|
+
"License :: OSI Approved :: MIT License",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.8",
|
|
20
|
+
"Programming Language :: Python :: 3.9",
|
|
21
|
+
"Programming Language :: Python :: 3.10",
|
|
22
|
+
"Programming Language :: Python :: 3.11",
|
|
23
|
+
"Programming Language :: Python :: 3.12",
|
|
24
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
25
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
26
|
+
"Topic :: Office/Business :: Financial",
|
|
27
|
+
]
|
|
28
|
+
keywords = ["agentpay", "ai", "agents", "cryptocurrency", "bsv", "bitcoin", "payments", "marketplace"]
|
|
29
|
+
requires-python = ">=3.8"
|
|
30
|
+
dependencies = [
|
|
31
|
+
"requests>=2.28.0",
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[project.optional-dependencies]
|
|
35
|
+
dev = [
|
|
36
|
+
"pytest>=7.0.0",
|
|
37
|
+
"pytest-cov>=4.0.0",
|
|
38
|
+
"black>=23.0.0",
|
|
39
|
+
"mypy>=1.0.0",
|
|
40
|
+
"ruff>=0.0.260",
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[project.urls]
|
|
44
|
+
Homepage = "https://github.com/agentspay/agentspay"
|
|
45
|
+
Documentation = "https://docs.agentspay.io"
|
|
46
|
+
Repository = "https://github.com/agentspay/agentspay"
|
|
47
|
+
Issues = "https://github.com/agentspay/agentspay/issues"
|
|
48
|
+
|
|
49
|
+
[tool.setuptools.packages.find]
|
|
50
|
+
where = ["."]
|
|
51
|
+
include = ["agentspay*"]
|
|
52
|
+
|
|
53
|
+
[tool.black]
|
|
54
|
+
line-length = 100
|
|
55
|
+
target-version = ['py38', 'py39', 'py310', 'py311']
|
|
56
|
+
|
|
57
|
+
[tool.mypy]
|
|
58
|
+
python_version = "3.8"
|
|
59
|
+
warn_return_any = true
|
|
60
|
+
warn_unused_configs = true
|
|
61
|
+
disallow_untyped_defs = false
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"""Setup script for agentspay package"""
|
|
2
|
+
|
|
3
|
+
from setuptools import setup, find_packages
|
|
4
|
+
|
|
5
|
+
# Read the long description from README.md
|
|
6
|
+
with open("README.md", "r", encoding="utf-8") as fh:
|
|
7
|
+
long_description = fh.read()
|
|
8
|
+
|
|
9
|
+
setup(
|
|
10
|
+
name="agentspay",
|
|
11
|
+
version="0.2.0",
|
|
12
|
+
author="AgentsPay",
|
|
13
|
+
author_email="contact@agentspay.io",
|
|
14
|
+
description="Python SDK for AgentPay - AI agent service marketplace with cryptocurrency payments",
|
|
15
|
+
long_description=long_description,
|
|
16
|
+
long_description_content_type="text/markdown",
|
|
17
|
+
url="https://github.com/agentspay/agentspay",
|
|
18
|
+
project_urls={
|
|
19
|
+
"Bug Tracker": "https://github.com/agentspay/agentspay/issues",
|
|
20
|
+
"Documentation": "https://docs.agentspay.io",
|
|
21
|
+
"Source Code": "https://github.com/agentspay/agentspay",
|
|
22
|
+
},
|
|
23
|
+
packages=find_packages(exclude=["tests", "tests.*", "examples", "examples.*"]),
|
|
24
|
+
classifiers=[
|
|
25
|
+
"Development Status :: 4 - Beta",
|
|
26
|
+
"Intended Audience :: Developers",
|
|
27
|
+
"License :: OSI Approved :: MIT License",
|
|
28
|
+
"Operating System :: OS Independent",
|
|
29
|
+
"Programming Language :: Python :: 3",
|
|
30
|
+
"Programming Language :: Python :: 3.8",
|
|
31
|
+
"Programming Language :: Python :: 3.9",
|
|
32
|
+
"Programming Language :: Python :: 3.10",
|
|
33
|
+
"Programming Language :: Python :: 3.11",
|
|
34
|
+
"Programming Language :: Python :: 3.12",
|
|
35
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
36
|
+
"Topic :: Internet :: WWW/HTTP",
|
|
37
|
+
"Topic :: Office/Business :: Financial",
|
|
38
|
+
],
|
|
39
|
+
python_requires=">=3.8",
|
|
40
|
+
install_requires=[
|
|
41
|
+
"requests>=2.28.0",
|
|
42
|
+
],
|
|
43
|
+
extras_require={
|
|
44
|
+
"dev": [
|
|
45
|
+
"pytest>=7.0.0",
|
|
46
|
+
"pytest-cov>=4.0.0",
|
|
47
|
+
"black>=23.0.0",
|
|
48
|
+
"mypy>=1.0.0",
|
|
49
|
+
"ruff>=0.0.260",
|
|
50
|
+
],
|
|
51
|
+
},
|
|
52
|
+
keywords="agentpay ai agents cryptocurrency bsv bitcoin payments marketplace",
|
|
53
|
+
)
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
"""Tests for AgentPay SDK"""
|
|
2
|
+
|
|
3
|
+
import pytest
|
|
4
|
+
from unittest.mock import Mock, patch
|
|
5
|
+
from agentspay import AgentPayClient
|
|
6
|
+
from agentspay.exceptions import WalletError, ServiceError, ExecutionError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class TestAgentPayClient:
|
|
10
|
+
"""Test suite for AgentPayClient"""
|
|
11
|
+
|
|
12
|
+
def test_client_initialization(self):
|
|
13
|
+
"""Test client initializes with correct defaults"""
|
|
14
|
+
client = AgentPayClient()
|
|
15
|
+
assert client.base_url == "http://localhost:3100"
|
|
16
|
+
assert client.api_key is None
|
|
17
|
+
|
|
18
|
+
client_with_key = AgentPayClient(
|
|
19
|
+
base_url="https://api.agentspay.io",
|
|
20
|
+
api_key="test-key"
|
|
21
|
+
)
|
|
22
|
+
assert client_with_key.base_url == "https://api.agentspay.io"
|
|
23
|
+
assert client_with_key.api_key == "test-key"
|
|
24
|
+
|
|
25
|
+
@patch('agentspay.wallet.requests.post')
|
|
26
|
+
def test_create_wallet(self, mock_post):
|
|
27
|
+
"""Test wallet creation"""
|
|
28
|
+
# Mock API response
|
|
29
|
+
mock_response = Mock()
|
|
30
|
+
mock_response.json.return_value = {
|
|
31
|
+
"wallet": {
|
|
32
|
+
"id": "wallet_123",
|
|
33
|
+
"publicKey": "pub_key_abc",
|
|
34
|
+
"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
|
|
35
|
+
"createdAt": "2026-02-14T12:00:00Z",
|
|
36
|
+
"balance": 100000,
|
|
37
|
+
"balanceMnee": 5000
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
mock_response.raise_for_status = Mock()
|
|
41
|
+
mock_post.return_value = mock_response
|
|
42
|
+
|
|
43
|
+
# Test
|
|
44
|
+
client = AgentPayClient()
|
|
45
|
+
wallet = client.create_wallet()
|
|
46
|
+
|
|
47
|
+
assert wallet.id == "wallet_123"
|
|
48
|
+
assert wallet.public_key == "pub_key_abc"
|
|
49
|
+
assert wallet.address == "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa"
|
|
50
|
+
assert wallet.balance == 100000
|
|
51
|
+
assert wallet.balance_mnee == 5000
|
|
52
|
+
|
|
53
|
+
@patch('agentspay.wallet.requests.get')
|
|
54
|
+
def test_get_wallet(self, mock_get):
|
|
55
|
+
"""Test getting wallet by ID"""
|
|
56
|
+
# Mock API response
|
|
57
|
+
mock_response = Mock()
|
|
58
|
+
mock_response.json.return_value = {
|
|
59
|
+
"wallet": {
|
|
60
|
+
"id": "wallet_123",
|
|
61
|
+
"publicKey": "pub_key_abc",
|
|
62
|
+
"address": "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa",
|
|
63
|
+
"createdAt": "2026-02-14T12:00:00Z",
|
|
64
|
+
"balance": 50000
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
mock_response.raise_for_status = Mock()
|
|
68
|
+
mock_get.return_value = mock_response
|
|
69
|
+
|
|
70
|
+
# Test
|
|
71
|
+
client = AgentPayClient()
|
|
72
|
+
wallet = client.get_wallet("wallet_123")
|
|
73
|
+
|
|
74
|
+
assert wallet.id == "wallet_123"
|
|
75
|
+
assert wallet.balance == 50000
|
|
76
|
+
|
|
77
|
+
@patch('agentspay.services.requests.post')
|
|
78
|
+
def test_register_service(self, mock_post):
|
|
79
|
+
"""Test service registration"""
|
|
80
|
+
# Mock API response
|
|
81
|
+
mock_response = Mock()
|
|
82
|
+
mock_response.json.return_value = {
|
|
83
|
+
"service": {
|
|
84
|
+
"id": "service_456",
|
|
85
|
+
"agentId": "wallet_123",
|
|
86
|
+
"name": "TextAnalyzer",
|
|
87
|
+
"description": "NLP service",
|
|
88
|
+
"category": "nlp",
|
|
89
|
+
"price": 1000,
|
|
90
|
+
"currency": "BSV",
|
|
91
|
+
"endpoint": "https://agent.com/analyze",
|
|
92
|
+
"method": "POST",
|
|
93
|
+
"active": True,
|
|
94
|
+
"timeout": 30,
|
|
95
|
+
"disputeWindow": 30,
|
|
96
|
+
"createdAt": "2026-02-14T12:00:00Z",
|
|
97
|
+
"updatedAt": "2026-02-14T12:00:00Z"
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
mock_response.raise_for_status = Mock()
|
|
101
|
+
mock_post.return_value = mock_response
|
|
102
|
+
|
|
103
|
+
# Test
|
|
104
|
+
client = AgentPayClient()
|
|
105
|
+
service = client.register_service(
|
|
106
|
+
agent_id="wallet_123",
|
|
107
|
+
name="TextAnalyzer",
|
|
108
|
+
description="NLP service",
|
|
109
|
+
price=1000,
|
|
110
|
+
currency="BSV",
|
|
111
|
+
endpoint="https://agent.com/analyze",
|
|
112
|
+
category="nlp"
|
|
113
|
+
)
|
|
114
|
+
|
|
115
|
+
assert service.id == "service_456"
|
|
116
|
+
assert service.name == "TextAnalyzer"
|
|
117
|
+
assert service.price == 1000
|
|
118
|
+
assert service.currency == "BSV"
|
|
119
|
+
assert service.active is True
|
|
120
|
+
|
|
121
|
+
@patch('agentspay.services.requests.get')
|
|
122
|
+
def test_search_services(self, mock_get):
|
|
123
|
+
"""Test searching for services"""
|
|
124
|
+
# Mock API response
|
|
125
|
+
mock_response = Mock()
|
|
126
|
+
mock_response.json.return_value = {
|
|
127
|
+
"services": [
|
|
128
|
+
{
|
|
129
|
+
"id": "service_1",
|
|
130
|
+
"agentId": "wallet_1",
|
|
131
|
+
"name": "Service 1",
|
|
132
|
+
"description": "Test service",
|
|
133
|
+
"category": "nlp",
|
|
134
|
+
"price": 500,
|
|
135
|
+
"currency": "BSV",
|
|
136
|
+
"endpoint": "https://agent.com/1",
|
|
137
|
+
"method": "POST",
|
|
138
|
+
"active": True,
|
|
139
|
+
"timeout": 30,
|
|
140
|
+
"disputeWindow": 30,
|
|
141
|
+
"createdAt": "2026-02-14T12:00:00Z",
|
|
142
|
+
"updatedAt": "2026-02-14T12:00:00Z"
|
|
143
|
+
}
|
|
144
|
+
]
|
|
145
|
+
}
|
|
146
|
+
mock_response.raise_for_status = Mock()
|
|
147
|
+
mock_get.return_value = mock_response
|
|
148
|
+
|
|
149
|
+
# Test
|
|
150
|
+
client = AgentPayClient()
|
|
151
|
+
services = client.search_services(keyword="nlp", max_price=1000)
|
|
152
|
+
|
|
153
|
+
assert len(services) == 1
|
|
154
|
+
assert services[0].id == "service_1"
|
|
155
|
+
assert services[0].category == "nlp"
|
|
156
|
+
|
|
157
|
+
@patch('agentspay.payments.requests.post')
|
|
158
|
+
def test_execute_service(self, mock_post):
|
|
159
|
+
"""Test service execution"""
|
|
160
|
+
# Mock API response
|
|
161
|
+
mock_response = Mock()
|
|
162
|
+
mock_response.json.return_value = {
|
|
163
|
+
"paymentId": "payment_789",
|
|
164
|
+
"serviceId": "service_456",
|
|
165
|
+
"output": {
|
|
166
|
+
"result": "success",
|
|
167
|
+
"data": "analyzed"
|
|
168
|
+
},
|
|
169
|
+
"executionTimeMs": 250,
|
|
170
|
+
"status": "success"
|
|
171
|
+
}
|
|
172
|
+
mock_response.raise_for_status = Mock()
|
|
173
|
+
mock_post.return_value = mock_response
|
|
174
|
+
|
|
175
|
+
# Test
|
|
176
|
+
client = AgentPayClient()
|
|
177
|
+
result = client.execute(
|
|
178
|
+
service_id="service_456",
|
|
179
|
+
buyer_wallet_id="wallet_123",
|
|
180
|
+
input_data={"text": "Test"}
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
assert result.payment_id == "payment_789"
|
|
184
|
+
assert result.service_id == "service_456"
|
|
185
|
+
assert result.status == "success"
|
|
186
|
+
assert result.execution_time_ms == 250
|
|
187
|
+
assert result.output["result"] == "success"
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class TestExceptions:
|
|
191
|
+
"""Test SDK exceptions"""
|
|
192
|
+
|
|
193
|
+
@patch('agentspay.wallet.requests.post')
|
|
194
|
+
def test_wallet_error(self, mock_post):
|
|
195
|
+
"""Test WalletError is raised on API failure"""
|
|
196
|
+
mock_post.side_effect = Exception("Network error")
|
|
197
|
+
|
|
198
|
+
client = AgentPayClient()
|
|
199
|
+
with pytest.raises(WalletError):
|
|
200
|
+
client.create_wallet()
|
|
201
|
+
|
|
202
|
+
@patch('agentspay.services.requests.post')
|
|
203
|
+
def test_service_error(self, mock_post):
|
|
204
|
+
"""Test ServiceError is raised on API failure"""
|
|
205
|
+
mock_post.side_effect = Exception("API error")
|
|
206
|
+
|
|
207
|
+
client = AgentPayClient()
|
|
208
|
+
with pytest.raises(ServiceError):
|
|
209
|
+
client.register_service(
|
|
210
|
+
agent_id="wallet_123",
|
|
211
|
+
name="Test",
|
|
212
|
+
description="Test",
|
|
213
|
+
price=100,
|
|
214
|
+
currency="BSV",
|
|
215
|
+
endpoint="https://test.com",
|
|
216
|
+
category="test"
|
|
217
|
+
)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
if __name__ == "__main__":
|
|
221
|
+
pytest.main([__file__, "-v"])
|
package/test-addr.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
const { PrivateKey, Hash, Utils } = require('@bsv/sdk')
|
|
2
|
+
const crypto = require('crypto')
|
|
3
|
+
|
|
4
|
+
const pk = PrivateKey.fromRandom()
|
|
5
|
+
const pub = pk.toPublicKey()
|
|
6
|
+
|
|
7
|
+
// Mainnet
|
|
8
|
+
console.log('Mainnet:', pub.toAddress())
|
|
9
|
+
|
|
10
|
+
// Testnet - manual P2PKH with 0x6f prefix
|
|
11
|
+
const pubEncoded = pub.encode(true)
|
|
12
|
+
const hash160 = Hash.hash160(pubEncoded)
|
|
13
|
+
const prefix = Uint8Array.from([0x6f])
|
|
14
|
+
const payload = new Uint8Array(prefix.length + hash160.length)
|
|
15
|
+
payload.set(prefix, 0)
|
|
16
|
+
payload.set(hash160, prefix.length)
|
|
17
|
+
const checksum = Hash.hash256(payload).slice(0, 4)
|
|
18
|
+
const full = new Uint8Array(payload.length + checksum.length)
|
|
19
|
+
full.set(payload, 0)
|
|
20
|
+
full.set(checksum, payload.length)
|
|
21
|
+
console.log('Testnet:', Utils.toBase58(full))
|
|
22
|
+
console.log('WIF:', pk.toWif())
|
|
23
|
+
|
|
24
|
+
// Also check toAddress with network param
|
|
25
|
+
try {
|
|
26
|
+
console.log('toAddress testnet:', pub.toAddress('testnet'))
|
|
27
|
+
} catch(e) {
|
|
28
|
+
console.log('toAddress testnet not supported:', e.message)
|
|
29
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
// Simple MNEE test without database
|
|
2
|
+
const { CurrencyManager } = require('./dist/currency/currency')
|
|
3
|
+
|
|
4
|
+
async function test() {
|
|
5
|
+
console.log('๐งช Testing MNEE Currency Manager\n')
|
|
6
|
+
|
|
7
|
+
console.log('โ
Currency Configuration:')
|
|
8
|
+
console.log(' BSV:', JSON.stringify(CurrencyManager.getConfig('BSV'), null, 2))
|
|
9
|
+
console.log(' MNEE:', JSON.stringify(CurrencyManager.getConfig('MNEE'), null, 2))
|
|
10
|
+
|
|
11
|
+
console.log('\nโ
Amount Validation:')
|
|
12
|
+
console.log(' 1000 sats (BSV):', CurrencyManager.validateAmount(1000, 'BSV'))
|
|
13
|
+
console.log(' 150 cents (MNEE):', CurrencyManager.validateAmount(150, 'MNEE'))
|
|
14
|
+
console.log(' -10 cents (MNEE):', CurrencyManager.validateAmount(-10, 'MNEE'))
|
|
15
|
+
console.log(' 0.5 cents (MNEE):', CurrencyManager.validateAmount(0.5, 'MNEE'))
|
|
16
|
+
|
|
17
|
+
console.log('\nโ
Formatting:')
|
|
18
|
+
console.log(' 50000000 sats โ', CurrencyManager.format(50000000, 'BSV'))
|
|
19
|
+
console.log(' 1000 sats โ', CurrencyManager.format(1000, 'BSV'))
|
|
20
|
+
console.log(' 150 cents โ', CurrencyManager.format(150, 'MNEE'))
|
|
21
|
+
console.log(' 5000 cents โ', CurrencyManager.format(5000, 'MNEE'))
|
|
22
|
+
console.log(' 1 cent โ', CurrencyManager.format(1, 'MNEE'))
|
|
23
|
+
|
|
24
|
+
console.log('\nโ
Fee Calculation (2%):')
|
|
25
|
+
console.log(' 10000 sats BSV fee:', CurrencyManager.calculateFee(10000, 'BSV'), 'sats')
|
|
26
|
+
console.log(' 1000 cents MNEE fee:', CurrencyManager.calculateFee(1000, 'MNEE'), 'cents ($0.20)')
|
|
27
|
+
console.log(' 100 cents MNEE fee:', CurrencyManager.calculateFee(100, 'MNEE'), 'cents ($0.02)')
|
|
28
|
+
console.log(' 10 cents MNEE fee:', CurrencyManager.calculateFee(10, 'MNEE'), 'cents (min 1 cent)')
|
|
29
|
+
|
|
30
|
+
console.log('\nโ
Parsing:')
|
|
31
|
+
console.log(' "1.50 MNEE" โ', CurrencyManager.parse('1.50 MNEE', 'MNEE'), 'cents')
|
|
32
|
+
console.log(' "0.00001 BSV" โ', CurrencyManager.parse('0.00001 BSV', 'BSV'), 'sats')
|
|
33
|
+
console.log(' "100.00" MNEE โ', CurrencyManager.parse('100.00', 'MNEE'), 'cents')
|
|
34
|
+
|
|
35
|
+
console.log('\nโ
Conversion Rates:')
|
|
36
|
+
const bsvToMnee = await CurrencyManager.getConversionRate('BSV', 'MNEE')
|
|
37
|
+
const mneeToBsv = await CurrencyManager.getConversionRate('MNEE', 'BSV')
|
|
38
|
+
console.log(' 1 sat =', bsvToMnee.rate.toFixed(6), 'MNEE cents')
|
|
39
|
+
console.log(' 1 MNEE cent =', mneeToBsv.rate.toFixed(2), 'sats')
|
|
40
|
+
console.log(' Source:', bsvToMnee.source)
|
|
41
|
+
|
|
42
|
+
console.log('\nโ
Conversion Examples:')
|
|
43
|
+
const satsToCents = await CurrencyManager.convert(10000, 'BSV', 'MNEE')
|
|
44
|
+
console.log(' 10000 sats โ', satsToCents, 'cents ($' + (satsToCents/100).toFixed(2) + ')')
|
|
45
|
+
const centsToSats = await CurrencyManager.convert(100, 'MNEE', 'BSV')
|
|
46
|
+
console.log(' 100 cents ($1) โ', centsToSats, 'sats')
|
|
47
|
+
|
|
48
|
+
console.log('\n๐ All currency manager tests passed!')
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
test().catch(console.error)
|