uvd-x402-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.
- uvd_x402_sdk/__init__.py +169 -0
- uvd_x402_sdk/client.py +527 -0
- uvd_x402_sdk/config.py +249 -0
- uvd_x402_sdk/decorators.py +325 -0
- uvd_x402_sdk/exceptions.py +254 -0
- uvd_x402_sdk/integrations/__init__.py +74 -0
- uvd_x402_sdk/integrations/django_integration.py +237 -0
- uvd_x402_sdk/integrations/fastapi_integration.py +330 -0
- uvd_x402_sdk/integrations/flask_integration.py +259 -0
- uvd_x402_sdk/integrations/lambda_integration.py +320 -0
- uvd_x402_sdk/models.py +397 -0
- uvd_x402_sdk/networks/__init__.py +54 -0
- uvd_x402_sdk/networks/base.py +348 -0
- uvd_x402_sdk/networks/evm.py +235 -0
- uvd_x402_sdk/networks/near.py +397 -0
- uvd_x402_sdk/networks/solana.py +269 -0
- uvd_x402_sdk/networks/stellar.py +129 -0
- uvd_x402_sdk/response.py +439 -0
- uvd_x402_sdk-0.2.0.dist-info/LICENSE +21 -0
- uvd_x402_sdk-0.2.0.dist-info/METADATA +776 -0
- uvd_x402_sdk-0.2.0.dist-info/RECORD +23 -0
- uvd_x402_sdk-0.2.0.dist-info/WHEEL +5 -0
- uvd_x402_sdk-0.2.0.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,348 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Base network configuration and registry.
|
|
3
|
+
|
|
4
|
+
This module provides the foundation for network configuration, including:
|
|
5
|
+
- NetworkConfig dataclass for defining network parameters
|
|
6
|
+
- NetworkType enum for categorizing networks
|
|
7
|
+
- Global registry for storing and retrieving network configurations
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
from dataclasses import dataclass, field
|
|
11
|
+
from enum import Enum
|
|
12
|
+
from typing import Dict, List, Optional, Any
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class NetworkType(Enum):
|
|
16
|
+
"""
|
|
17
|
+
Network type categorization.
|
|
18
|
+
|
|
19
|
+
Different network types use different signature/transaction formats:
|
|
20
|
+
- EVM: EIP-712 signed TransferWithAuthorization (ERC-3009)
|
|
21
|
+
- SVM: Partially-signed VersionedTransaction (SPL token transfer) - Solana, Fogo
|
|
22
|
+
- NEAR: NEP-366 SignedDelegateAction (meta-transaction)
|
|
23
|
+
- STELLAR: Soroban Authorization Entry XDR
|
|
24
|
+
|
|
25
|
+
Note: SOLANA is deprecated, use SVM instead for Solana-compatible chains.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
EVM = "evm"
|
|
29
|
+
SVM = "svm" # Solana Virtual Machine chains (Solana, Fogo, etc.)
|
|
30
|
+
SOLANA = "solana" # Deprecated: use SVM
|
|
31
|
+
NEAR = "near"
|
|
32
|
+
STELLAR = "stellar"
|
|
33
|
+
|
|
34
|
+
@classmethod
|
|
35
|
+
def is_svm(cls, network_type: "NetworkType") -> bool:
|
|
36
|
+
"""Check if network type is SVM-compatible (Solana, Fogo, etc.)."""
|
|
37
|
+
return network_type in (cls.SVM, cls.SOLANA)
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
@dataclass
|
|
41
|
+
class NetworkConfig:
|
|
42
|
+
"""
|
|
43
|
+
Configuration for a blockchain network supporting x402 payments.
|
|
44
|
+
|
|
45
|
+
Attributes:
|
|
46
|
+
name: Lowercase network identifier (e.g., 'base', 'solana')
|
|
47
|
+
display_name: Human-readable name (e.g., 'Base', 'Solana')
|
|
48
|
+
network_type: Type of network (EVM, SOLANA, NEAR, STELLAR)
|
|
49
|
+
chain_id: EVM chain ID (0 for non-EVM networks)
|
|
50
|
+
usdc_address: USDC contract/token address
|
|
51
|
+
usdc_decimals: Number of decimals for USDC (usually 6, BSC=18, Stellar=7)
|
|
52
|
+
usdc_domain_name: EIP-712 domain name for USDC (EVM only)
|
|
53
|
+
usdc_domain_version: EIP-712 domain version (EVM only)
|
|
54
|
+
rpc_url: Default RPC endpoint
|
|
55
|
+
enabled: Whether network is currently enabled
|
|
56
|
+
extra_config: Additional network-specific configuration
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
name: str
|
|
60
|
+
display_name: str
|
|
61
|
+
network_type: NetworkType
|
|
62
|
+
chain_id: int = 0
|
|
63
|
+
usdc_address: str = ""
|
|
64
|
+
usdc_decimals: int = 6
|
|
65
|
+
usdc_domain_name: str = "USD Coin"
|
|
66
|
+
usdc_domain_version: str = "2"
|
|
67
|
+
rpc_url: str = ""
|
|
68
|
+
enabled: bool = True
|
|
69
|
+
extra_config: Dict[str, Any] = field(default_factory=dict)
|
|
70
|
+
|
|
71
|
+
def __post_init__(self) -> None:
|
|
72
|
+
"""Validate configuration after initialization."""
|
|
73
|
+
if not self.name:
|
|
74
|
+
raise ValueError("Network name is required")
|
|
75
|
+
if not self.usdc_address:
|
|
76
|
+
raise ValueError(f"USDC address is required for network {self.name}")
|
|
77
|
+
|
|
78
|
+
def get_token_amount(self, usd_amount: float) -> int:
|
|
79
|
+
"""
|
|
80
|
+
Convert USD amount to token base units.
|
|
81
|
+
|
|
82
|
+
Args:
|
|
83
|
+
usd_amount: Amount in USD (e.g., 10.50)
|
|
84
|
+
|
|
85
|
+
Returns:
|
|
86
|
+
Amount in token base units (e.g., 10500000 for 6 decimals)
|
|
87
|
+
"""
|
|
88
|
+
return int(usd_amount * (10**self.usdc_decimals))
|
|
89
|
+
|
|
90
|
+
def format_token_amount(self, base_units: int) -> float:
|
|
91
|
+
"""
|
|
92
|
+
Convert token base units to USD amount.
|
|
93
|
+
|
|
94
|
+
Args:
|
|
95
|
+
base_units: Amount in token base units
|
|
96
|
+
|
|
97
|
+
Returns:
|
|
98
|
+
Amount in USD
|
|
99
|
+
"""
|
|
100
|
+
return base_units / (10**self.usdc_decimals)
|
|
101
|
+
|
|
102
|
+
|
|
103
|
+
# Global network registry
|
|
104
|
+
_NETWORK_REGISTRY: Dict[str, NetworkConfig] = {}
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
def register_network(config: NetworkConfig) -> None:
|
|
108
|
+
"""
|
|
109
|
+
Register a network configuration.
|
|
110
|
+
|
|
111
|
+
This allows adding custom networks or overriding built-in configurations.
|
|
112
|
+
|
|
113
|
+
Args:
|
|
114
|
+
config: NetworkConfig instance to register
|
|
115
|
+
|
|
116
|
+
Example:
|
|
117
|
+
>>> from uvd_x402_sdk.networks import register_network, NetworkConfig, NetworkType
|
|
118
|
+
>>> custom_network = NetworkConfig(
|
|
119
|
+
... name="mychain",
|
|
120
|
+
... display_name="My Custom Chain",
|
|
121
|
+
... network_type=NetworkType.EVM,
|
|
122
|
+
... chain_id=12345,
|
|
123
|
+
... usdc_address="0x...",
|
|
124
|
+
... )
|
|
125
|
+
>>> register_network(custom_network)
|
|
126
|
+
"""
|
|
127
|
+
_NETWORK_REGISTRY[config.name.lower()] = config
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def get_network(name: str) -> Optional[NetworkConfig]:
|
|
131
|
+
"""
|
|
132
|
+
Get network configuration by name.
|
|
133
|
+
|
|
134
|
+
Args:
|
|
135
|
+
name: Network identifier (case-insensitive)
|
|
136
|
+
|
|
137
|
+
Returns:
|
|
138
|
+
NetworkConfig if found, None otherwise
|
|
139
|
+
"""
|
|
140
|
+
return _NETWORK_REGISTRY.get(name.lower())
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def get_network_by_chain_id(chain_id: int) -> Optional[NetworkConfig]:
|
|
144
|
+
"""
|
|
145
|
+
Get network configuration by EVM chain ID.
|
|
146
|
+
|
|
147
|
+
Args:
|
|
148
|
+
chain_id: EVM chain ID
|
|
149
|
+
|
|
150
|
+
Returns:
|
|
151
|
+
NetworkConfig if found, None otherwise
|
|
152
|
+
"""
|
|
153
|
+
for config in _NETWORK_REGISTRY.values():
|
|
154
|
+
if config.chain_id == chain_id and config.network_type == NetworkType.EVM:
|
|
155
|
+
return config
|
|
156
|
+
return None
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
def list_networks(
|
|
160
|
+
enabled_only: bool = True,
|
|
161
|
+
network_type: Optional[NetworkType] = None,
|
|
162
|
+
) -> List[NetworkConfig]:
|
|
163
|
+
"""
|
|
164
|
+
List all registered networks.
|
|
165
|
+
|
|
166
|
+
Args:
|
|
167
|
+
enabled_only: Only return enabled networks
|
|
168
|
+
network_type: Filter by network type
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
List of matching NetworkConfig instances
|
|
172
|
+
"""
|
|
173
|
+
networks = list(_NETWORK_REGISTRY.values())
|
|
174
|
+
|
|
175
|
+
if enabled_only:
|
|
176
|
+
networks = [n for n in networks if n.enabled]
|
|
177
|
+
|
|
178
|
+
if network_type:
|
|
179
|
+
networks = [n for n in networks if n.network_type == network_type]
|
|
180
|
+
|
|
181
|
+
return networks
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def get_supported_chain_ids() -> List[int]:
|
|
185
|
+
"""
|
|
186
|
+
Get list of supported EVM chain IDs.
|
|
187
|
+
|
|
188
|
+
Returns:
|
|
189
|
+
List of chain IDs for enabled EVM networks
|
|
190
|
+
"""
|
|
191
|
+
return [
|
|
192
|
+
n.chain_id
|
|
193
|
+
for n in _NETWORK_REGISTRY.values()
|
|
194
|
+
if n.enabled and n.network_type == NetworkType.EVM and n.chain_id > 0
|
|
195
|
+
]
|
|
196
|
+
|
|
197
|
+
|
|
198
|
+
def get_supported_network_names() -> List[str]:
|
|
199
|
+
"""
|
|
200
|
+
Get list of supported network names.
|
|
201
|
+
|
|
202
|
+
Returns:
|
|
203
|
+
List of network names for enabled networks
|
|
204
|
+
"""
|
|
205
|
+
return [n.name for n in _NETWORK_REGISTRY.values() if n.enabled]
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
# Expose registry for inspection
|
|
209
|
+
SUPPORTED_NETWORKS = _NETWORK_REGISTRY
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
# =============================================================================
|
|
213
|
+
# CAIP-2 Utilities (x402 v2 support)
|
|
214
|
+
# =============================================================================
|
|
215
|
+
|
|
216
|
+
# CAIP-2 namespace to network mapping
|
|
217
|
+
_CAIP2_NAMESPACE_MAP = {
|
|
218
|
+
"eip155": NetworkType.EVM,
|
|
219
|
+
"solana": NetworkType.SVM,
|
|
220
|
+
"near": NetworkType.NEAR,
|
|
221
|
+
"stellar": NetworkType.STELLAR,
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
# Network name to CAIP-2 format
|
|
225
|
+
_NETWORK_TO_CAIP2 = {
|
|
226
|
+
# EVM chains (eip155:chainId)
|
|
227
|
+
"base": "eip155:8453",
|
|
228
|
+
"ethereum": "eip155:1",
|
|
229
|
+
"polygon": "eip155:137",
|
|
230
|
+
"arbitrum": "eip155:42161",
|
|
231
|
+
"optimism": "eip155:10",
|
|
232
|
+
"avalanche": "eip155:43114",
|
|
233
|
+
"celo": "eip155:42220",
|
|
234
|
+
"hyperevm": "eip155:999",
|
|
235
|
+
"unichain": "eip155:130",
|
|
236
|
+
"monad": "eip155:143",
|
|
237
|
+
"bsc": "eip155:56",
|
|
238
|
+
# SVM chains (solana:genesisHash first 32 chars)
|
|
239
|
+
"solana": "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp",
|
|
240
|
+
"fogo": "solana:fogo", # Placeholder - update when known
|
|
241
|
+
# NEAR
|
|
242
|
+
"near": "near:mainnet",
|
|
243
|
+
# Stellar
|
|
244
|
+
"stellar": "stellar:pubnet",
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
# CAIP-2 to network name mapping (reverse of above)
|
|
248
|
+
_CAIP2_TO_NETWORK = {v: k for k, v in _NETWORK_TO_CAIP2.items()}
|
|
249
|
+
|
|
250
|
+
|
|
251
|
+
def parse_caip2_network(caip2_id: str) -> Optional[str]:
|
|
252
|
+
"""
|
|
253
|
+
Parse a CAIP-2 network identifier to network name.
|
|
254
|
+
|
|
255
|
+
CAIP-2 format: namespace:reference
|
|
256
|
+
Examples:
|
|
257
|
+
- "eip155:8453" -> "base"
|
|
258
|
+
- "solana:5eykt4UsFv8P8NJdTREpY1vzqKqZKvdp" -> "solana"
|
|
259
|
+
- "near:mainnet" -> "near"
|
|
260
|
+
|
|
261
|
+
Args:
|
|
262
|
+
caip2_id: CAIP-2 format network identifier
|
|
263
|
+
|
|
264
|
+
Returns:
|
|
265
|
+
Network name if recognized, None otherwise
|
|
266
|
+
"""
|
|
267
|
+
if not caip2_id or ":" not in caip2_id:
|
|
268
|
+
return None
|
|
269
|
+
|
|
270
|
+
# Direct lookup first
|
|
271
|
+
if caip2_id in _CAIP2_TO_NETWORK:
|
|
272
|
+
return _CAIP2_TO_NETWORK[caip2_id]
|
|
273
|
+
|
|
274
|
+
# Parse namespace and reference
|
|
275
|
+
parts = caip2_id.split(":", 1)
|
|
276
|
+
if len(parts) != 2:
|
|
277
|
+
return None
|
|
278
|
+
|
|
279
|
+
namespace, reference = parts
|
|
280
|
+
|
|
281
|
+
# For EIP-155 (EVM), the reference is the chain ID
|
|
282
|
+
if namespace == "eip155":
|
|
283
|
+
try:
|
|
284
|
+
chain_id = int(reference)
|
|
285
|
+
network = get_network_by_chain_id(chain_id)
|
|
286
|
+
return network.name if network else None
|
|
287
|
+
except ValueError:
|
|
288
|
+
return None
|
|
289
|
+
|
|
290
|
+
# For other namespaces, check if reference matches known patterns
|
|
291
|
+
# This handles cases like "solana:mainnet" or "near:mainnet"
|
|
292
|
+
if namespace == "solana" and reference in ("mainnet", "mainnet-beta"):
|
|
293
|
+
return "solana"
|
|
294
|
+
if namespace == "near" and reference == "mainnet":
|
|
295
|
+
return "near"
|
|
296
|
+
if namespace == "stellar" and reference in ("pubnet", "mainnet"):
|
|
297
|
+
return "stellar"
|
|
298
|
+
|
|
299
|
+
return None
|
|
300
|
+
|
|
301
|
+
|
|
302
|
+
def to_caip2_network(network_name: str) -> Optional[str]:
|
|
303
|
+
"""
|
|
304
|
+
Convert network name to CAIP-2 format.
|
|
305
|
+
|
|
306
|
+
Args:
|
|
307
|
+
network_name: Network identifier (e.g., 'base', 'solana')
|
|
308
|
+
|
|
309
|
+
Returns:
|
|
310
|
+
CAIP-2 format string (e.g., 'eip155:8453'), or None if unknown
|
|
311
|
+
"""
|
|
312
|
+
return _NETWORK_TO_CAIP2.get(network_name.lower())
|
|
313
|
+
|
|
314
|
+
|
|
315
|
+
def is_caip2_format(network: str) -> bool:
|
|
316
|
+
"""
|
|
317
|
+
Check if a network identifier is in CAIP-2 format.
|
|
318
|
+
|
|
319
|
+
Args:
|
|
320
|
+
network: Network identifier to check
|
|
321
|
+
|
|
322
|
+
Returns:
|
|
323
|
+
True if CAIP-2 format (contains colon), False if v1 format
|
|
324
|
+
"""
|
|
325
|
+
return ":" in network
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
def normalize_network(network: str) -> str:
|
|
329
|
+
"""
|
|
330
|
+
Normalize a network identifier to v1 format (network name).
|
|
331
|
+
|
|
332
|
+
Handles both v1 ("base") and v2 CAIP-2 ("eip155:8453") formats.
|
|
333
|
+
|
|
334
|
+
Args:
|
|
335
|
+
network: Network identifier in either format
|
|
336
|
+
|
|
337
|
+
Returns:
|
|
338
|
+
Normalized network name (v1 format)
|
|
339
|
+
|
|
340
|
+
Raises:
|
|
341
|
+
ValueError: If network cannot be parsed
|
|
342
|
+
"""
|
|
343
|
+
if is_caip2_format(network):
|
|
344
|
+
normalized = parse_caip2_network(network)
|
|
345
|
+
if normalized is None:
|
|
346
|
+
raise ValueError(f"Unknown CAIP-2 network: {network}")
|
|
347
|
+
return normalized
|
|
348
|
+
return network.lower()
|
|
@@ -0,0 +1,235 @@
|
|
|
1
|
+
"""
|
|
2
|
+
EVM network configurations.
|
|
3
|
+
|
|
4
|
+
This module defines configurations for all supported EVM-compatible chains.
|
|
5
|
+
Each chain uses ERC-3009 TransferWithAuthorization for USDC transfers.
|
|
6
|
+
|
|
7
|
+
Important EIP-712 domain considerations:
|
|
8
|
+
- Most chains use 'USD Coin' as the domain name
|
|
9
|
+
- Celo, HyperEVM, Unichain, Monad use 'USDC' as the domain name
|
|
10
|
+
- BSC USDC uses 18 decimals (not standard 6)
|
|
11
|
+
"""
|
|
12
|
+
|
|
13
|
+
from uvd_x402_sdk.networks.base import (
|
|
14
|
+
NetworkConfig,
|
|
15
|
+
NetworkType,
|
|
16
|
+
register_network,
|
|
17
|
+
)
|
|
18
|
+
|
|
19
|
+
# =============================================================================
|
|
20
|
+
# EVM Networks Configuration
|
|
21
|
+
# =============================================================================
|
|
22
|
+
|
|
23
|
+
# Base (Layer 2)
|
|
24
|
+
BASE = NetworkConfig(
|
|
25
|
+
name="base",
|
|
26
|
+
display_name="Base",
|
|
27
|
+
network_type=NetworkType.EVM,
|
|
28
|
+
chain_id=8453,
|
|
29
|
+
usdc_address="0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913",
|
|
30
|
+
usdc_decimals=6,
|
|
31
|
+
usdc_domain_name="USD Coin",
|
|
32
|
+
usdc_domain_version="2",
|
|
33
|
+
rpc_url="https://mainnet.base.org",
|
|
34
|
+
enabled=True,
|
|
35
|
+
)
|
|
36
|
+
|
|
37
|
+
# Ethereum Mainnet
|
|
38
|
+
ETHEREUM = NetworkConfig(
|
|
39
|
+
name="ethereum",
|
|
40
|
+
display_name="Ethereum",
|
|
41
|
+
network_type=NetworkType.EVM,
|
|
42
|
+
chain_id=1,
|
|
43
|
+
usdc_address="0xA0b86991c6218b36c1d19D4a2e9Eb0cE3606eB48",
|
|
44
|
+
usdc_decimals=6,
|
|
45
|
+
usdc_domain_name="USD Coin",
|
|
46
|
+
usdc_domain_version="2",
|
|
47
|
+
rpc_url="https://eth.llamarpc.com",
|
|
48
|
+
enabled=True,
|
|
49
|
+
)
|
|
50
|
+
|
|
51
|
+
# Polygon (PoS)
|
|
52
|
+
POLYGON = NetworkConfig(
|
|
53
|
+
name="polygon",
|
|
54
|
+
display_name="Polygon",
|
|
55
|
+
network_type=NetworkType.EVM,
|
|
56
|
+
chain_id=137,
|
|
57
|
+
usdc_address="0x3c499c542cEF5E3811e1192ce70d8cC03d5c3359",
|
|
58
|
+
usdc_decimals=6,
|
|
59
|
+
usdc_domain_name="USD Coin",
|
|
60
|
+
usdc_domain_version="2",
|
|
61
|
+
rpc_url="https://polygon-rpc.com",
|
|
62
|
+
enabled=True,
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
# Arbitrum One
|
|
66
|
+
ARBITRUM = NetworkConfig(
|
|
67
|
+
name="arbitrum",
|
|
68
|
+
display_name="Arbitrum One",
|
|
69
|
+
network_type=NetworkType.EVM,
|
|
70
|
+
chain_id=42161,
|
|
71
|
+
usdc_address="0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
|
|
72
|
+
usdc_decimals=6,
|
|
73
|
+
usdc_domain_name="USD Coin",
|
|
74
|
+
usdc_domain_version="2",
|
|
75
|
+
rpc_url="https://arb1.arbitrum.io/rpc",
|
|
76
|
+
enabled=True,
|
|
77
|
+
)
|
|
78
|
+
|
|
79
|
+
# Optimism
|
|
80
|
+
OPTIMISM = NetworkConfig(
|
|
81
|
+
name="optimism",
|
|
82
|
+
display_name="Optimism",
|
|
83
|
+
network_type=NetworkType.EVM,
|
|
84
|
+
chain_id=10,
|
|
85
|
+
usdc_address="0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85",
|
|
86
|
+
usdc_decimals=6,
|
|
87
|
+
usdc_domain_name="USD Coin",
|
|
88
|
+
usdc_domain_version="2",
|
|
89
|
+
rpc_url="https://mainnet.optimism.io",
|
|
90
|
+
enabled=True,
|
|
91
|
+
)
|
|
92
|
+
|
|
93
|
+
# Avalanche C-Chain
|
|
94
|
+
AVALANCHE = NetworkConfig(
|
|
95
|
+
name="avalanche",
|
|
96
|
+
display_name="Avalanche C-Chain",
|
|
97
|
+
network_type=NetworkType.EVM,
|
|
98
|
+
chain_id=43114,
|
|
99
|
+
usdc_address="0xB97EF9Ef8734C71904D8002F8b6Bc66Dd9c48a6E",
|
|
100
|
+
usdc_decimals=6,
|
|
101
|
+
usdc_domain_name="USD Coin",
|
|
102
|
+
usdc_domain_version="2",
|
|
103
|
+
rpc_url="https://avalanche-c-chain-rpc.publicnode.com",
|
|
104
|
+
enabled=True,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# Celo
|
|
108
|
+
# NOTE: Celo uses 'USDC' (not 'USD Coin') for EIP-712 domain name
|
|
109
|
+
CELO = NetworkConfig(
|
|
110
|
+
name="celo",
|
|
111
|
+
display_name="Celo",
|
|
112
|
+
network_type=NetworkType.EVM,
|
|
113
|
+
chain_id=42220,
|
|
114
|
+
usdc_address="0xcebA9300f2b948710d2653dD7B07f33A8B32118C",
|
|
115
|
+
usdc_decimals=6,
|
|
116
|
+
usdc_domain_name="USDC", # Different from other chains!
|
|
117
|
+
usdc_domain_version="2",
|
|
118
|
+
rpc_url="https://forno.celo.org",
|
|
119
|
+
enabled=True,
|
|
120
|
+
)
|
|
121
|
+
|
|
122
|
+
# HyperEVM (Hyperliquid)
|
|
123
|
+
# NOTE: HyperEVM uses 'USDC' (not 'USD Coin') for EIP-712 domain name
|
|
124
|
+
HYPEREVM = NetworkConfig(
|
|
125
|
+
name="hyperevm",
|
|
126
|
+
display_name="HyperEVM",
|
|
127
|
+
network_type=NetworkType.EVM,
|
|
128
|
+
chain_id=999,
|
|
129
|
+
usdc_address="0xb88339CB7199b77E23DB6E890353E22632Ba630f",
|
|
130
|
+
usdc_decimals=6,
|
|
131
|
+
usdc_domain_name="USDC", # Different from other chains!
|
|
132
|
+
usdc_domain_version="2",
|
|
133
|
+
rpc_url="https://rpc.hyperliquid.xyz/evm",
|
|
134
|
+
enabled=True,
|
|
135
|
+
)
|
|
136
|
+
|
|
137
|
+
# Unichain
|
|
138
|
+
# NOTE: Unichain uses 'USDC' (not 'USD Coin') for EIP-712 domain name
|
|
139
|
+
UNICHAIN = NetworkConfig(
|
|
140
|
+
name="unichain",
|
|
141
|
+
display_name="Unichain",
|
|
142
|
+
network_type=NetworkType.EVM,
|
|
143
|
+
chain_id=130,
|
|
144
|
+
usdc_address="0x078d782b760474a361dda0af3839290b0ef57ad6",
|
|
145
|
+
usdc_decimals=6,
|
|
146
|
+
usdc_domain_name="USDC", # Different from other chains!
|
|
147
|
+
usdc_domain_version="2",
|
|
148
|
+
rpc_url="https://unichain-rpc.publicnode.com",
|
|
149
|
+
enabled=True,
|
|
150
|
+
)
|
|
151
|
+
|
|
152
|
+
# Monad
|
|
153
|
+
# NOTE: Monad uses 'USDC' (not 'USD Coin') for EIP-712 domain name
|
|
154
|
+
MONAD = NetworkConfig(
|
|
155
|
+
name="monad",
|
|
156
|
+
display_name="Monad",
|
|
157
|
+
network_type=NetworkType.EVM,
|
|
158
|
+
chain_id=143,
|
|
159
|
+
usdc_address="0x754704bc059f8c67012fed69bc8a327a5aafb603",
|
|
160
|
+
usdc_decimals=6,
|
|
161
|
+
usdc_domain_name="USDC", # Different from other chains!
|
|
162
|
+
usdc_domain_version="2",
|
|
163
|
+
rpc_url="https://rpc.monad.xyz",
|
|
164
|
+
enabled=True,
|
|
165
|
+
)
|
|
166
|
+
|
|
167
|
+
# BNB Smart Chain (BSC)
|
|
168
|
+
# NOTE: BSC USDC uses 18 decimals (not 6 like other chains)
|
|
169
|
+
# NOTE: Binance-Peg USDC doesn't support ERC-3009 - DISABLED
|
|
170
|
+
BSC = NetworkConfig(
|
|
171
|
+
name="bsc",
|
|
172
|
+
display_name="BNB Smart Chain",
|
|
173
|
+
network_type=NetworkType.EVM,
|
|
174
|
+
chain_id=56,
|
|
175
|
+
usdc_address="0x8AC76a51cc950d9822D68b83fE1Ad97B32Cd580d",
|
|
176
|
+
usdc_decimals=18, # Different from other chains!
|
|
177
|
+
usdc_domain_name="USD Coin",
|
|
178
|
+
usdc_domain_version="2",
|
|
179
|
+
rpc_url="https://binance.llamarpc.com",
|
|
180
|
+
enabled=False, # Disabled: Binance-Peg USDC doesn't support ERC-3009
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
# =============================================================================
|
|
184
|
+
# Register all EVM networks
|
|
185
|
+
# =============================================================================
|
|
186
|
+
|
|
187
|
+
_EVM_NETWORKS = [
|
|
188
|
+
BASE,
|
|
189
|
+
ETHEREUM,
|
|
190
|
+
POLYGON,
|
|
191
|
+
ARBITRUM,
|
|
192
|
+
OPTIMISM,
|
|
193
|
+
AVALANCHE,
|
|
194
|
+
CELO,
|
|
195
|
+
HYPEREVM,
|
|
196
|
+
UNICHAIN,
|
|
197
|
+
MONAD,
|
|
198
|
+
BSC,
|
|
199
|
+
]
|
|
200
|
+
|
|
201
|
+
for network in _EVM_NETWORKS:
|
|
202
|
+
register_network(network)
|
|
203
|
+
|
|
204
|
+
|
|
205
|
+
def get_usdc_domain_name(network_name: str) -> str:
|
|
206
|
+
"""
|
|
207
|
+
Get the correct EIP-712 domain name for USDC on a network.
|
|
208
|
+
|
|
209
|
+
Args:
|
|
210
|
+
network_name: Network identifier
|
|
211
|
+
|
|
212
|
+
Returns:
|
|
213
|
+
Domain name string ('USD Coin' or 'USDC')
|
|
214
|
+
"""
|
|
215
|
+
# Networks that use 'USDC' instead of 'USD Coin'
|
|
216
|
+
usdc_domain_networks = {"celo", "hyperevm", "unichain", "monad"}
|
|
217
|
+
|
|
218
|
+
if network_name.lower() in usdc_domain_networks:
|
|
219
|
+
return "USDC"
|
|
220
|
+
return "USD Coin"
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
def get_token_decimals(network_name: str) -> int:
|
|
224
|
+
"""
|
|
225
|
+
Get USDC token decimals for a network.
|
|
226
|
+
|
|
227
|
+
Args:
|
|
228
|
+
network_name: Network identifier
|
|
229
|
+
|
|
230
|
+
Returns:
|
|
231
|
+
Number of decimals (6 for most chains, 18 for BSC)
|
|
232
|
+
"""
|
|
233
|
+
if network_name.lower() == "bsc":
|
|
234
|
+
return 18
|
|
235
|
+
return 6
|