forked from MudwoodLabs/pyrxd
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmnemonic_to_key.py
More file actions
89 lines (69 loc) · 3.38 KB
/
Copy pathmnemonic_to_key.py
File metadata and controls
89 lines (69 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
#!/usr/bin/env python3
"""Derive Radiant keys and addresses from a BIP39 mnemonic.
Two flows are demonstrated, in order of how most users will want to
approach the problem:
1. ``HdWallet.from_mnemonic`` — the high-level path. Returns a full HD
wallet at the correct Radiant BIP44 path (``m/44'/512'/0'``) with
address tracking, gap-limit discovery, and optional encrypted
persistence. This is the recommended entry point.
2. ``bip44_derive_xprv_from_mnemonic`` — the low-level path. Returns
the account xprv so you can derive a single private key at a
specific child index. Useful when you only want one key, or when
migrating code from another library that exposed the seed-to-key
primitives directly.
Radiant note
------------
Radiant's officially registered BIP44 coin type per SLIP-0044 is **512**, not 0
(Bitcoin). Code copied from Bitcoin examples that hardcodes
``m/44'/0'/0'/0/0`` will derive the wrong addresses. Both helpers here use
the correct Radiant path by default.
Tangem (the hardware wallet) also uses ``m/44'/512'/0'/0/0`` for Radiant.
Earlier versions of pyrxd (and this example) cited coin type 236, which is
actually BSV's. Users with funds derived at the old path can override via
``RXD_PY_SDK_BIP44_DERIVATION_PATH=m/44'/236'/0'`` to recover and sweep them.
Usage
-----
# Use the demo mnemonic baked into this script:
python examples/mnemonic_to_key.py
# Or supply your own (do NOT share a real mnemonic on the command line
# in production — this is for local testing only):
MNEMONIC="word1 word2 ... word12" python examples/mnemonic_to_key.py
"""
from __future__ import annotations
import os
import sys
sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..", "src"))
from pyrxd.hd import HdWallet, bip44_derive_xprv_from_mnemonic
# A well-known BIP39 test vector mnemonic. NEVER use this for real funds —
# the seed and every key derived from it are public. It is here purely so
# the example runs without configuration.
DEMO_MNEMONIC = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about"
def high_level(mnemonic: str) -> None:
"""Build a full HD wallet from the mnemonic."""
print("=== HdWallet.from_mnemonic ===")
wallet = HdWallet.from_mnemonic(mnemonic)
print(f"first receive address: {wallet.next_receive_address()}")
# next_receive_address keeps returning the same address until it is
# marked used (after a refresh against the network finds history).
print(f"same again (unused): {wallet.next_receive_address()}")
print()
def low_level(mnemonic: str) -> None:
"""Derive a single private key at m/44'/512'/0'/0/0."""
print("=== bip44_derive_xprv_from_mnemonic ===")
# Default path is m/44'/512'/0' (Radiant account 0, per SLIP-0044).
account_xprv = bip44_derive_xprv_from_mnemonic(mnemonic)
# External chain (change=0), first address (index=0).
child = account_xprv.ckd(0).ckd(0)
priv = child.private_key()
print("path: m/44'/512'/0'/0/0")
print(f"WIF: {priv.wif()}")
print(f"address: {priv.public_key().address()}")
print()
def main() -> None:
mnemonic = os.environ.get("MNEMONIC", DEMO_MNEMONIC)
if mnemonic == DEMO_MNEMONIC:
print("Using the public BIP39 test-vector mnemonic. Do not send funds to these addresses.\n")
high_level(mnemonic)
low_level(mnemonic)
if __name__ == "__main__":
main()