token-network 0.4.4__tar.gz → 0.4.6__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.
- {token_network-0.4.4 → token_network-0.4.6}/PKG-INFO +32 -4
- {token_network-0.4.4 → token_network-0.4.6}/README.md +31 -3
- {token_network-0.4.4 → token_network-0.4.6}/pyproject.toml +1 -1
- {token_network-0.4.4 → token_network-0.4.6}/setup.py +1 -1
- {token_network-0.4.4 → token_network-0.4.6}/tests/test_network.py +40 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/__init__.py +12 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/_accessor.py +20 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/_models.py +23 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/data/networks.yaml +16 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/PKG-INFO +32 -4
- {token_network-0.4.4 → token_network-0.4.6}/setup.cfg +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/_loader.py +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/data/token_networks.yaml +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/data/token_networks_testnet.yaml +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network/data/tokens.yaml +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/SOURCES.txt +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/dependency_links.txt +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/requires.txt +0 -0
- {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: token-network
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.6
|
|
4
4
|
Summary: Validate input and return token network config (e.g. network.bitcoin, network.bsc.usdt)
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: blockchain,tokens,networks,crypto,config
|
|
@@ -49,10 +49,36 @@ bitcoin = network("bitcoin")
|
|
|
49
49
|
|
|
50
50
|
bitcoin.decimal # 8 (base token decimals)
|
|
51
51
|
bitcoin.confirmation_number # 2 (required confirmations)
|
|
52
|
+
bitcoin.wallet_address_regex # wallet validation regex for this network
|
|
53
|
+
bitcoin.approximate_confirmation_time # 1200 (approx. seconds to confirm)
|
|
52
54
|
bitcoin.config # NetworkConfigDto (Pydantic)
|
|
53
55
|
bitcoin.__dict__() # Full data: {"config": {...}, "tokens": [...]}
|
|
54
56
|
```
|
|
55
57
|
|
|
58
|
+
### Wallet address validation
|
|
59
|
+
|
|
60
|
+
Each network includes a `wallet_address_regex` pattern in its config. Use it to validate addresses for that chain:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from token_network import network, get_network, validate_wallet_address
|
|
64
|
+
|
|
65
|
+
# Direct property (same style as .decimal / .confirmation_number)
|
|
66
|
+
network("ethereum").wallet_address_regex
|
|
67
|
+
# ^(0x)[0-9A-Fa-f]{40}$
|
|
68
|
+
|
|
69
|
+
# Via config
|
|
70
|
+
network("ethereum").config.wallet_address_regex
|
|
71
|
+
get_network("bitcoin").config.wallet_address_regex
|
|
72
|
+
|
|
73
|
+
# In full network dict
|
|
74
|
+
network("ethereum").to_dict()["config"]["wallet_address_regex"]
|
|
75
|
+
|
|
76
|
+
# Validate an address
|
|
77
|
+
validate_wallet_address("ethereum", "0xdAC17F958D2ee523a2206206994597C13D831ec7") # True
|
|
78
|
+
validate_wallet_address("ethereum", "0x123") # False
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
|
|
56
82
|
### List tokens on a network
|
|
57
83
|
|
|
58
84
|
```python
|
|
@@ -151,7 +177,9 @@ except TokenNetworkError as e:
|
|
|
151
177
|
| What you want | How |
|
|
152
178
|
|---------------|-----|
|
|
153
179
|
| Network by name | `network("bitcoin")` or `network.bitcoin` |
|
|
154
|
-
| Base decimals / confirmations | `network("bitcoin").decimal`, `.confirmation_number` |
|
|
180
|
+
| Base decimals / confirmations | `network("bitcoin").decimal`, `.confirmation_number`, `.approximate_confirmation_time` |
|
|
181
|
+
| Wallet address regex | `network("ethereum").wallet_address_regex` or `.config.wallet_address_regex` |
|
|
182
|
+
| Validate wallet address | `validate_wallet_address("ethereum", "0x...")` → `True` / `False` |
|
|
155
183
|
| Full network data as dict | `network("bitcoin").__dict__()` or `.to_dict()` |
|
|
156
184
|
| Tokens on a network | `network("ethereum").tokens` → list of `TokenOnNetworkDto` |
|
|
157
185
|
| One token on a network | `get_token_on_network(network="ethereum", token_abbr="USDT")` or `network.ethereum.usdt` |
|
|
@@ -164,7 +192,7 @@ All identifiers are **case-insensitive**. Unknown network/token raises `TokenNet
|
|
|
164
192
|
## Pydantic models
|
|
165
193
|
|
|
166
194
|
- **`TokenDto`** — Token definition (slug, symbol, name, precision, factor). From `get_token()`.
|
|
167
|
-
- **`NetworkConfigDto`** — Chain config (slug, name, network_type, base_token_decimal, confirmation_number, …). From `network("x").config` and inside `TokenOnNetworkDto.network`.
|
|
195
|
+
- **`NetworkConfigDto`** — Chain config (slug, name, network_type, base_token_decimal, confirmation_number, wallet_address_regex, …). From `network("x").config` and inside `TokenOnNetworkDto.network`.
|
|
168
196
|
- **`TokenOnNetworkDto`** — Token on a network (network, token, contract_address, decimal, native, type). From `get_token_on_network()`, `get_token_network()`, `network.ethereum.usdt`.
|
|
169
197
|
- **`NetworkDataDto`** — Result of `get_network()`: `config` + `tokens` (list of `TokenOnNetworkDto`).
|
|
170
198
|
|
|
@@ -174,7 +202,7 @@ Use `.model_dump()` to export any model as a dict.
|
|
|
174
202
|
|
|
175
203
|
YAML under `token_network/data/`:
|
|
176
204
|
|
|
177
|
-
- `networks.yaml` — chain config
|
|
205
|
+
- `networks.yaml` — chain config (including `wallet_address_regex` per network)
|
|
178
206
|
- `tokens.yaml` — token definitions
|
|
179
207
|
- `token_networks.yaml` — mainnet bindings (token + network → contract, decimals)
|
|
180
208
|
- `token_networks_testnet.yaml` — testnet bindings (used with `NetworkAccessor(testnet=True)`)
|
|
@@ -26,10 +26,36 @@ bitcoin = network("bitcoin")
|
|
|
26
26
|
|
|
27
27
|
bitcoin.decimal # 8 (base token decimals)
|
|
28
28
|
bitcoin.confirmation_number # 2 (required confirmations)
|
|
29
|
+
bitcoin.wallet_address_regex # wallet validation regex for this network
|
|
30
|
+
bitcoin.approximate_confirmation_time # 1200 (approx. seconds to confirm)
|
|
29
31
|
bitcoin.config # NetworkConfigDto (Pydantic)
|
|
30
32
|
bitcoin.__dict__() # Full data: {"config": {...}, "tokens": [...]}
|
|
31
33
|
```
|
|
32
34
|
|
|
35
|
+
### Wallet address validation
|
|
36
|
+
|
|
37
|
+
Each network includes a `wallet_address_regex` pattern in its config. Use it to validate addresses for that chain:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
from token_network import network, get_network, validate_wallet_address
|
|
41
|
+
|
|
42
|
+
# Direct property (same style as .decimal / .confirmation_number)
|
|
43
|
+
network("ethereum").wallet_address_regex
|
|
44
|
+
# ^(0x)[0-9A-Fa-f]{40}$
|
|
45
|
+
|
|
46
|
+
# Via config
|
|
47
|
+
network("ethereum").config.wallet_address_regex
|
|
48
|
+
get_network("bitcoin").config.wallet_address_regex
|
|
49
|
+
|
|
50
|
+
# In full network dict
|
|
51
|
+
network("ethereum").to_dict()["config"]["wallet_address_regex"]
|
|
52
|
+
|
|
53
|
+
# Validate an address
|
|
54
|
+
validate_wallet_address("ethereum", "0xdAC17F958D2ee523a2206206994597C13D831ec7") # True
|
|
55
|
+
validate_wallet_address("ethereum", "0x123") # False
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
|
|
33
59
|
### List tokens on a network
|
|
34
60
|
|
|
35
61
|
```python
|
|
@@ -128,7 +154,9 @@ except TokenNetworkError as e:
|
|
|
128
154
|
| What you want | How |
|
|
129
155
|
|---------------|-----|
|
|
130
156
|
| Network by name | `network("bitcoin")` or `network.bitcoin` |
|
|
131
|
-
| Base decimals / confirmations | `network("bitcoin").decimal`, `.confirmation_number` |
|
|
157
|
+
| Base decimals / confirmations | `network("bitcoin").decimal`, `.confirmation_number`, `.approximate_confirmation_time` |
|
|
158
|
+
| Wallet address regex | `network("ethereum").wallet_address_regex` or `.config.wallet_address_regex` |
|
|
159
|
+
| Validate wallet address | `validate_wallet_address("ethereum", "0x...")` → `True` / `False` |
|
|
132
160
|
| Full network data as dict | `network("bitcoin").__dict__()` or `.to_dict()` |
|
|
133
161
|
| Tokens on a network | `network("ethereum").tokens` → list of `TokenOnNetworkDto` |
|
|
134
162
|
| One token on a network | `get_token_on_network(network="ethereum", token_abbr="USDT")` or `network.ethereum.usdt` |
|
|
@@ -141,7 +169,7 @@ All identifiers are **case-insensitive**. Unknown network/token raises `TokenNet
|
|
|
141
169
|
## Pydantic models
|
|
142
170
|
|
|
143
171
|
- **`TokenDto`** — Token definition (slug, symbol, name, precision, factor). From `get_token()`.
|
|
144
|
-
- **`NetworkConfigDto`** — Chain config (slug, name, network_type, base_token_decimal, confirmation_number, …). From `network("x").config` and inside `TokenOnNetworkDto.network`.
|
|
172
|
+
- **`NetworkConfigDto`** — Chain config (slug, name, network_type, base_token_decimal, confirmation_number, wallet_address_regex, …). From `network("x").config` and inside `TokenOnNetworkDto.network`.
|
|
145
173
|
- **`TokenOnNetworkDto`** — Token on a network (network, token, contract_address, decimal, native, type). From `get_token_on_network()`, `get_token_network()`, `network.ethereum.usdt`.
|
|
146
174
|
- **`NetworkDataDto`** — Result of `get_network()`: `config` + `tokens` (list of `TokenOnNetworkDto`).
|
|
147
175
|
|
|
@@ -151,7 +179,7 @@ Use `.model_dump()` to export any model as a dict.
|
|
|
151
179
|
|
|
152
180
|
YAML under `token_network/data/`:
|
|
153
181
|
|
|
154
|
-
- `networks.yaml` — chain config
|
|
182
|
+
- `networks.yaml` — chain config (including `wallet_address_regex` per network)
|
|
155
183
|
- `tokens.yaml` — token definitions
|
|
156
184
|
- `token_networks.yaml` — mainnet bindings (token + network → contract, decimals)
|
|
157
185
|
- `token_networks_testnet.yaml` — testnet bindings (used with `NetworkAccessor(testnet=True)`)
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "token-network"
|
|
7
|
-
version = "0.4.
|
|
7
|
+
version = "0.4.6"
|
|
8
8
|
description = "Validate input and return token network config (e.g. network.bitcoin, network.bsc.usdt)"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">=3.8"
|
|
@@ -7,7 +7,7 @@ long_description = _readme.read_text(encoding="utf-8") if _readme.exists() else
|
|
|
7
7
|
|
|
8
8
|
setup(
|
|
9
9
|
name="token-network",
|
|
10
|
-
version="0.4.
|
|
10
|
+
version="0.4.6",
|
|
11
11
|
description="Validate input and return token network config (e.g. network.bitcoin, network.bsc.usdt)",
|
|
12
12
|
long_description=long_description or None,
|
|
13
13
|
long_description_content_type="text/markdown" if long_description else None,
|
|
@@ -66,6 +66,8 @@ def test_network_callable():
|
|
|
66
66
|
bitcoin = network("bitcoin")
|
|
67
67
|
assert bitcoin.decimal == 8
|
|
68
68
|
assert bitcoin.confirmation_number == 2
|
|
69
|
+
assert bitcoin.approximate_confirmation_time == 1200
|
|
70
|
+
assert bitcoin.config.approximate_confirmation_time == 1200
|
|
69
71
|
assert "config" in bitcoin.__dict__()
|
|
70
72
|
assert bitcoin.config == network.bitcoin.config
|
|
71
73
|
|
|
@@ -90,3 +92,41 @@ def test_get_token_on_network():
|
|
|
90
92
|
assert isinstance(ton, TokenOnNetworkDto)
|
|
91
93
|
assert ton.contract_address == "0xdAC17F958D2ee523a2206206994597C13D831ec7"
|
|
92
94
|
assert ton.__dict__()["contract_address"] == ton.contract_address
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
@pytest.mark.parametrize(
|
|
98
|
+
"network_id,address,expected",
|
|
99
|
+
[
|
|
100
|
+
("ethereum", "0xdAC17F958D2ee523a2206206994597C13D831ec7", True),
|
|
101
|
+
("ethereum", "0x123", False),
|
|
102
|
+
("bsc", "0x55d398326f99059fF775485246999027B3197955", True),
|
|
103
|
+
("polygon", "0x742d35Cc6634C0532925a3b844Bc9e7595f0bEb0", True),
|
|
104
|
+
("tron", "TExample123456789012345678901234567890", False),
|
|
105
|
+
("tron", "T9yD14Nj9j7xAB4dbGeiX9h8unkKHxuWwb", True),
|
|
106
|
+
("solana", "7EqQdE8L7Q1RqJqYqYqYqYqYqYqYqYqYqYqYqYqYqYq", True),
|
|
107
|
+
("solana", "0", False),
|
|
108
|
+
("bitcoin", "1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa", True),
|
|
109
|
+
("bitcoin", "bc1qxy2kgdygjrsqtzq2n0yrf2493p83kkfjhx0wlh", True),
|
|
110
|
+
("bitcoin", "invalid", False),
|
|
111
|
+
("ripple", "rN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH", True),
|
|
112
|
+
("ripple", "xN7n7otQDd6FczFgLdSqtcsAUxDkw6fzRH", False),
|
|
113
|
+
("dogecoin", "D7Y55LJ4f4M4M4M4M4M4M4M4M4M4M4M4M4M", True),
|
|
114
|
+
("dogecoin", "B7Y55LJ4f4M4M4M4M4M4M4M4M4M4M4M4M4M", False),
|
|
115
|
+
],
|
|
116
|
+
)
|
|
117
|
+
def test_validate_wallet_address(network_id, address, expected):
|
|
118
|
+
from token_network import validate_wallet_address
|
|
119
|
+
|
|
120
|
+
assert validate_wallet_address(network_id, address) is expected
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
def test_network_config_exposes_wallet_address_regex():
|
|
124
|
+
cfg = network.ethereum.config
|
|
125
|
+
assert cfg.wallet_address_regex == r"^(0x)[0-9A-Fa-f]{40}$"
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def test_network_details_include_wallet_address_regex():
|
|
129
|
+
eth = network("ethereum")
|
|
130
|
+
assert eth.wallet_address_regex == r"^(0x)[0-9A-Fa-f]{40}$"
|
|
131
|
+
assert eth.__dict__()["config"]["wallet_address_regex"] == r"^(0x)[0-9A-Fa-f]{40}$"
|
|
132
|
+
assert eth.to_dict()["config"]["wallet_address_regex"] == r"^(0x)[0-9A-Fa-f]{40}$"
|
|
@@ -8,6 +8,7 @@ Usage:
|
|
|
8
8
|
bitcoin = network("bitcoin")
|
|
9
9
|
bitcoin.decimal # 8 (base token decimals)
|
|
10
10
|
bitcoin.confirmation_number # 2
|
|
11
|
+
bitcoin.wallet_address_regex # wallet validation regex for this network
|
|
11
12
|
bitcoin.__dict__() # all network data: {"config": {...}, "tokens": [...]}
|
|
12
13
|
bitcoin.config
|
|
13
14
|
bitcoin.tokens # list of TokenOnNetwork objects
|
|
@@ -80,6 +81,16 @@ def get_token_network(token_identifier: str, network_identifier: str) -> TokenOn
|
|
|
80
81
|
return _network.get_token_network(token_identifier, network_identifier)
|
|
81
82
|
|
|
82
83
|
|
|
84
|
+
def validate_wallet_address(network_identifier: str, address: str) -> bool:
|
|
85
|
+
"""
|
|
86
|
+
Validate a wallet address against the network's wallet_address_regex pattern.
|
|
87
|
+
|
|
88
|
+
Example:
|
|
89
|
+
validate_wallet_address("ethereum", "0xdAC17F958D2ee523a2206206994597C13D831ec7") # True
|
|
90
|
+
"""
|
|
91
|
+
return _network.validate_wallet_address(network_identifier, address)
|
|
92
|
+
|
|
93
|
+
|
|
83
94
|
def get_token_on_network(*, network: str, token_abbr: str) -> TokenOnNetworkDto:
|
|
84
95
|
"""
|
|
85
96
|
Get token-on-network object by network and token symbol/slug (e.g. USDT).
|
|
@@ -101,6 +112,7 @@ __all__ = [
|
|
|
101
112
|
"get_network",
|
|
102
113
|
"get_token_network",
|
|
103
114
|
"get_token_on_network",
|
|
115
|
+
"validate_wallet_address",
|
|
104
116
|
"TokenNetworkError",
|
|
105
117
|
"NetworkAccessor",
|
|
106
118
|
"TokenOnNetworkDto",
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import re
|
|
5
6
|
from typing import Any
|
|
6
7
|
|
|
7
8
|
from ._loader import load_all
|
|
@@ -62,6 +63,16 @@ class _NetworkNode:
|
|
|
62
63
|
"""Required number of confirmations for this network."""
|
|
63
64
|
return self.config.confirmation_number
|
|
64
65
|
|
|
66
|
+
@property
|
|
67
|
+
def wallet_address_regex(self) -> str:
|
|
68
|
+
"""Regex pattern for validating wallet addresses on this network."""
|
|
69
|
+
return self.config.wallet_address_regex
|
|
70
|
+
|
|
71
|
+
@property
|
|
72
|
+
def approximate_confirmation_time(self) -> int:
|
|
73
|
+
"""Approximate time (in seconds) to reach the required confirmations."""
|
|
74
|
+
return self.config.approximate_confirmation_time
|
|
75
|
+
|
|
65
76
|
@property
|
|
66
77
|
def tokens(self) -> list[TokenOnNetworkDto]:
|
|
67
78
|
"""List of token objects on this network (Pydantic TokenOnNetwork models)."""
|
|
@@ -231,5 +242,14 @@ class NetworkAccessor:
|
|
|
231
242
|
return self.get_token_network(token_abbr, network)
|
|
232
243
|
|
|
233
244
|
|
|
245
|
+
def validate_wallet_address(self, network_identifier: str, address: str) -> bool:
|
|
246
|
+
"""Return True if address matches the network's wallet_address_regex."""
|
|
247
|
+
config = self.get_network(network_identifier).config
|
|
248
|
+
pattern = (config.wallet_address_regex or "").strip()
|
|
249
|
+
if not pattern:
|
|
250
|
+
return False
|
|
251
|
+
return re.fullmatch(pattern, (address or "").strip()) is not None
|
|
252
|
+
|
|
253
|
+
|
|
234
254
|
# Singleton used as `network`
|
|
235
255
|
network = NetworkAccessor()
|
|
@@ -7,6 +7,21 @@ from typing import Any
|
|
|
7
7
|
from pydantic import BaseModel, ConfigDict, computed_field
|
|
8
8
|
|
|
9
9
|
|
|
10
|
+
class _CallableFieldDict(dict):
|
|
11
|
+
"""
|
|
12
|
+
A dict subclass that doubles as the pydantic field storage and is also
|
|
13
|
+
callable, so that ``model.__dict__()`` returns the fully serialized data.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
_model: "BaseModel | None" = None
|
|
17
|
+
|
|
18
|
+
def __call__(self) -> dict[str, Any]:
|
|
19
|
+
model = self._model
|
|
20
|
+
if model is not None:
|
|
21
|
+
return model.model_dump()
|
|
22
|
+
return dict(self)
|
|
23
|
+
|
|
24
|
+
|
|
10
25
|
class TokenDto(BaseModel):
|
|
11
26
|
"""Token definition (from tokens.yaml): slug, symbol, name, precision, factor."""
|
|
12
27
|
|
|
@@ -44,9 +59,11 @@ class NetworkConfigDto(BaseModel):
|
|
|
44
59
|
base_token_decimal: int = 0
|
|
45
60
|
confirmation_number: int = 0
|
|
46
61
|
confirmation_check_time: int = 0
|
|
62
|
+
approximate_confirmation_time: int = 0
|
|
47
63
|
resource_providing_amount: float = 0.0
|
|
48
64
|
resource_providing_below_threshold: float = 0.0
|
|
49
65
|
is_tag_based: bool = False
|
|
66
|
+
wallet_address_regex: str = ""
|
|
50
67
|
|
|
51
68
|
def __getitem__(self, key: str) -> Any:
|
|
52
69
|
"""Dict-like access (e.g. config['network_type'])."""
|
|
@@ -71,6 +88,12 @@ class TokenOnNetworkDto(BaseModel):
|
|
|
71
88
|
"""Alias for decimal."""
|
|
72
89
|
return self.decimal
|
|
73
90
|
|
|
91
|
+
def model_post_init(self, __context: Any) -> None:
|
|
92
|
+
"""Wrap field storage so ``obj.__dict__()`` returns the full serialized dict."""
|
|
93
|
+
callable_dict = _CallableFieldDict(self.__dict__)
|
|
94
|
+
callable_dict._model = self
|
|
95
|
+
object.__setattr__(self, "__dict__", callable_dict)
|
|
96
|
+
|
|
74
97
|
def to_dict(self) -> dict[str, Any]:
|
|
75
98
|
"""Return all token-on-network data as a dict."""
|
|
76
99
|
return self.model_dump()
|
|
@@ -2,96 +2,112 @@ networks:
|
|
|
2
2
|
ethereum:
|
|
3
3
|
slug: ethereum
|
|
4
4
|
name: Ethereum
|
|
5
|
+
wallet_address_regex: "^(0x)[0-9A-Fa-f]{40}$"
|
|
5
6
|
network_type: EVM
|
|
6
7
|
token_standard: ERC20
|
|
7
8
|
base_token: ETH
|
|
8
9
|
base_token_decimal: 18
|
|
9
10
|
confirmation_number: 10
|
|
10
11
|
confirmation_check_time: 2
|
|
12
|
+
approximate_confirmation_time: 120
|
|
11
13
|
resource_providing_amount: 0.0005
|
|
12
14
|
resource_providing_below_threshold: 0.0001
|
|
13
15
|
is_tag_based: false
|
|
14
16
|
polygon:
|
|
15
17
|
slug: polygon
|
|
16
18
|
name: Polygon
|
|
19
|
+
wallet_address_regex: "^(0x)[0-9A-Fa-f]{40}$"
|
|
17
20
|
network_type: EVM
|
|
18
21
|
token_standard: ERC20
|
|
19
22
|
base_token: POL
|
|
20
23
|
base_token_decimal: 18
|
|
21
24
|
confirmation_number: 128
|
|
22
25
|
confirmation_check_time: 1
|
|
26
|
+
approximate_confirmation_time: 120
|
|
23
27
|
resource_providing_amount: 1
|
|
24
28
|
resource_providing_below_threshold: 0.5
|
|
25
29
|
is_tag_based: false
|
|
26
30
|
bsc:
|
|
27
31
|
slug: bsc
|
|
28
32
|
name: BNB Smart Chain
|
|
33
|
+
wallet_address_regex: "^(0x)[0-9A-Fa-f]{40}$"
|
|
29
34
|
network_type: EVM
|
|
30
35
|
token_standard: ERC20 # BEP20
|
|
31
36
|
base_token: BNB
|
|
32
37
|
base_token_decimal: 18
|
|
33
38
|
confirmation_number: 10
|
|
34
39
|
confirmation_check_time: 1
|
|
40
|
+
approximate_confirmation_time: 60
|
|
35
41
|
resource_providing_amount: 0.0005
|
|
36
42
|
resource_providing_below_threshold: 0.0001
|
|
37
43
|
is_tag_based: false
|
|
38
44
|
tron:
|
|
39
45
|
slug: tron
|
|
40
46
|
name: Tron
|
|
47
|
+
wallet_address_regex: "^T[1-9A-HJ-NP-Za-km-z]{33}$"
|
|
41
48
|
network_type: TVM
|
|
42
49
|
token_standard: TRC20
|
|
43
50
|
base_token: TRX
|
|
44
51
|
base_token_decimal: 6
|
|
45
52
|
confirmation_number: 20
|
|
46
53
|
confirmation_check_time: 1
|
|
54
|
+
approximate_confirmation_time: 60
|
|
47
55
|
resource_providing_amount: 10
|
|
48
56
|
resource_providing_below_threshold: 7
|
|
49
57
|
is_tag_based: false
|
|
50
58
|
solana:
|
|
51
59
|
slug: solana
|
|
52
60
|
name: Solana
|
|
61
|
+
wallet_address_regex: "^[1-9A-HJ-NP-Za-km-z]{32,44}$"
|
|
53
62
|
network_type: SOLANA
|
|
54
63
|
token_standard: SPL
|
|
55
64
|
base_token: SOL
|
|
56
65
|
base_token_decimal: 9
|
|
57
66
|
confirmation_number: 5
|
|
58
67
|
confirmation_check_time: 1
|
|
68
|
+
approximate_confirmation_time: 30
|
|
59
69
|
resource_providing_amount: 0.005
|
|
60
70
|
resource_providing_below_threshold: 0.001
|
|
61
71
|
is_tag_based: false
|
|
62
72
|
bitcoin:
|
|
63
73
|
slug: bitcoin
|
|
64
74
|
name: Bitcoin
|
|
75
|
+
wallet_address_regex: "^[13][a-km-zA-HJ-NP-Z1-9]{25,34}$|^(bc1)[0-9A-Za-z]{39,59}$"
|
|
65
76
|
network_type: UTXO
|
|
66
77
|
token_standard: BTC
|
|
67
78
|
base_token: BTC
|
|
68
79
|
base_token_decimal: 8
|
|
69
80
|
confirmation_number: 2
|
|
70
81
|
confirmation_check_time: 2
|
|
82
|
+
approximate_confirmation_time: 1200
|
|
71
83
|
resource_providing_amount: 0
|
|
72
84
|
resource_providing_below_threshold: 0
|
|
73
85
|
is_tag_based: false
|
|
74
86
|
ripple:
|
|
75
87
|
slug: ripple
|
|
76
88
|
name: XRP Ledger
|
|
89
|
+
wallet_address_regex: "^r[1-9A-HJ-NP-Za-km-z]{25,34}$"
|
|
77
90
|
network_type: XRPL
|
|
78
91
|
token_standard: XRP
|
|
79
92
|
base_token: XRP
|
|
80
93
|
base_token_decimal: 6
|
|
81
94
|
confirmation_number: 1
|
|
82
95
|
confirmation_check_time: 1
|
|
96
|
+
approximate_confirmation_time: 30
|
|
83
97
|
resource_providing_amount: 0
|
|
84
98
|
resource_providing_below_threshold: 0
|
|
85
99
|
is_tag_based: true
|
|
86
100
|
dogecoin:
|
|
87
101
|
slug: dogecoin
|
|
88
102
|
name: Dogecoin
|
|
103
|
+
wallet_address_regex: "^(D|A|9)[a-km-zA-HJ-NP-Z1-9]{33,34}$"
|
|
89
104
|
network_type: UTXO
|
|
90
105
|
token_standard: DOGE
|
|
91
106
|
base_token: DOGE
|
|
92
107
|
base_token_decimal: 8
|
|
93
108
|
confirmation_number: 6
|
|
94
109
|
confirmation_check_time: 5
|
|
110
|
+
approximate_confirmation_time: 300
|
|
95
111
|
resource_providing_amount: 0
|
|
96
112
|
resource_providing_below_threshold: 0
|
|
97
113
|
is_tag_based: false
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: token-network
|
|
3
|
-
Version: 0.4.
|
|
3
|
+
Version: 0.4.6
|
|
4
4
|
Summary: Validate input and return token network config (e.g. network.bitcoin, network.bsc.usdt)
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: blockchain,tokens,networks,crypto,config
|
|
@@ -49,10 +49,36 @@ bitcoin = network("bitcoin")
|
|
|
49
49
|
|
|
50
50
|
bitcoin.decimal # 8 (base token decimals)
|
|
51
51
|
bitcoin.confirmation_number # 2 (required confirmations)
|
|
52
|
+
bitcoin.wallet_address_regex # wallet validation regex for this network
|
|
53
|
+
bitcoin.approximate_confirmation_time # 1200 (approx. seconds to confirm)
|
|
52
54
|
bitcoin.config # NetworkConfigDto (Pydantic)
|
|
53
55
|
bitcoin.__dict__() # Full data: {"config": {...}, "tokens": [...]}
|
|
54
56
|
```
|
|
55
57
|
|
|
58
|
+
### Wallet address validation
|
|
59
|
+
|
|
60
|
+
Each network includes a `wallet_address_regex` pattern in its config. Use it to validate addresses for that chain:
|
|
61
|
+
|
|
62
|
+
```python
|
|
63
|
+
from token_network import network, get_network, validate_wallet_address
|
|
64
|
+
|
|
65
|
+
# Direct property (same style as .decimal / .confirmation_number)
|
|
66
|
+
network("ethereum").wallet_address_regex
|
|
67
|
+
# ^(0x)[0-9A-Fa-f]{40}$
|
|
68
|
+
|
|
69
|
+
# Via config
|
|
70
|
+
network("ethereum").config.wallet_address_regex
|
|
71
|
+
get_network("bitcoin").config.wallet_address_regex
|
|
72
|
+
|
|
73
|
+
# In full network dict
|
|
74
|
+
network("ethereum").to_dict()["config"]["wallet_address_regex"]
|
|
75
|
+
|
|
76
|
+
# Validate an address
|
|
77
|
+
validate_wallet_address("ethereum", "0xdAC17F958D2ee523a2206206994597C13D831ec7") # True
|
|
78
|
+
validate_wallet_address("ethereum", "0x123") # False
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
|
|
56
82
|
### List tokens on a network
|
|
57
83
|
|
|
58
84
|
```python
|
|
@@ -151,7 +177,9 @@ except TokenNetworkError as e:
|
|
|
151
177
|
| What you want | How |
|
|
152
178
|
|---------------|-----|
|
|
153
179
|
| Network by name | `network("bitcoin")` or `network.bitcoin` |
|
|
154
|
-
| Base decimals / confirmations | `network("bitcoin").decimal`, `.confirmation_number` |
|
|
180
|
+
| Base decimals / confirmations | `network("bitcoin").decimal`, `.confirmation_number`, `.approximate_confirmation_time` |
|
|
181
|
+
| Wallet address regex | `network("ethereum").wallet_address_regex` or `.config.wallet_address_regex` |
|
|
182
|
+
| Validate wallet address | `validate_wallet_address("ethereum", "0x...")` → `True` / `False` |
|
|
155
183
|
| Full network data as dict | `network("bitcoin").__dict__()` or `.to_dict()` |
|
|
156
184
|
| Tokens on a network | `network("ethereum").tokens` → list of `TokenOnNetworkDto` |
|
|
157
185
|
| One token on a network | `get_token_on_network(network="ethereum", token_abbr="USDT")` or `network.ethereum.usdt` |
|
|
@@ -164,7 +192,7 @@ All identifiers are **case-insensitive**. Unknown network/token raises `TokenNet
|
|
|
164
192
|
## Pydantic models
|
|
165
193
|
|
|
166
194
|
- **`TokenDto`** — Token definition (slug, symbol, name, precision, factor). From `get_token()`.
|
|
167
|
-
- **`NetworkConfigDto`** — Chain config (slug, name, network_type, base_token_decimal, confirmation_number, …). From `network("x").config` and inside `TokenOnNetworkDto.network`.
|
|
195
|
+
- **`NetworkConfigDto`** — Chain config (slug, name, network_type, base_token_decimal, confirmation_number, wallet_address_regex, …). From `network("x").config` and inside `TokenOnNetworkDto.network`.
|
|
168
196
|
- **`TokenOnNetworkDto`** — Token on a network (network, token, contract_address, decimal, native, type). From `get_token_on_network()`, `get_token_network()`, `network.ethereum.usdt`.
|
|
169
197
|
- **`NetworkDataDto`** — Result of `get_network()`: `config` + `tokens` (list of `TokenOnNetworkDto`).
|
|
170
198
|
|
|
@@ -174,7 +202,7 @@ Use `.model_dump()` to export any model as a dict.
|
|
|
174
202
|
|
|
175
203
|
YAML under `token_network/data/`:
|
|
176
204
|
|
|
177
|
-
- `networks.yaml` — chain config
|
|
205
|
+
- `networks.yaml` — chain config (including `wallet_address_regex` per network)
|
|
178
206
|
- `tokens.yaml` — token definitions
|
|
179
207
|
- `token_networks.yaml` — mainnet bindings (token + network → contract, decimals)
|
|
180
208
|
- `token_networks_testnet.yaml` — testnet bindings (used with `NetworkAccessor(testnet=True)`)
|
|
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
|