Skip to content

Commit 075f739

Browse files
committed
Updates
- Introduce `DEFAULT_SEMANTIC` to cryptocurrency description; - Introduce `"base58check"` semantic (for DeSo); - Introduce `address()` in `HDWallet`; - Fix xpub/xprv address prefixes for DESOTEST. The default semantic for Bitcoin is "p2wpkh".
1 parent aa0c4a3 commit 075f739

File tree

2 files changed

+47
-45
lines changed

2 files changed

+47
-45
lines changed

hdwallet/cryptocurrencies.py

Lines changed: 13 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -62,17 +62,19 @@ class Cryptocurrency(NestedNamespace):
6262
SOURCE_CODE: Optional[str]
6363
COIN_TYPE: CoinType
6464

65-
SCRIPT_ADDRESS: int
65+
SCRIPT_ADDRESS: Optional[int] = None
6666
PUBLIC_KEY_ADDRESS: int = 0
6767
PRIVATE_KEY_ADDRESS: int = 0
68-
SEGWIT_ADDRESS: SegwitAddress
68+
SEGWIT_ADDRESS: Optional[SegwitAddress] = None
6969

7070
EXTENDED_PRIVATE_KEY: ExtendedPrivateKey
7171
EXTENDED_PUBLIC_KEY: ExtendedPublicKey
7272

7373
MESSAGE_PREFIX: Optional[str]
7474
DEFAULT_PATH: str
75-
WIF_SECRET_KEY: int
75+
WIF_SECRET_KEY: Optional[int] = None
76+
77+
DEFAULT_SEMANTIC: str = "p2pkh"
7678

7779

7880
class AnonMainnet(Cryptocurrency):
@@ -713,6 +715,7 @@ class BitcoinMainnet(Cryptocurrency):
713715
MESSAGE_PREFIX = "\x18Bitcoin Signed Message:\n"
714716
DEFAULT_PATH = f"m/44'/{str(COIN_TYPE)}/0'/0/0"
715717
WIF_SECRET_KEY = 0x80
718+
DEFAULT_SEMANTIC = "p2wpkh"
716719

717720

718721
class BitcoinPlusMainnet(Cryptocurrency):
@@ -833,6 +836,7 @@ class BitcoinTestnet(Cryptocurrency):
833836
MESSAGE_PREFIX = "\x18Bitcoin Signed Message:\n"
834837
DEFAULT_PATH = f"m/44'/{str(COIN_TYPE)}/0'/0/0"
835838
WIF_SECRET_KEY = 0xef
839+
DEFAULT_SEMANTIC = "p2wpkh"
836840

837841

838842
class BitcoinZMainnet(Cryptocurrency):
@@ -1686,34 +1690,18 @@ class DeSoMainnet(Cryptocurrency):
16861690
"HARDENED": True
16871691
})
16881692

1689-
SCRIPT_ADDRESS = 0x05
16901693
PUBLIC_KEY_ADDRESS = 0xCD1400
16911694
PRIVATE_KEY_ADDRESS = 0x350000
1692-
SEGWIT_ADDRESS = SegwitAddress({
1693-
"HRP": "bc",
1694-
"VERSION": 0x00
1695-
})
1696-
16971695
EXTENDED_PRIVATE_KEY = ExtendedPrivateKey({
1698-
"P2PKH": 0x0488ade4,
1699-
"P2SH": 0x0488ade4,
1700-
"P2WPKH": 0x04b2430c,
1701-
"P2WPKH_IN_P2SH": 0x049d7878,
1702-
"P2WSH": 0x02aa7a99,
1703-
"P2WSH_IN_P2SH": 0x0295b005
1696+
"BASE58CHECK": 0x0488ade4
17041697
})
17051698
EXTENDED_PUBLIC_KEY = ExtendedPublicKey({
1706-
"P2PKH": 0x0488b21e,
1707-
"P2SH": 0x0488b21e,
1708-
"P2WPKH": 0x04b24746,
1709-
"P2WPKH_IN_P2SH": 0x049d7cb2,
1710-
"P2WSH": 0x02aa7ed3,
1711-
"P2WSH_IN_P2SH": 0x0295b43f
1699+
"BASE58CHECK": 0x0488b21e
17121700
})
17131701

17141702
MESSAGE_PREFIX = "\x18DeSo Signed Message:\n"
17151703
DEFAULT_PATH = f"m/44'/{str(COIN_TYPE)}/0'/0/0"
1716-
WIF_SECRET_KEY = 0x80
1704+
DEFAULT_SEMANTIC = "base58check"
17171705

17181706

17191707
class DeSoTestnet(Cryptocurrency):
@@ -1727,34 +1715,18 @@ class DeSoTestnet(Cryptocurrency):
17271715
"HARDENED": True
17281716
})
17291717

1730-
SCRIPT_ADDRESS = 0x05
17311718
PUBLIC_KEY_ADDRESS = 0x11C200
17321719
PRIVATE_KEY_ADDRESS = 0x4F061B
1733-
SEGWIT_ADDRESS = SegwitAddress({
1734-
"HRP": "bc",
1735-
"VERSION": 0x00
1736-
})
1737-
17381720
EXTENDED_PRIVATE_KEY = ExtendedPrivateKey({
1739-
"P2PKH": 0x0488ade4,
1740-
"P2SH": 0x0488ade4,
1741-
"P2WPKH": 0x04b2430c,
1742-
"P2WPKH_IN_P2SH": 0x049d7878,
1743-
"P2WSH": 0x02aa7a99,
1744-
"P2WSH_IN_P2SH": 0x0295b005
1721+
"BASE58CHECK": 0x04358394
17451722
})
17461723
EXTENDED_PUBLIC_KEY = ExtendedPublicKey({
1747-
"P2PKH": 0x0488b21e,
1748-
"P2SH": 0x0488b21e,
1749-
"P2WPKH": 0x04b24746,
1750-
"P2WPKH_IN_P2SH": 0x049d7cb2,
1751-
"P2WSH": 0x02aa7ed3,
1752-
"P2WSH_IN_P2SH": 0x0295b43f
1724+
"BASE58CHECK": 0x043587cf
17531725
})
17541726

17551727
MESSAGE_PREFIX = "\x18DeSo Signed Message:\n"
17561728
DEFAULT_PATH = f"m/44'/{str(COIN_TYPE)}/0'/0/0"
1757-
WIF_SECRET_KEY = 0x80
1729+
DEFAULT_SEMANTIC = "base58check"
17581730

17591731

17601732
class DiamondMainnet(Cryptocurrency):

hdwallet/hdwallet.py

Lines changed: 34 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ class HDWallet:
6767
:type symbol: str
6868
:param cryptocurrency: Cryptocurrency instance, defaults to ``None``.
6969
:type cryptocurrency: Cryptocurrency
70-
:param semantic: Extended semantic, defaults to ``P2PKH``.
70+
:param semantic: Extended semantic
7171
:type semantic: str
7272
:param use_default_path: Use default derivation path, defaults to ``False``.
7373
:type use_default_path: bool
@@ -79,7 +79,7 @@ class HDWallet:
7979
"""
8080

8181
def __init__(self, symbol: str = "BTC", cryptocurrency: Any = None,
82-
semantic: str = "p2pkh", use_default_path: bool = False):
82+
semantic: str = None, use_default_path: bool = False):
8383
self._cryptocurrency: Any = None
8484
if cryptocurrency:
8585
if not issubclass(cryptocurrency, Cryptocurrency):
@@ -88,6 +88,9 @@ def __init__(self, symbol: str = "BTC", cryptocurrency: Any = None,
8888
else:
8989
self._cryptocurrency: Any = get_cryptocurrency(symbol=symbol)
9090

91+
if semantic is None:
92+
semantic = self._cryptocurrency.DEFAULT_SEMANTIC
93+
9194
self._strength: Optional[int] = None
9295
self._entropy: Optional[str] = None
9396
self._mnemonic: Optional[str] = None
@@ -878,6 +881,9 @@ def private_key_base58check(self) -> str:
878881
unhexlify(self.private_key())
879882
).decode()
880883

884+
def base58check_address(self) -> str:
885+
return self.public_key_base58check()
886+
881887
def strength(self) -> Optional[int]:
882888
"""
883889
Get Entropy strength.
@@ -1142,7 +1148,7 @@ def p2pkh_address(self) -> str:
11421148
network_hash160_bytes = _unhexlify(self._cryptocurrency.PUBLIC_KEY_ADDRESS) + public_key_hash
11431149
return ensure_string(base58.b58encode_check(network_hash160_bytes))
11441150

1145-
def p2sh_address(self) -> str:
1151+
def p2sh_address(self) -> Optional[str]:
11461152
"""
11471153
Get Pay to Script Hash (P2SH) address.
11481154
@@ -1157,6 +1163,9 @@ def p2sh_address(self) -> str:
11571163
"3Jp6ad4ErhibQmhSRfavbPRiUyg2xTTT4j"
11581164
"""
11591165

1166+
if self._cryptocurrency.SCRIPT_ADDRESS is None:
1167+
return None
1168+
11601169
compressed_public_key = unhexlify(self.compressed())
11611170
public_key_hash = hashlib.new('ripemd160', sha256(compressed_public_key).digest()).hexdigest()
11621171
public_key_hash_script = unhexlify("76a914" + public_key_hash + "88ac")
@@ -1181,6 +1190,8 @@ def p2wpkh_address(self) -> Optional[str]:
11811190

11821191
compressed_public_key = unhexlify(self.compressed())
11831192
public_key_hash = hashlib.new('ripemd160', sha256(compressed_public_key).digest()).digest()
1193+
if self._cryptocurrency.SEGWIT_ADDRESS is None:
1194+
return None
11841195
if self._cryptocurrency.SEGWIT_ADDRESS.HRP is None:
11851196
return None
11861197
return ensure_string(encode(self._cryptocurrency.SEGWIT_ADDRESS.HRP, 0, public_key_hash))
@@ -1200,10 +1211,15 @@ def p2wpkh_in_p2sh_address(self) -> Optional[str]:
12001211
"3CCrxPrHNa6ePbnB7qjh7S3vaPx9qiLc3e"
12011212
"""
12021213

1214+
if self._cryptocurrency.SCRIPT_ADDRESS is None:
1215+
return None
1216+
12031217
compressed_public_key = unhexlify(self.compressed())
12041218
public_key_hash = hashlib.new('ripemd160', sha256(compressed_public_key).digest()).hexdigest()
12051219
script_hash = hashlib.new('ripemd160', sha256(unhexlify("0014" + public_key_hash)).digest()).digest()
12061220
network_hash160_bytes = _unhexlify(self._cryptocurrency.SCRIPT_ADDRESS) + script_hash
1221+
if self._cryptocurrency.SEGWIT_ADDRESS is None:
1222+
return None
12071223
if self._cryptocurrency.SEGWIT_ADDRESS.HRP is None:
12081224
return None
12091225
return ensure_string(base58.b58encode_check(network_hash160_bytes))
@@ -1225,6 +1241,8 @@ def p2wsh_address(self) -> Optional[str]:
12251241

12261242
compressed_public_key = unhexlify("5121" + self.compressed() + "51ae")
12271243
script_hash = sha256(compressed_public_key).digest()
1244+
if self._cryptocurrency.SEGWIT_ADDRESS is None:
1245+
return None
12281246
if self._cryptocurrency.SEGWIT_ADDRESS.HRP is None:
12291247
return None
12301248
return ensure_string(encode(self._cryptocurrency.SEGWIT_ADDRESS.HRP, 0, script_hash))
@@ -1244,6 +1262,9 @@ def p2wsh_in_p2sh_address(self) -> Optional[str]:
12441262
"38YMonfh2yLFRViLrM2kdvZx8ctcp1vbbV"
12451263
"""
12461264

1265+
if self._cryptocurrency.SCRIPT_ADDRESS is None:
1266+
return None
1267+
12471268
compressed_public_key = unhexlify("5121" + self.compressed() + "51ae")
12481269
script_hash = unhexlify("0020" + sha256(compressed_public_key).hexdigest())
12491270
script_hash = hashlib.new('ripemd160', sha256(script_hash).digest()).digest()
@@ -1252,6 +1273,11 @@ def p2wsh_in_p2sh_address(self) -> Optional[str]:
12521273
return None
12531274
return ensure_string(base58.b58encode_check(network_hash160_bytes))
12541275

1276+
def address(self, semantic=None):
1277+
if semantic == None:
1278+
semantic = self._cryptocurrency.DEFAULT_SEMANTIC
1279+
return getattr(self, f"{semantic}_address")()
1280+
12551281
def wif(self) -> Optional[str]:
12561282
"""
12571283
Get Wallet Important Format.
@@ -1267,6 +1293,9 @@ def wif(self) -> Optional[str]:
12671293
"KzsHWUJsrTWUUhBGPfMMxLLydiH7NhEn6z7mKHXD5qNkUWaC4TEn"
12681294
"""
12691295

1296+
if self._cryptocurrency.WIF_SECRET_KEY is None:
1297+
return
1298+
12701299
return check_encode(_unhexlify(self._cryptocurrency.WIF_SECRET_KEY) + self._key.to_string() + b"\x01") if self._key else None
12711300

12721301
def dumps(self) -> dict:
@@ -1321,7 +1350,8 @@ def dumps(self) -> dict:
13211350
p2wpkh_in_p2sh=self.p2wpkh_in_p2sh_address(),
13221351
p2wsh=self.p2wsh_address(),
13231352
p2wsh_in_p2sh=self.p2wsh_in_p2sh_address()
1324-
)
1353+
),
1354+
address=self.address()
13251355
)
13261356

13271357

0 commit comments

Comments
 (0)