agentsync-sdk 1.0.0__tar.gz
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.
- agentsync_sdk-1.0.0/PKG-INFO +68 -0
- agentsync_sdk-1.0.0/README.md +46 -0
- agentsync_sdk-1.0.0/agentsync/__init__.py +88 -0
- agentsync_sdk-1.0.0/agentsync/attestation.py +89 -0
- agentsync_sdk-1.0.0/agentsync/client.py +565 -0
- agentsync_sdk-1.0.0/agentsync/errors.py +50 -0
- agentsync_sdk-1.0.0/agentsync/rap.py +165 -0
- agentsync_sdk-1.0.0/agentsync/types.py +328 -0
- agentsync_sdk-1.0.0/agentsync_sdk.egg-info/PKG-INFO +68 -0
- agentsync_sdk-1.0.0/agentsync_sdk.egg-info/SOURCES.txt +15 -0
- agentsync_sdk-1.0.0/agentsync_sdk.egg-info/dependency_links.txt +1 -0
- agentsync_sdk-1.0.0/agentsync_sdk.egg-info/requires.txt +7 -0
- agentsync_sdk-1.0.0/agentsync_sdk.egg-info/top_level.txt +2 -0
- agentsync_sdk-1.0.0/pyproject.toml +40 -0
- agentsync_sdk-1.0.0/setup.cfg +4 -0
- agentsync_sdk-1.0.0/tests/test_attestation.py +89 -0
- agentsync_sdk-1.0.0/tests/test_sdk.py +726 -0
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: agentsync-sdk
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Python SDK for the AgentSync x402 micropayment gateway on Radix
|
|
5
|
+
License: MIT
|
|
6
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
7
|
+
Classifier: Intended Audience :: Developers
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Programming Language :: Python :: 3
|
|
11
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
12
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
13
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
14
|
+
Requires-Python: >=3.10
|
|
15
|
+
Description-Content-Type: text/markdown
|
|
16
|
+
Requires-Dist: httpx>=0.27.0
|
|
17
|
+
Requires-Dist: PyNaCl>=1.5.0
|
|
18
|
+
Provides-Extra: dev
|
|
19
|
+
Requires-Dist: pytest>=8.0; extra == "dev"
|
|
20
|
+
Requires-Dist: pytest-asyncio>=0.23.0; extra == "dev"
|
|
21
|
+
Requires-Dist: pytest-httpx>=0.30.0; extra == "dev"
|
|
22
|
+
|
|
23
|
+
# AgentSync Python SDK
|
|
24
|
+
|
|
25
|
+
Python SDK for the AgentSync x402 micropayment gateway on Radix.
|
|
26
|
+
|
|
27
|
+
## Install
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
pip install agentsync-sdk
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
> Note: the distribution name is `agentsync-sdk`; the import package remains
|
|
34
|
+
> `agentsync` (`from agentsync import ...`). For local development use
|
|
35
|
+
> `pip install -e .` in the repo.
|
|
36
|
+
|
|
37
|
+
## Development
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install -e ".[dev]"
|
|
41
|
+
pytest
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Platform Attestation Verification
|
|
45
|
+
|
|
46
|
+
Verify a platform-signed attestation envelope against the trusted platform
|
|
47
|
+
Ed25519 public key:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
from agentsync import SignatureEnvelope, verify_platform_attestation
|
|
51
|
+
|
|
52
|
+
trusted_public_key = "9afcc1cf66b256d7d9567a906fba4317305d92c3e7fd7f27386dffe182332576"
|
|
53
|
+
envelope = SignatureEnvelope(
|
|
54
|
+
payload="account_tdx_2_...:5.500000:0",
|
|
55
|
+
signature="<128-char hex>",
|
|
56
|
+
public_key=trusted_public_key,
|
|
57
|
+
algorithm="ed25519+sha256",
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
valid = verify_platform_attestation(envelope, trusted_public_key) # bool
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
`verify_platform_attestation()` is pure and synchronous: the trusted key is
|
|
64
|
+
injected by the caller and never fetched from the network. It asserts that the
|
|
65
|
+
envelope's `public_key` matches the trusted key before verifying the
|
|
66
|
+
`Ed25519(SHA-256(payload))` signature.
|
|
67
|
+
|
|
68
|
+
The TypeScript counterpart lives at [`../sdk-typescript`](../sdk-typescript).
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# AgentSync Python SDK
|
|
2
|
+
|
|
3
|
+
Python SDK for the AgentSync x402 micropayment gateway on Radix.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install agentsync-sdk
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
> Note: the distribution name is `agentsync-sdk`; the import package remains
|
|
12
|
+
> `agentsync` (`from agentsync import ...`). For local development use
|
|
13
|
+
> `pip install -e .` in the repo.
|
|
14
|
+
|
|
15
|
+
## Development
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
pip install -e ".[dev]"
|
|
19
|
+
pytest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Platform Attestation Verification
|
|
23
|
+
|
|
24
|
+
Verify a platform-signed attestation envelope against the trusted platform
|
|
25
|
+
Ed25519 public key:
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
from agentsync import SignatureEnvelope, verify_platform_attestation
|
|
29
|
+
|
|
30
|
+
trusted_public_key = "9afcc1cf66b256d7d9567a906fba4317305d92c3e7fd7f27386dffe182332576"
|
|
31
|
+
envelope = SignatureEnvelope(
|
|
32
|
+
payload="account_tdx_2_...:5.500000:0",
|
|
33
|
+
signature="<128-char hex>",
|
|
34
|
+
public_key=trusted_public_key,
|
|
35
|
+
algorithm="ed25519+sha256",
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
valid = verify_platform_attestation(envelope, trusted_public_key) # bool
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
`verify_platform_attestation()` is pure and synchronous: the trusted key is
|
|
42
|
+
injected by the caller and never fetched from the network. It asserts that the
|
|
43
|
+
envelope's `public_key` matches the trusted key before verifying the
|
|
44
|
+
`Ed25519(SHA-256(payload))` signature.
|
|
45
|
+
|
|
46
|
+
The TypeScript counterpart lives at [`../sdk-typescript`](../sdk-typescript).
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"""
|
|
2
|
+
AgentSync Python SDK.
|
|
3
|
+
|
|
4
|
+
Idiomatic Python client for the AgentSync x402 micropayment gateway
|
|
5
|
+
on the Radix ledger. Supports ROLA authentication, Mode A (credit
|
|
6
|
+
buffer), Mode B (single-pay), and Mode C (RAP/1 bundled non-custodial
|
|
7
|
+
on-chain settlement), plus catalog discovery and withdrawal attestation.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from .attestation import SignatureEnvelope, verify_platform_attestation
|
|
11
|
+
from .client import AgentSyncClient, CatalogModule, set_default_registry_component
|
|
12
|
+
from .errors import AuthenticationError, GatewayError, InsufficientCreditError
|
|
13
|
+
from .rap import generate_composite_manifest, generate_rap_manifest
|
|
14
|
+
from .types import (
|
|
15
|
+
AgentSyncClientOptions,
|
|
16
|
+
AgentSyncFetchOptions,
|
|
17
|
+
AuthChallengeResponse,
|
|
18
|
+
AuthVerifyResponse,
|
|
19
|
+
CatalogEntry,
|
|
20
|
+
CatalogResponse,
|
|
21
|
+
CompositeManifestConfig,
|
|
22
|
+
CompositePurchase,
|
|
23
|
+
InsufficientCreditPayload,
|
|
24
|
+
PremiumDataResponse,
|
|
25
|
+
RadixAccountAddress,
|
|
26
|
+
RapManifestConfig,
|
|
27
|
+
RapPublicKey,
|
|
28
|
+
RapSignatureValue,
|
|
29
|
+
RapHash,
|
|
30
|
+
RapRootManifest,
|
|
31
|
+
RapNotary,
|
|
32
|
+
RapDraftInputs,
|
|
33
|
+
RapEconomicParams,
|
|
34
|
+
RapSignatureFile,
|
|
35
|
+
RapPayload,
|
|
36
|
+
RolaSigner,
|
|
37
|
+
SessionDebitEntry,
|
|
38
|
+
SessionSummary,
|
|
39
|
+
SettleResponse,
|
|
40
|
+
WithdrawalPayload,
|
|
41
|
+
WithdrawResponse,
|
|
42
|
+
UsdcDecimal,
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
__all__ = [
|
|
46
|
+
# Client
|
|
47
|
+
"AgentSyncClient",
|
|
48
|
+
"CatalogModule",
|
|
49
|
+
"set_default_registry_component",
|
|
50
|
+
# Standalone functions
|
|
51
|
+
"generate_composite_manifest",
|
|
52
|
+
"generate_rap_manifest",
|
|
53
|
+
"verify_platform_attestation",
|
|
54
|
+
# Errors
|
|
55
|
+
"AuthenticationError",
|
|
56
|
+
"GatewayError",
|
|
57
|
+
"InsufficientCreditError",
|
|
58
|
+
# Types
|
|
59
|
+
"AgentSyncClientOptions",
|
|
60
|
+
"AgentSyncFetchOptions",
|
|
61
|
+
"AuthChallengeResponse",
|
|
62
|
+
"AuthVerifyResponse",
|
|
63
|
+
"CatalogEntry",
|
|
64
|
+
"CatalogResponse",
|
|
65
|
+
"CompositeManifestConfig",
|
|
66
|
+
"CompositePurchase",
|
|
67
|
+
"InsufficientCreditPayload",
|
|
68
|
+
"PremiumDataResponse",
|
|
69
|
+
"RadixAccountAddress",
|
|
70
|
+
"RapManifestConfig",
|
|
71
|
+
"RapPublicKey",
|
|
72
|
+
"RapSignatureValue",
|
|
73
|
+
"RapHash",
|
|
74
|
+
"RapRootManifest",
|
|
75
|
+
"RapNotary",
|
|
76
|
+
"RapDraftInputs",
|
|
77
|
+
"RapEconomicParams",
|
|
78
|
+
"RapSignatureFile",
|
|
79
|
+
"RapPayload",
|
|
80
|
+
"RolaSigner",
|
|
81
|
+
"SessionDebitEntry",
|
|
82
|
+
"SessionSummary",
|
|
83
|
+
"SettleResponse",
|
|
84
|
+
"SignatureEnvelope",
|
|
85
|
+
"WithdrawalPayload",
|
|
86
|
+
"WithdrawResponse",
|
|
87
|
+
"UsdcDecimal",
|
|
88
|
+
]
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Platform attestation verification for AgentSync.
|
|
3
|
+
|
|
4
|
+
Verifies the Ed25519 signature over the SHA-256 pre-hash of an attestation
|
|
5
|
+
payload, mirroring the platform signing path in ``worker/src/attestation.ts``.
|
|
6
|
+
|
|
7
|
+
Signature scheme: SHA-256 pre-hash → Ed25519 verify (matches Scrypto's
|
|
8
|
+
``verify_ed25519`` convention where messages are hashed before verifying).
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
from __future__ import annotations
|
|
12
|
+
|
|
13
|
+
import hashlib
|
|
14
|
+
import hmac
|
|
15
|
+
from dataclasses import dataclass
|
|
16
|
+
|
|
17
|
+
from nacl.exceptions import BadSignatureError
|
|
18
|
+
from nacl.signing import VerifyKey
|
|
19
|
+
|
|
20
|
+
SUPPORTED_ALGORITHM = "ed25519+sha256"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
@dataclass(frozen=True)
|
|
24
|
+
class SignatureEnvelope:
|
|
25
|
+
"""Attestation envelope produced by the platform."""
|
|
26
|
+
|
|
27
|
+
payload: str
|
|
28
|
+
signature: str
|
|
29
|
+
public_key: str
|
|
30
|
+
algorithm: str
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
def verify_platform_attestation(
|
|
34
|
+
envelope: SignatureEnvelope,
|
|
35
|
+
trusted_public_key: str,
|
|
36
|
+
) -> bool:
|
|
37
|
+
"""Verify a platform attestation envelope against the trusted platform key.
|
|
38
|
+
|
|
39
|
+
The function is pure and synchronous: the trusted public key is injected by
|
|
40
|
+
the caller, never fetched from the network. To prevent tautological spoofing
|
|
41
|
+
(an attacker signing a tampered payload with their own key), the envelope's
|
|
42
|
+
``public_key`` must match ``trusted_public_key`` before any signature check.
|
|
43
|
+
|
|
44
|
+
Args:
|
|
45
|
+
envelope: Attestation envelope (payload, signature, public key,
|
|
46
|
+
algorithm) produced by the platform.
|
|
47
|
+
trusted_public_key: Hex-encoded 32-byte Ed25519 public key the caller
|
|
48
|
+
has independently verified as the platform's key.
|
|
49
|
+
|
|
50
|
+
Returns:
|
|
51
|
+
``True`` if the algorithm is supported, the embedded key matches the
|
|
52
|
+
trusted key, and the signature verifies over ``SHA-256(payload)``.
|
|
53
|
+
"""
|
|
54
|
+
if envelope.algorithm != SUPPORTED_ALGORITHM:
|
|
55
|
+
return False
|
|
56
|
+
|
|
57
|
+
if not _constant_time_hex_equals(envelope.public_key, trusted_public_key):
|
|
58
|
+
return False
|
|
59
|
+
|
|
60
|
+
public_key = _hex_to_bytes(trusted_public_key)
|
|
61
|
+
signature = _hex_to_bytes(envelope.signature)
|
|
62
|
+
if public_key is None or signature is None:
|
|
63
|
+
return False
|
|
64
|
+
if len(public_key) != 32 or len(signature) != 64:
|
|
65
|
+
return False
|
|
66
|
+
|
|
67
|
+
# SHA-256 pre-hash — matches the platform's Ed25519(SHA-256(payload)) scheme.
|
|
68
|
+
message_hash = hashlib.sha256(envelope.payload.encode("utf-8")).digest()
|
|
69
|
+
|
|
70
|
+
try:
|
|
71
|
+
VerifyKey(public_key).verify(message_hash, signature)
|
|
72
|
+
return True
|
|
73
|
+
except (BadSignatureError, ValueError):
|
|
74
|
+
return False
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _hex_to_bytes(value: str) -> bytes | None:
|
|
78
|
+
"""Decode a hex string to bytes, returning ``None`` on malformed input."""
|
|
79
|
+
try:
|
|
80
|
+
return bytes.fromhex(value)
|
|
81
|
+
except ValueError:
|
|
82
|
+
return None
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
def _constant_time_hex_equals(a: str, b: str) -> bool:
|
|
86
|
+
"""Compare two hex strings in constant time."""
|
|
87
|
+
if len(a) != len(b):
|
|
88
|
+
return False
|
|
89
|
+
return hmac.compare_digest(a.encode("utf-8"), b.encode("utf-8"))
|