uvd-x402-sdk 0.3.3__tar.gz → 0.4.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.
- {uvd_x402_sdk-0.3.3/src/uvd_x402_sdk.egg-info → uvd_x402_sdk-0.4.0}/PKG-INFO +10 -4
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/README.md +7 -1
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/pyproject.toml +3 -2
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/__init__.py +1 -1
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/networks/__init__.py +3 -2
- uvd_x402_sdk-0.4.0/src/uvd_x402_sdk/networks/algorand.py +287 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/networks/base.py +14 -2
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/networks/evm.py +38 -3
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0/src/uvd_x402_sdk.egg-info}/PKG-INFO +10 -4
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk.egg-info/SOURCES.txt +1 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/LICENSE +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/setup.cfg +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/client.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/config.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/decorators.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/exceptions.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/__init__.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/django_integration.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/fastapi_integration.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/flask_integration.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/lambda_integration.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/models.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/networks/near.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/networks/solana.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/networks/stellar.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/response.py +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk.egg-info/dependency_links.txt +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk.egg-info/requires.txt +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk.egg-info/top_level.txt +0 -0
- {uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/tests/test_client.py +0 -0
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: uvd-x402-sdk
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Python SDK for x402 payments - gasless crypto payments across
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Python SDK for x402 payments - gasless crypto payments across 16 blockchains with multi-stablecoin support (USDC, EURC, AUSD, PYUSD, USDT)
|
|
5
5
|
Author-email: Ultravioleta DAO <dev@ultravioletadao.xyz>
|
|
6
6
|
Project-URL: Homepage, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
|
|
7
7
|
Project-URL: Documentation, https://docs.ultravioletadao.xyz/x402-sdk
|
|
8
8
|
Project-URL: Repository, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
|
|
9
9
|
Project-URL: Issues, https://github.com/UltravioletaDAO/uvd-x402-sdk-python/issues
|
|
10
|
-
Keywords: x402,payments,crypto,usdc,eurc,stablecoin,web3,evm,solana,near,stellar,facilitator,gasless,eip-712,eip-3009
|
|
10
|
+
Keywords: x402,payments,crypto,usdc,eurc,stablecoin,web3,evm,solana,near,stellar,algorand,facilitator,gasless,eip-712,eip-3009
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -56,7 +56,7 @@ Accept **gasless stablecoin payments** across **14 blockchain networks** with a
|
|
|
56
56
|
## Features
|
|
57
57
|
|
|
58
58
|
- **14 Networks**: EVM chains (Base, Ethereum, Polygon, etc.), SVM chains (Solana, Fogo), NEAR, and Stellar
|
|
59
|
-
- **
|
|
59
|
+
- **5 Stablecoins**: USDC, EURC, AUSD, PYUSD, USDT (EVM chains)
|
|
60
60
|
- **x402 v1 & v2**: Full support for both protocol versions with auto-detection
|
|
61
61
|
- **Framework Integrations**: Flask, FastAPI, Django, AWS Lambda
|
|
62
62
|
- **Gasless Payments**: Users sign EIP-712/EIP-3009 authorizations, facilitator pays all network fees
|
|
@@ -102,6 +102,7 @@ print(f"Paid by {result.payer_address}, tx: {result.transaction_hash}")
|
|
|
102
102
|
| EURC | Ethereum, Base, Avalanche | 6 |
|
|
103
103
|
| AUSD | Ethereum, Arbitrum, Avalanche, Polygon, Monad | 6 |
|
|
104
104
|
| PYUSD | Ethereum | 6 |
|
|
105
|
+
| USDT | Ethereum, Arbitrum, Optimism, Avalanche, Polygon | 6 |
|
|
105
106
|
|
|
106
107
|
## Installation
|
|
107
108
|
|
|
@@ -926,6 +927,11 @@ MIT License - see LICENSE file.
|
|
|
926
927
|
|
|
927
928
|
## Changelog
|
|
928
929
|
|
|
930
|
+
### v0.3.4 (2025-12-22)
|
|
931
|
+
|
|
932
|
+
- Added USDT support (USDT0 omnichain via LayerZero) on Ethereum, Arbitrum, Optimism, Avalanche, Polygon
|
|
933
|
+
- SDK now supports 5 stablecoins: USDC, EURC, AUSD, PYUSD, USDT
|
|
934
|
+
|
|
929
935
|
### v0.3.3 (2025-12-22)
|
|
930
936
|
|
|
931
937
|
- Fixed EIP-712 domain names: AUSD uses "Agora Dollar" (not "Agora USD")
|
|
@@ -7,7 +7,7 @@ Accept **gasless stablecoin payments** across **14 blockchain networks** with a
|
|
|
7
7
|
## Features
|
|
8
8
|
|
|
9
9
|
- **14 Networks**: EVM chains (Base, Ethereum, Polygon, etc.), SVM chains (Solana, Fogo), NEAR, and Stellar
|
|
10
|
-
- **
|
|
10
|
+
- **5 Stablecoins**: USDC, EURC, AUSD, PYUSD, USDT (EVM chains)
|
|
11
11
|
- **x402 v1 & v2**: Full support for both protocol versions with auto-detection
|
|
12
12
|
- **Framework Integrations**: Flask, FastAPI, Django, AWS Lambda
|
|
13
13
|
- **Gasless Payments**: Users sign EIP-712/EIP-3009 authorizations, facilitator pays all network fees
|
|
@@ -53,6 +53,7 @@ print(f"Paid by {result.payer_address}, tx: {result.transaction_hash}")
|
|
|
53
53
|
| EURC | Ethereum, Base, Avalanche | 6 |
|
|
54
54
|
| AUSD | Ethereum, Arbitrum, Avalanche, Polygon, Monad | 6 |
|
|
55
55
|
| PYUSD | Ethereum | 6 |
|
|
56
|
+
| USDT | Ethereum, Arbitrum, Optimism, Avalanche, Polygon | 6 |
|
|
56
57
|
|
|
57
58
|
## Installation
|
|
58
59
|
|
|
@@ -877,6 +878,11 @@ MIT License - see LICENSE file.
|
|
|
877
878
|
|
|
878
879
|
## Changelog
|
|
879
880
|
|
|
881
|
+
### v0.3.4 (2025-12-22)
|
|
882
|
+
|
|
883
|
+
- Added USDT support (USDT0 omnichain via LayerZero) on Ethereum, Arbitrum, Optimism, Avalanche, Polygon
|
|
884
|
+
- SDK now supports 5 stablecoins: USDC, EURC, AUSD, PYUSD, USDT
|
|
885
|
+
|
|
880
886
|
### v0.3.3 (2025-12-22)
|
|
881
887
|
|
|
882
888
|
- Fixed EIP-712 domain names: AUSD uses "Agora Dollar" (not "Agora USD")
|
|
@@ -4,8 +4,8 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "uvd-x402-sdk"
|
|
7
|
-
version = "0.
|
|
8
|
-
description = "Python SDK for x402 payments - gasless crypto payments across
|
|
7
|
+
version = "0.4.0"
|
|
8
|
+
description = "Python SDK for x402 payments - gasless crypto payments across 16 blockchains with multi-stablecoin support (USDC, EURC, AUSD, PYUSD, USDT)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.9"
|
|
11
11
|
authors = [
|
|
@@ -23,6 +23,7 @@ keywords = [
|
|
|
23
23
|
"solana",
|
|
24
24
|
"near",
|
|
25
25
|
"stellar",
|
|
26
|
+
"algorand",
|
|
26
27
|
"facilitator",
|
|
27
28
|
"gasless",
|
|
28
29
|
"eip-712",
|
|
@@ -4,12 +4,13 @@ Network configurations for x402 payments.
|
|
|
4
4
|
This module provides configuration for all supported blockchain networks,
|
|
5
5
|
including USDC contract addresses, RPC URLs, and network-specific parameters.
|
|
6
6
|
|
|
7
|
-
The SDK supports
|
|
7
|
+
The SDK supports 16 mainnet networks out of the box:
|
|
8
8
|
- 10 EVM chains: Base, Ethereum, Polygon, Arbitrum, Optimism, Avalanche,
|
|
9
9
|
Celo, HyperEVM, Unichain, Monad
|
|
10
10
|
- 2 SVM chains: Solana, Fogo
|
|
11
11
|
- 1 NEAR: NEAR Protocol
|
|
12
12
|
- 1 Stellar: Stellar
|
|
13
|
+
- 2 Algorand: Algorand mainnet and testnet
|
|
13
14
|
|
|
14
15
|
Multi-token support (EVM chains only):
|
|
15
16
|
- USDC: All chains
|
|
@@ -47,7 +48,7 @@ from uvd_x402_sdk.networks.base import (
|
|
|
47
48
|
)
|
|
48
49
|
|
|
49
50
|
# Import all default network configurations
|
|
50
|
-
from uvd_x402_sdk.networks import evm, solana, near, stellar
|
|
51
|
+
from uvd_x402_sdk.networks import evm, solana, near, stellar, algorand
|
|
51
52
|
|
|
52
53
|
__all__ = [
|
|
53
54
|
# Core
|
|
@@ -0,0 +1,287 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Algorand network configurations.
|
|
3
|
+
|
|
4
|
+
This module supports Algorand blockchain networks:
|
|
5
|
+
- Algorand mainnet
|
|
6
|
+
- Algorand testnet
|
|
7
|
+
|
|
8
|
+
Algorand uses ASA (Algorand Standard Assets) for USDC:
|
|
9
|
+
- Mainnet USDC ASA ID: 31566704
|
|
10
|
+
- Testnet USDC ASA ID: 10458941
|
|
11
|
+
|
|
12
|
+
Payment Flow:
|
|
13
|
+
1. User creates a signed ASA transfer transaction via Pera Wallet
|
|
14
|
+
2. Transaction transfers USDC from user to recipient
|
|
15
|
+
3. Facilitator submits the pre-signed transaction on-chain
|
|
16
|
+
4. User pays ZERO transaction fees (facilitator covers fees)
|
|
17
|
+
|
|
18
|
+
Transaction Structure:
|
|
19
|
+
- ASA TransferAsset transaction
|
|
20
|
+
- Signed by user wallet (Pera Wallet)
|
|
21
|
+
- Facilitator submits the signed transaction
|
|
22
|
+
|
|
23
|
+
Address Format:
|
|
24
|
+
- Algorand addresses are 58 characters, base32 encoded
|
|
25
|
+
- Example: AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAY5HFKQ
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
import base64
|
|
29
|
+
import re
|
|
30
|
+
from typing import Any, Dict, Optional
|
|
31
|
+
|
|
32
|
+
from uvd_x402_sdk.networks.base import (
|
|
33
|
+
NetworkConfig,
|
|
34
|
+
NetworkType,
|
|
35
|
+
register_network,
|
|
36
|
+
)
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
# =============================================================================
|
|
40
|
+
# Algorand Networks Configuration
|
|
41
|
+
# =============================================================================
|
|
42
|
+
|
|
43
|
+
# Algorand Mainnet
|
|
44
|
+
ALGORAND = NetworkConfig(
|
|
45
|
+
name="algorand",
|
|
46
|
+
display_name="Algorand",
|
|
47
|
+
network_type=NetworkType.ALGORAND,
|
|
48
|
+
chain_id=0, # Non-EVM, no chain ID
|
|
49
|
+
usdc_address="31566704", # USDC ASA ID on mainnet
|
|
50
|
+
usdc_decimals=6,
|
|
51
|
+
usdc_domain_name="", # Not applicable for Algorand
|
|
52
|
+
usdc_domain_version="",
|
|
53
|
+
rpc_url="https://mainnet-api.algonode.cloud",
|
|
54
|
+
enabled=True,
|
|
55
|
+
extra_config={
|
|
56
|
+
# ASA (Algorand Standard Asset) details
|
|
57
|
+
"usdc_asa_id": 31566704,
|
|
58
|
+
# Block explorer
|
|
59
|
+
"explorer_url": "https://allo.info",
|
|
60
|
+
# Indexer endpoint (for account queries)
|
|
61
|
+
"indexer_url": "https://mainnet-idx.algonode.cloud",
|
|
62
|
+
# Network identifier
|
|
63
|
+
"genesis_id": "mainnet-v1.0",
|
|
64
|
+
# Genesis hash (for CAIP-2)
|
|
65
|
+
"genesis_hash": "wGHE2Pwdvd7S12BL5FaOP20EGYesN73ktiC1qzkkit8=",
|
|
66
|
+
},
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
# Algorand Testnet
|
|
70
|
+
ALGORAND_TESTNET = NetworkConfig(
|
|
71
|
+
name="algorand-testnet",
|
|
72
|
+
display_name="Algorand Testnet",
|
|
73
|
+
network_type=NetworkType.ALGORAND,
|
|
74
|
+
chain_id=0, # Non-EVM, no chain ID
|
|
75
|
+
usdc_address="10458941", # USDC ASA ID on testnet
|
|
76
|
+
usdc_decimals=6,
|
|
77
|
+
usdc_domain_name="", # Not applicable for Algorand
|
|
78
|
+
usdc_domain_version="",
|
|
79
|
+
rpc_url="https://testnet-api.algonode.cloud",
|
|
80
|
+
enabled=True,
|
|
81
|
+
extra_config={
|
|
82
|
+
# ASA (Algorand Standard Asset) details
|
|
83
|
+
"usdc_asa_id": 10458941,
|
|
84
|
+
# Block explorer
|
|
85
|
+
"explorer_url": "https://testnet.allo.info",
|
|
86
|
+
# Indexer endpoint (for account queries)
|
|
87
|
+
"indexer_url": "https://testnet-idx.algonode.cloud",
|
|
88
|
+
# Network identifier
|
|
89
|
+
"genesis_id": "testnet-v1.0",
|
|
90
|
+
# Genesis hash
|
|
91
|
+
"genesis_hash": "SGO1GKSzyE7IEPItTxCByw9x8FmnrCDexi9/cOUJOiI=",
|
|
92
|
+
},
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
# Register Algorand networks
|
|
96
|
+
register_network(ALGORAND)
|
|
97
|
+
register_network(ALGORAND_TESTNET)
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
# =============================================================================
|
|
101
|
+
# Algorand-specific utilities
|
|
102
|
+
# =============================================================================
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def is_algorand_network(network_name: str) -> bool:
|
|
106
|
+
"""
|
|
107
|
+
Check if a network is Algorand.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
network_name: Network name to check
|
|
111
|
+
|
|
112
|
+
Returns:
|
|
113
|
+
True if network is Algorand (mainnet or testnet)
|
|
114
|
+
"""
|
|
115
|
+
from uvd_x402_sdk.networks.base import get_network, NetworkType
|
|
116
|
+
|
|
117
|
+
network = get_network(network_name)
|
|
118
|
+
if not network:
|
|
119
|
+
return False
|
|
120
|
+
return network.network_type == NetworkType.ALGORAND
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def get_algorand_networks() -> list:
|
|
124
|
+
"""
|
|
125
|
+
Get all registered Algorand networks.
|
|
126
|
+
|
|
127
|
+
Returns:
|
|
128
|
+
List of Algorand NetworkConfig instances
|
|
129
|
+
"""
|
|
130
|
+
from uvd_x402_sdk.networks.base import list_networks, NetworkType
|
|
131
|
+
|
|
132
|
+
return [
|
|
133
|
+
n for n in list_networks(enabled_only=True)
|
|
134
|
+
if n.network_type == NetworkType.ALGORAND
|
|
135
|
+
]
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
def is_valid_algorand_address(address: str) -> bool:
|
|
139
|
+
"""
|
|
140
|
+
Validate an Algorand address format.
|
|
141
|
+
|
|
142
|
+
Algorand addresses are 58 characters, base32 encoded (RFC 4648).
|
|
143
|
+
They consist of uppercase letters A-Z and digits 2-7.
|
|
144
|
+
|
|
145
|
+
Args:
|
|
146
|
+
address: Address to validate
|
|
147
|
+
|
|
148
|
+
Returns:
|
|
149
|
+
True if valid Algorand address format
|
|
150
|
+
"""
|
|
151
|
+
if not address or not isinstance(address, str):
|
|
152
|
+
return False
|
|
153
|
+
|
|
154
|
+
# Algorand addresses are exactly 58 characters
|
|
155
|
+
if len(address) != 58:
|
|
156
|
+
return False
|
|
157
|
+
|
|
158
|
+
# Base32 alphabet (RFC 4648): A-Z and 2-7
|
|
159
|
+
base32_pattern = re.compile(r'^[A-Z2-7]+$')
|
|
160
|
+
return bool(base32_pattern.match(address))
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
def validate_algorand_payload(payload: Dict[str, Any]) -> bool:
|
|
164
|
+
"""
|
|
165
|
+
Validate an Algorand payment payload structure.
|
|
166
|
+
|
|
167
|
+
The payload must contain:
|
|
168
|
+
- from: Sender's Algorand address
|
|
169
|
+
- to: Recipient's Algorand address
|
|
170
|
+
- amount: Amount in base units (microUSDC)
|
|
171
|
+
- assetId: ASA ID for USDC
|
|
172
|
+
- signedTxn: Base64-encoded signed transaction
|
|
173
|
+
|
|
174
|
+
Args:
|
|
175
|
+
payload: Payload dictionary from x402 payment
|
|
176
|
+
|
|
177
|
+
Returns:
|
|
178
|
+
True if valid, raises ValueError if invalid
|
|
179
|
+
"""
|
|
180
|
+
required_fields = ["from", "to", "amount", "assetId", "signedTxn"]
|
|
181
|
+
|
|
182
|
+
for field in required_fields:
|
|
183
|
+
if field not in payload:
|
|
184
|
+
raise ValueError(f"Algorand payload missing '{field}' field")
|
|
185
|
+
|
|
186
|
+
# Validate addresses
|
|
187
|
+
if not is_valid_algorand_address(payload["from"]):
|
|
188
|
+
raise ValueError(f"Invalid 'from' address: {payload['from']}")
|
|
189
|
+
if not is_valid_algorand_address(payload["to"]):
|
|
190
|
+
raise ValueError(f"Invalid 'to' address: {payload['to']}")
|
|
191
|
+
|
|
192
|
+
# Validate amount
|
|
193
|
+
try:
|
|
194
|
+
amount = int(payload["amount"])
|
|
195
|
+
if amount <= 0:
|
|
196
|
+
raise ValueError(f"Amount must be positive: {amount}")
|
|
197
|
+
except (ValueError, TypeError) as e:
|
|
198
|
+
raise ValueError(f"Invalid amount: {payload['amount']}") from e
|
|
199
|
+
|
|
200
|
+
# Validate assetId
|
|
201
|
+
try:
|
|
202
|
+
asset_id = int(payload["assetId"])
|
|
203
|
+
if asset_id <= 0:
|
|
204
|
+
raise ValueError(f"Asset ID must be positive: {asset_id}")
|
|
205
|
+
except (ValueError, TypeError) as e:
|
|
206
|
+
raise ValueError(f"Invalid assetId: {payload['assetId']}") from e
|
|
207
|
+
|
|
208
|
+
# Validate signedTxn is valid base64
|
|
209
|
+
try:
|
|
210
|
+
signed_txn = payload["signedTxn"]
|
|
211
|
+
tx_bytes = base64.b64decode(signed_txn)
|
|
212
|
+
if len(tx_bytes) < 50:
|
|
213
|
+
raise ValueError(f"Signed transaction too short: {len(tx_bytes)} bytes")
|
|
214
|
+
except Exception as e:
|
|
215
|
+
raise ValueError(f"Invalid signedTxn (not valid base64): {e}") from e
|
|
216
|
+
|
|
217
|
+
return True
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def get_explorer_tx_url(network_name: str, tx_id: str) -> Optional[str]:
|
|
221
|
+
"""
|
|
222
|
+
Get block explorer URL for a transaction.
|
|
223
|
+
|
|
224
|
+
Args:
|
|
225
|
+
network_name: Network name ('algorand' or 'algorand-testnet')
|
|
226
|
+
tx_id: Transaction ID
|
|
227
|
+
|
|
228
|
+
Returns:
|
|
229
|
+
Explorer URL or None if network not found
|
|
230
|
+
"""
|
|
231
|
+
from uvd_x402_sdk.networks.base import get_network
|
|
232
|
+
|
|
233
|
+
network = get_network(network_name)
|
|
234
|
+
if not network or network.network_type != NetworkType.ALGORAND:
|
|
235
|
+
return None
|
|
236
|
+
|
|
237
|
+
explorer_url = network.extra_config.get("explorer_url", "https://allo.info")
|
|
238
|
+
return f"{explorer_url}/tx/{tx_id}"
|
|
239
|
+
|
|
240
|
+
|
|
241
|
+
def get_explorer_address_url(network_name: str, address: str) -> Optional[str]:
|
|
242
|
+
"""
|
|
243
|
+
Get block explorer URL for an address.
|
|
244
|
+
|
|
245
|
+
Args:
|
|
246
|
+
network_name: Network name ('algorand' or 'algorand-testnet')
|
|
247
|
+
address: Algorand address
|
|
248
|
+
|
|
249
|
+
Returns:
|
|
250
|
+
Explorer URL or None if network not found
|
|
251
|
+
"""
|
|
252
|
+
from uvd_x402_sdk.networks.base import get_network
|
|
253
|
+
|
|
254
|
+
network = get_network(network_name)
|
|
255
|
+
if not network or network.network_type != NetworkType.ALGORAND:
|
|
256
|
+
return None
|
|
257
|
+
|
|
258
|
+
explorer_url = network.extra_config.get("explorer_url", "https://allo.info")
|
|
259
|
+
return f"{explorer_url}/account/{address}"
|
|
260
|
+
|
|
261
|
+
|
|
262
|
+
def get_usdc_asa_id(network_name: str) -> Optional[int]:
|
|
263
|
+
"""
|
|
264
|
+
Get the USDC ASA ID for an Algorand network.
|
|
265
|
+
|
|
266
|
+
Args:
|
|
267
|
+
network_name: Network name ('algorand' or 'algorand-testnet')
|
|
268
|
+
|
|
269
|
+
Returns:
|
|
270
|
+
USDC ASA ID or None if network not found
|
|
271
|
+
"""
|
|
272
|
+
from uvd_x402_sdk.networks.base import get_network
|
|
273
|
+
|
|
274
|
+
network = get_network(network_name)
|
|
275
|
+
if not network or network.network_type != NetworkType.ALGORAND:
|
|
276
|
+
return None
|
|
277
|
+
|
|
278
|
+
# Try extra_config first, then fall back to usdc_address
|
|
279
|
+
asa_id = network.extra_config.get("usdc_asa_id")
|
|
280
|
+
if asa_id:
|
|
281
|
+
return int(asa_id)
|
|
282
|
+
|
|
283
|
+
# Parse from usdc_address (which stores the ASA ID as string)
|
|
284
|
+
try:
|
|
285
|
+
return int(network.usdc_address)
|
|
286
|
+
except (ValueError, TypeError):
|
|
287
|
+
return None
|
|
@@ -22,10 +22,11 @@ from typing import Dict, List, Literal, Optional, Any
|
|
|
22
22
|
# - eurc: Euro Coin (Circle) - 6 decimals
|
|
23
23
|
# - ausd: Agora USD (Agora Finance) - 6 decimals
|
|
24
24
|
# - pyusd: PayPal USD (PayPal/Paxos) - 6 decimals
|
|
25
|
-
|
|
25
|
+
# - usdt: Tether USD (USDT0 omnichain via LayerZero) - 6 decimals
|
|
26
|
+
TokenType = Literal["usdc", "eurc", "ausd", "pyusd", "usdt"]
|
|
26
27
|
|
|
27
28
|
# All supported token types
|
|
28
|
-
ALL_TOKEN_TYPES: List[TokenType] = ["usdc", "eurc", "ausd", "pyusd"]
|
|
29
|
+
ALL_TOKEN_TYPES: List[TokenType] = ["usdc", "eurc", "ausd", "pyusd", "usdt"]
|
|
29
30
|
|
|
30
31
|
|
|
31
32
|
@dataclass
|
|
@@ -55,6 +56,7 @@ class NetworkType(Enum):
|
|
|
55
56
|
- SVM: Partially-signed VersionedTransaction (SPL token transfer) - Solana, Fogo
|
|
56
57
|
- NEAR: NEP-366 SignedDelegateAction (meta-transaction)
|
|
57
58
|
- STELLAR: Soroban Authorization Entry XDR
|
|
59
|
+
- ALGORAND: ASA (Algorand Standard Assets) transfer via signed transaction
|
|
58
60
|
|
|
59
61
|
Note: SOLANA is deprecated, use SVM instead for Solana-compatible chains.
|
|
60
62
|
"""
|
|
@@ -64,6 +66,7 @@ class NetworkType(Enum):
|
|
|
64
66
|
SOLANA = "solana" # Deprecated: use SVM
|
|
65
67
|
NEAR = "near"
|
|
66
68
|
STELLAR = "stellar"
|
|
69
|
+
ALGORAND = "algorand" # Algorand ASA transfers
|
|
67
70
|
|
|
68
71
|
@classmethod
|
|
69
72
|
def is_svm(cls, network_type: "NetworkType") -> bool:
|
|
@@ -368,6 +371,7 @@ _CAIP2_NAMESPACE_MAP = {
|
|
|
368
371
|
"solana": NetworkType.SVM,
|
|
369
372
|
"near": NetworkType.NEAR,
|
|
370
373
|
"stellar": NetworkType.STELLAR,
|
|
374
|
+
"algorand": NetworkType.ALGORAND,
|
|
371
375
|
}
|
|
372
376
|
|
|
373
377
|
# Network name to CAIP-2 format
|
|
@@ -390,6 +394,9 @@ _NETWORK_TO_CAIP2 = {
|
|
|
390
394
|
"near": "near:mainnet",
|
|
391
395
|
# Stellar
|
|
392
396
|
"stellar": "stellar:pubnet",
|
|
397
|
+
# Algorand
|
|
398
|
+
"algorand": "algorand:mainnet",
|
|
399
|
+
"algorand-testnet": "algorand:testnet",
|
|
393
400
|
}
|
|
394
401
|
|
|
395
402
|
# CAIP-2 to network name mapping (reverse of above)
|
|
@@ -443,6 +450,11 @@ def parse_caip2_network(caip2_id: str) -> Optional[str]:
|
|
|
443
450
|
return "near"
|
|
444
451
|
if namespace == "stellar" and reference in ("pubnet", "mainnet"):
|
|
445
452
|
return "stellar"
|
|
453
|
+
if namespace == "algorand":
|
|
454
|
+
if reference == "mainnet":
|
|
455
|
+
return "algorand"
|
|
456
|
+
if reference == "testnet":
|
|
457
|
+
return "algorand-testnet"
|
|
446
458
|
|
|
447
459
|
return None
|
|
448
460
|
|
|
@@ -13,6 +13,7 @@ Multi-token support:
|
|
|
13
13
|
- EURC: Ethereum, Base, Avalanche (6 decimals)
|
|
14
14
|
- AUSD: Ethereum, Arbitrum, Avalanche, Polygon, Monad (6 decimals)
|
|
15
15
|
- PYUSD: Ethereum (6 decimals)
|
|
16
|
+
- USDT: Arbitrum, Optimism, Celo (6 decimals) - USDT0 omnichain via LayerZero
|
|
16
17
|
"""
|
|
17
18
|
|
|
18
19
|
from uvd_x402_sdk.networks.base import (
|
|
@@ -122,7 +123,7 @@ POLYGON = NetworkConfig(
|
|
|
122
123
|
},
|
|
123
124
|
)
|
|
124
125
|
|
|
125
|
-
# Arbitrum One - supports USDC, AUSD
|
|
126
|
+
# Arbitrum One - supports USDC, AUSD, USDT
|
|
126
127
|
ARBITRUM = NetworkConfig(
|
|
127
128
|
name="arbitrum",
|
|
128
129
|
display_name="Arbitrum One",
|
|
@@ -147,10 +148,16 @@ ARBITRUM = NetworkConfig(
|
|
|
147
148
|
name="Agora Dollar",
|
|
148
149
|
version="1",
|
|
149
150
|
),
|
|
151
|
+
"usdt": TokenConfig(
|
|
152
|
+
address="0xFd086bC7CD5C481DCC9C85ebE478A1C0b69FCbb9",
|
|
153
|
+
decimals=6,
|
|
154
|
+
name="USD₮0",
|
|
155
|
+
version="1",
|
|
156
|
+
),
|
|
150
157
|
},
|
|
151
158
|
)
|
|
152
159
|
|
|
153
|
-
# Optimism
|
|
160
|
+
# Optimism - supports USDC, USDT
|
|
154
161
|
OPTIMISM = NetworkConfig(
|
|
155
162
|
name="optimism",
|
|
156
163
|
display_name="Optimism",
|
|
@@ -162,6 +169,20 @@ OPTIMISM = NetworkConfig(
|
|
|
162
169
|
usdc_domain_version="2",
|
|
163
170
|
rpc_url="https://mainnet.optimism.io",
|
|
164
171
|
enabled=True,
|
|
172
|
+
tokens={
|
|
173
|
+
"usdc": TokenConfig(
|
|
174
|
+
address="0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
175
|
+
decimals=6,
|
|
176
|
+
name="USD Coin",
|
|
177
|
+
version="2",
|
|
178
|
+
),
|
|
179
|
+
"usdt": TokenConfig(
|
|
180
|
+
address="0x01bff41798a0bcf287b996046ca68b395dbc1071",
|
|
181
|
+
decimals=6,
|
|
182
|
+
name="USD₮0",
|
|
183
|
+
version="1",
|
|
184
|
+
),
|
|
185
|
+
},
|
|
165
186
|
)
|
|
166
187
|
|
|
167
188
|
# Avalanche C-Chain - supports USDC, EURC, AUSD
|
|
@@ -198,7 +219,7 @@ AVALANCHE = NetworkConfig(
|
|
|
198
219
|
},
|
|
199
220
|
)
|
|
200
221
|
|
|
201
|
-
# Celo
|
|
222
|
+
# Celo - supports USDC, USDT
|
|
202
223
|
# NOTE: Celo uses 'USDC' (not 'USD Coin') for EIP-712 domain name
|
|
203
224
|
CELO = NetworkConfig(
|
|
204
225
|
name="celo",
|
|
@@ -211,6 +232,20 @@ CELO = NetworkConfig(
|
|
|
211
232
|
usdc_domain_version="2",
|
|
212
233
|
rpc_url="https://forno.celo.org",
|
|
213
234
|
enabled=True,
|
|
235
|
+
tokens={
|
|
236
|
+
"usdc": TokenConfig(
|
|
237
|
+
address="0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
|
|
238
|
+
decimals=6,
|
|
239
|
+
name="USDC", # Celo uses "USDC" not "USD Coin"
|
|
240
|
+
version="2",
|
|
241
|
+
),
|
|
242
|
+
"usdt": TokenConfig(
|
|
243
|
+
address="0x48065fbBE25f71C9282ddf5e1cD6D6A887483D5e",
|
|
244
|
+
decimals=6,
|
|
245
|
+
name="Tether USD", # Celo USDT uses "Tether USD"
|
|
246
|
+
version="1",
|
|
247
|
+
),
|
|
248
|
+
},
|
|
214
249
|
)
|
|
215
250
|
|
|
216
251
|
# HyperEVM (Hyperliquid)
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: uvd-x402-sdk
|
|
3
|
-
Version: 0.
|
|
4
|
-
Summary: Python SDK for x402 payments - gasless crypto payments across
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Python SDK for x402 payments - gasless crypto payments across 16 blockchains with multi-stablecoin support (USDC, EURC, AUSD, PYUSD, USDT)
|
|
5
5
|
Author-email: Ultravioleta DAO <dev@ultravioletadao.xyz>
|
|
6
6
|
Project-URL: Homepage, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
|
|
7
7
|
Project-URL: Documentation, https://docs.ultravioletadao.xyz/x402-sdk
|
|
8
8
|
Project-URL: Repository, https://github.com/UltravioletaDAO/uvd-x402-sdk-python
|
|
9
9
|
Project-URL: Issues, https://github.com/UltravioletaDAO/uvd-x402-sdk-python/issues
|
|
10
|
-
Keywords: x402,payments,crypto,usdc,eurc,stablecoin,web3,evm,solana,near,stellar,facilitator,gasless,eip-712,eip-3009
|
|
10
|
+
Keywords: x402,payments,crypto,usdc,eurc,stablecoin,web3,evm,solana,near,stellar,algorand,facilitator,gasless,eip-712,eip-3009
|
|
11
11
|
Classifier: Development Status :: 4 - Beta
|
|
12
12
|
Classifier: Intended Audience :: Developers
|
|
13
13
|
Classifier: License :: OSI Approved :: MIT License
|
|
@@ -56,7 +56,7 @@ Accept **gasless stablecoin payments** across **14 blockchain networks** with a
|
|
|
56
56
|
## Features
|
|
57
57
|
|
|
58
58
|
- **14 Networks**: EVM chains (Base, Ethereum, Polygon, etc.), SVM chains (Solana, Fogo), NEAR, and Stellar
|
|
59
|
-
- **
|
|
59
|
+
- **5 Stablecoins**: USDC, EURC, AUSD, PYUSD, USDT (EVM chains)
|
|
60
60
|
- **x402 v1 & v2**: Full support for both protocol versions with auto-detection
|
|
61
61
|
- **Framework Integrations**: Flask, FastAPI, Django, AWS Lambda
|
|
62
62
|
- **Gasless Payments**: Users sign EIP-712/EIP-3009 authorizations, facilitator pays all network fees
|
|
@@ -102,6 +102,7 @@ print(f"Paid by {result.payer_address}, tx: {result.transaction_hash}")
|
|
|
102
102
|
| EURC | Ethereum, Base, Avalanche | 6 |
|
|
103
103
|
| AUSD | Ethereum, Arbitrum, Avalanche, Polygon, Monad | 6 |
|
|
104
104
|
| PYUSD | Ethereum | 6 |
|
|
105
|
+
| USDT | Ethereum, Arbitrum, Optimism, Avalanche, Polygon | 6 |
|
|
105
106
|
|
|
106
107
|
## Installation
|
|
107
108
|
|
|
@@ -926,6 +927,11 @@ MIT License - see LICENSE file.
|
|
|
926
927
|
|
|
927
928
|
## Changelog
|
|
928
929
|
|
|
930
|
+
### v0.3.4 (2025-12-22)
|
|
931
|
+
|
|
932
|
+
- Added USDT support (USDT0 omnichain via LayerZero) on Ethereum, Arbitrum, Optimism, Avalanche, Polygon
|
|
933
|
+
- SDK now supports 5 stablecoins: USDC, EURC, AUSD, PYUSD, USDT
|
|
934
|
+
|
|
929
935
|
### v0.3.3 (2025-12-22)
|
|
930
936
|
|
|
931
937
|
- Fixed EIP-712 domain names: AUSD uses "Agora Dollar" (not "Agora USD")
|
|
@@ -19,6 +19,7 @@ src/uvd_x402_sdk/integrations/fastapi_integration.py
|
|
|
19
19
|
src/uvd_x402_sdk/integrations/flask_integration.py
|
|
20
20
|
src/uvd_x402_sdk/integrations/lambda_integration.py
|
|
21
21
|
src/uvd_x402_sdk/networks/__init__.py
|
|
22
|
+
src/uvd_x402_sdk/networks/algorand.py
|
|
22
23
|
src/uvd_x402_sdk/networks/base.py
|
|
23
24
|
src/uvd_x402_sdk/networks/evm.py
|
|
24
25
|
src/uvd_x402_sdk/networks/near.py
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/django_integration.py
RENAMED
|
File without changes
|
{uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/fastapi_integration.py
RENAMED
|
File without changes
|
{uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/flask_integration.py
RENAMED
|
File without changes
|
{uvd_x402_sdk-0.3.3 → uvd_x402_sdk-0.4.0}/src/uvd_x402_sdk/integrations/lambda_integration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|