1"""TRX Address."""
2
3# standard
4import hashlib
5import re
6
7# local
8from validators.utils import validator
9
10
11def _base58_decode(addr: str) -> bytes:
12 """Decode a base58 encoded address."""
13 alphabet = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"
14 num = 0
15 for char in addr:
16 num = num * 58 + alphabet.index(char)
17 return num.to_bytes(25, byteorder="big")
18
19
20def _validate_trx_checksum_address(addr: str) -> bool:
21 """Validate TRX type checksum address."""
22 if len(addr) != 34:
23 return False
24
25 try:
26 address = _base58_decode(addr)
27 except ValueError:
28 return False
29
30 if len(address) != 25 or address[0] != 0x41:
31 return False
32
33 check_sum = hashlib.sha256(hashlib.sha256(address[:-4]).digest()).digest()[:4]
34 return address[-4:] == check_sum
35
36
37@validator
38def trx_address(value: str, /):
39 """Return whether or not given value is a valid tron address.
40
41 Full validation is implemented for TRC20 tron addresses.
42
43 Examples:
44 >>> trx_address('TLjfbTbpZYDQ4EoA4N5CLNgGjfbF8ZWz38')
45 True
46 >>> trx_address('TR2G7Rm4vFqF8EpY4U5xdLdQ7XgJ2U8Vd')
47 ValidationError(func=trx_address, args={'value': 'TR2G7Rm4vFqF8EpY4U5xdLdQ7XgJ2U8Vd'})
48
49 Args:
50 value:
51 Tron address string to validate.
52
53 Returns:
54 (Literal[True]): If `value` is a valid tron address.
55 (ValidationError): If `value` is an invalid tron address.
56 """
57 if not value:
58 return False
59
60 return re.compile(r"^[T][a-km-zA-HJ-NP-Z1-9]{33}$").match(
61 value
62 ) and _validate_trx_checksum_address(value)