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.
Files changed (19) hide show
  1. {token_network-0.4.4 → token_network-0.4.6}/PKG-INFO +32 -4
  2. {token_network-0.4.4 → token_network-0.4.6}/README.md +31 -3
  3. {token_network-0.4.4 → token_network-0.4.6}/pyproject.toml +1 -1
  4. {token_network-0.4.4 → token_network-0.4.6}/setup.py +1 -1
  5. {token_network-0.4.4 → token_network-0.4.6}/tests/test_network.py +40 -0
  6. {token_network-0.4.4 → token_network-0.4.6}/token_network/__init__.py +12 -0
  7. {token_network-0.4.4 → token_network-0.4.6}/token_network/_accessor.py +20 -0
  8. {token_network-0.4.4 → token_network-0.4.6}/token_network/_models.py +23 -0
  9. {token_network-0.4.4 → token_network-0.4.6}/token_network/data/networks.yaml +16 -0
  10. {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/PKG-INFO +32 -4
  11. {token_network-0.4.4 → token_network-0.4.6}/setup.cfg +0 -0
  12. {token_network-0.4.4 → token_network-0.4.6}/token_network/_loader.py +0 -0
  13. {token_network-0.4.4 → token_network-0.4.6}/token_network/data/token_networks.yaml +0 -0
  14. {token_network-0.4.4 → token_network-0.4.6}/token_network/data/token_networks_testnet.yaml +0 -0
  15. {token_network-0.4.4 → token_network-0.4.6}/token_network/data/tokens.yaml +0 -0
  16. {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/SOURCES.txt +0 -0
  17. {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/dependency_links.txt +0 -0
  18. {token_network-0.4.4 → token_network-0.4.6}/token_network.egg-info/requires.txt +0 -0
  19. {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.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.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.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.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