neo-n3-wallet v0.2.1
The Python wallet library for Neo N3 — with BIP-39 mnemonic support, HD key derivation, and full key management. Filling the gap that Rust and neon-js filled for other languages.
Aligned with Neo-CLI v3.10.0's expanded BIP-39 support (12 and 24-word phrases).
pip install neo-n3-wallet
Features
| Feature | Details |
|---|---|
| BIP-39 Mnemonics | 12 / 15 / 18 / 21 / 24 words, 8 languages |
| HD Derivation | BIP-32 over secp256r1 (NIST P-256), BIP-44 path m/44'/888'/0'/0/0 |
| NEP-2 Encryption | scrypt + AES-256-ECB passphrase-protected private keys |
| NEP-6 Wallets | Save / load standard Neo wallet JSON files |
| WIF | Wallet Import Format encode / decode |
| Signing | secp256r1 sign & verify |
What's New in v0.2.1
- Fixed
verifymsg()— it previously always returnedFalse. The implementation now recovers candidate public keys from the ECDSA signature and compares the derived Neo N3 address, matching Neo-CLI'sverifymsgRPC behavior. - Correct message-signing prefix —
signmsg()/verifymsg()now use the Neo magic prefix"Neo Signed Message:\n"before SHA-256 hashing, so signatures are compatible with the official neo-project/neo implementation.
What's New in v0.2.0
- Neo-CLI v3.10.0 RPC parity: added local helpers
signmsg()/verifymsg()for message-signing workflows. - DeferredRelay: added
DeferredRelayAttribute+create_deferred_relay_attribute()helpers for attaching DeferredRelay-compatible attributes to raw transactions. - NEP-6 mnemonic wallet interop: added
Wallet.from_mnemonic(mnemonic_phrase, passphrase="")for mnemonic-first wallet creation aligned with Neo-CLI v3.10.0 expectations. - Gorgon hard fork fee estimation: added
fee_estimate(tx_size_bytes, fork="gorgon")helper with a simplified Gorgon-aware fee model.
What's New in v0.1.2 — NEP-6 Compliance Fix
Full NEP-6 spec compliance after COZ team review:
- NFC password normalization — passphrase is Unicode NFC-normalized before any scrypt/encrypt/decrypt operation per NEP-2 spec
- Variable scrypt params — wallet JSON
n/r/pvalues are now read and applied instead of ignored lock,contract,extrafields — Account now stores and round-trips all NEP-6 fields includingcontract.script(base64),contract.parameters,contract.deployed, andextra- Single default account — setting one account as default now clears all others; enforced on load too
- Thread safety —
threading.RLock()added to all wallet operations wallet.save()password fix — tracks current password so save() always uses the right one after a password change- Duplicate prevention —
derive_accounts()andload()deduplicate by address
Quick Start
from neo_n3_wallet import Wallet, MnemonicManager, Account, KeyPair
# --- Create a brand-new HD wallet (24-word mnemonic) ---
wallet = Wallet.create(word_count=24)
print(wallet.mnemonic) # 24 BIP-39 words
# Derive the first account (m/44'/888'/0'/0/0)
account = wallet.derive_account(index=0)
print(account.address) # NXxx... Neo N3 address
# Derive 5 accounts at once
accounts = wallet.derive_accounts(count=5)
# Save as NEP-6 JSON (accounts are encrypted with the passphrase)
wallet.save("my_wallet.json", passphrase="s3cur3!")
# --- Restore a wallet from an existing mnemonic ---
wallet2 = Wallet.from_mnemonic(
"abandon abandon abandon ... art",
passphrase="" # optional BIP-39 passphrase
)
# --- Load a NEP-6 file ---
loaded = Wallet.load("my_wallet.json", passphrase="s3cur3!")
print(loaded.accounts[0].address)
Mnemonic Management
from neo_n3_wallet import MnemonicManager
m = MnemonicManager() # default: English
phrase = m.generate(24) # 24-word mnemonic
assert m.validate(phrase) # True
seed = m.to_seed(phrase) # 64-byte BIP-39 seed
entropy = m.to_entropy(phrase) # recover original entropy
restored = m.from_entropy(entropy) # back to phrase
# Other languages
m_jp = MnemonicManager("japanese")
phrase_jp = m_jp.generate(12)
Key Pair & Accounts
from neo_n3_wallet import KeyPair, Account
# Random key pair
kp = KeyPair.generate()
print(kp.address) # Neo N3 address
print(kp.public_key_hex) # 33-byte compressed public key
print(kp.to_wif()) # WIF-encoded private key
# From WIF
kp2 = KeyPair.from_wif("KwdMAjGmer...")
# Sign & verify
sig = kp.sign(b"my message")
assert kp.verify(b"my message", sig)
# Account with NEP-2 encryption
acct = Account.from_private_key(bytes.fromhex("..."))
nep2 = acct.encrypt("my-passphrase") # encrypt in-place
acct.lock() # wipe key from memory
acct.unlock("my-passphrase") # restore it
HD Derivation Paths
Neo N3 uses SLIP-0044 coin type 888 and secp256r1:
m / 44' / 888' / account' / change / index
Wallet.derivation_path(account=0, change=0, index=0)
# → "m/44'/888'/0'/0/0"
Running Tests
python -m pytest tests/ -v --no-cov # fast
python -m pytest tests/ -v # with coverage
Project Layout
neo_n3_wallet/
├── __init__.py public API
├── wallet.py Wallet (HD + NEP-6)
├── account.py Account (NEP-2 lock/unlock)
├── key_pair.py KeyPair (sign / verify)
├── mnemonic.py BIP-39 MnemonicManager
├── hd.py BIP-32 derivation (secp256r1)
├── nep2.py NEP-2 encrypt / decrypt
├── wif.py WIF encode / decode
├── address.py Neo N3 address utilities
├── crypto.py secp256r1 primitives
├── constants.py Neo N3 constants
└── exceptions.py Custom exceptions
License
Apache 2.0
Metadata
Release files for neo-n3-wallet 0.2.1
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| neo_n3_wallet-0.2.1.tar.gz | 32.8 kB | Without provenance | Details for neo_n3_wallet-0.2.1.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| neo_n3_wallet-0.2.1-py3-none-any.whl | Python 3 | none | any | Details for neo_n3_wallet-0.2.1-py3-none-any.whl |
Total release size: 59.3 kB
Release files / neo_n3_wallet-0.2.1.tar.gz
| Download URL | neo_n3_wallet-0.2.1.tar.gz |
|---|---|
| Size | 32.8 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
d5b11c217c9e7d4c91510ab53416e77644d1a95a88b4d6708cedb2777771e8e8
|
|
BLAKE2b-256 checksum How to use checksums |
1039936dc86700c6bce1d6a89464d92b4e52a58907c75a656ec1d9658299bf6f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Release files / neo_n3_wallet-0.2.1-py3-none-any.whl
| Download URL | neo_n3_wallet-0.2.1-py3-none-any.whl |
|---|---|
| Size | 26.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
a5a3545a34ab7355d1c8c9534a04504ff29ddede17fd564b3e18962e045fe880
|
|
BLAKE2b-256 checksum How to use checksums |
329dda1a81fffb9f571df1742bee0680601e1157b84a24bac9dc488558d3bd2f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.14.6
|
Security for neo-n3-wallet 0.2.1
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.