crypto-wallet-manager 0.1.0__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.
- crypto_wallet_manager-0.1.0/LICENSE +21 -0
- crypto_wallet_manager-0.1.0/PKG-INFO +152 -0
- crypto_wallet_manager-0.1.0/README.md +122 -0
- crypto_wallet_manager-0.1.0/crypto_wallet_manager.egg-info/PKG-INFO +152 -0
- crypto_wallet_manager-0.1.0/crypto_wallet_manager.egg-info/SOURCES.txt +11 -0
- crypto_wallet_manager-0.1.0/crypto_wallet_manager.egg-info/dependency_links.txt +1 -0
- crypto_wallet_manager-0.1.0/crypto_wallet_manager.egg-info/entry_points.txt +2 -0
- crypto_wallet_manager-0.1.0/crypto_wallet_manager.egg-info/requires.txt +7 -0
- crypto_wallet_manager-0.1.0/crypto_wallet_manager.egg-info/top_level.txt +1 -0
- crypto_wallet_manager-0.1.0/pyproject.toml +64 -0
- crypto_wallet_manager-0.1.0/setup.cfg +4 -0
- crypto_wallet_manager-0.1.0/tests/test_wallet_manager.py +336 -0
- crypto_wallet_manager-0.1.0/wallet_manager.py +644 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 R. Kürşat Vuruşan
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: crypto-wallet-manager
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local CLI for BIP39 HD wallets: derive BTC/ETH addresses, keep secrets encrypted at rest, check balances.
|
|
5
|
+
Author: R. Kürşat Vuruşan
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/RKursatV/crypto-wallet-manager
|
|
8
|
+
Project-URL: Repository, https://github.com/RKursatV/crypto-wallet-manager
|
|
9
|
+
Project-URL: Changelog, https://github.com/RKursatV/crypto-wallet-manager/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Issues, https://github.com/RKursatV/crypto-wallet-manager/issues
|
|
11
|
+
Keywords: bitcoin,ethereum,bip39,bip44,bip84,wallet,cli
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Topic :: Security :: Cryptography
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: bip-utils<3,>=2.9
|
|
24
|
+
Requires-Dist: cryptography>=42
|
|
25
|
+
Requires-Dist: requests>=2.31
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# crypto-wallet-manager
|
|
32
|
+
|
|
33
|
+
A local CLI for managing crypto wallets: generate BIP39 HD wallets, derive
|
|
34
|
+
Bitcoin (native segwit, BIP84) and Ethereum (BIP44) addresses, keep secrets
|
|
35
|
+
encrypted at rest, and check on-chain balances via public APIs.
|
|
36
|
+
|
|
37
|
+
It deliberately does **not** sign or send transactions — it manages keys and
|
|
38
|
+
watches balances only.
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
Requires Python 3.10+.
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pipx install crypto-wallet-manager # from PyPI; puts `wallet-manager` on PATH
|
|
46
|
+
# or, from a checkout:
|
|
47
|
+
pipx install .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For development, or to run it without installing:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
python3 -m venv .venv
|
|
54
|
+
.venv/bin/pip install -r requirements.txt # exact pinned versions
|
|
55
|
+
.venv/bin/python wallet_manager.py --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
wallet-manager create savings # generate a new 24-word wallet
|
|
62
|
+
wallet-manager create hot --words 12 # 12-word variant
|
|
63
|
+
wallet-manager list # names + addresses (no password needed)
|
|
64
|
+
wallet-manager balance # on-chain balances for all wallets
|
|
65
|
+
wallet-manager balance savings # ... or just one
|
|
66
|
+
wallet-manager show savings # details incl. derivation paths
|
|
67
|
+
wallet-manager import old-wallet # import an existing recovery phrase
|
|
68
|
+
wallet-manager import mm --eth-private-key # import a raw ETH private key
|
|
69
|
+
wallet-manager export savings # reveal the recovery phrase (guarded)
|
|
70
|
+
wallet-manager export savings --eth-key # reveal derived ETH private key (guarded)
|
|
71
|
+
wallet-manager delete old-wallet # remove a wallet (password + typed confirmation)
|
|
72
|
+
wallet-manager change-password # re-encrypt keystore with a new password
|
|
73
|
+
wallet-manager verify # prove stored addresses match their secrets
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The first `create`/`import` asks you to set a master password for the
|
|
77
|
+
keystore. Every command that touches or destroys secret material asks for
|
|
78
|
+
it again; `list`, `show`, and `balance` never need it.
|
|
79
|
+
|
|
80
|
+
`create` prints the new recovery phrase only when stdout is a terminal, so
|
|
81
|
+
it never lands in a log file or pipe by accident. Write it on paper.
|
|
82
|
+
|
|
83
|
+
## Where things live
|
|
84
|
+
|
|
85
|
+
The keystore is a single JSON file (default
|
|
86
|
+
`~/.crypto-wallet-manager/wallets.json`, permissions `0600`, written
|
|
87
|
+
atomically). Override the location with `--file <path>` or
|
|
88
|
+
`$WALLET_MANAGER_FILE`.
|
|
89
|
+
|
|
90
|
+
Wallet names and public addresses are plaintext; recovery phrases / private
|
|
91
|
+
keys are encrypted with Fernet (AES-128-CBC + HMAC-SHA256). scrypt
|
|
92
|
+
(N=2¹⁷, r=8, p=1 — the OWASP minimum, ~128 MiB and about half a second per
|
|
93
|
+
unlock) stretches your master password into 64 bytes: half becomes the
|
|
94
|
+
Fernet key, half an HMAC key that seals every wallet record, ciphertext
|
|
95
|
+
included.
|
|
96
|
+
|
|
97
|
+
That seal means anyone who edits the file — to swap your deposit addresses
|
|
98
|
+
for theirs, swap secrets between wallets, add or rename a wallet — is caught
|
|
99
|
+
the next time you enter your password, and a keystore whose seal is missing
|
|
100
|
+
is refused outright. `list` and `balance` skip the password, so they can't
|
|
101
|
+
check the seal — if the file has been somewhere you don't trust, run
|
|
102
|
+
`verify`, which additionally re-derives every address from its decrypted
|
|
103
|
+
secret.
|
|
104
|
+
|
|
105
|
+
Derivation paths: ETH `m/44'/60'/0'/0/0`, BTC `m/84'/0'/0'/0/0`.
|
|
106
|
+
These are the standard first-account paths, so any generated wallet can be
|
|
107
|
+
restored in MetaMask, Sparrow, Electrum, Ledger, etc. from its phrase.
|
|
108
|
+
|
|
109
|
+
Balance sources: `ethereum-rpc.publicnode.com` (JSON-RPC) and
|
|
110
|
+
`blockstream.info` (REST). Only your public addresses are sent to these
|
|
111
|
+
services. `balance` exits non-zero if any lookup fails.
|
|
112
|
+
|
|
113
|
+
## Limitations
|
|
114
|
+
|
|
115
|
+
- One address per wallet per chain (account 0, index 0). Funds received on
|
|
116
|
+
other addresses of the same seed are not shown by `balance`.
|
|
117
|
+
- No BIP39 passphrase ("25th word") support.
|
|
118
|
+
- English BIP39 word list only.
|
|
119
|
+
- Keystores written by pre-release builds (format v1/v2) are not read.
|
|
120
|
+
Recreate the keystore by importing each wallet from its recovery phrase.
|
|
121
|
+
|
|
122
|
+
## Automation
|
|
123
|
+
|
|
124
|
+
`$WALLET_MANAGER_PASSWORD` (and `$WALLET_MANAGER_NEW_PASSWORD` for
|
|
125
|
+
`change-password`) bypass the interactive prompts — meant for scripts and
|
|
126
|
+
tests. When stdin is not a terminal, `import` reads the phrase or key from
|
|
127
|
+
it, and `export`/`delete` read their confirmation from it. Don't put your
|
|
128
|
+
real master password in shell history or dotfiles.
|
|
129
|
+
|
|
130
|
+
## Security notes
|
|
131
|
+
|
|
132
|
+
- Write recovery phrases on paper. The encrypted file protects against
|
|
133
|
+
casual file theft, not against a compromised machine or a weak password.
|
|
134
|
+
- `export` prints secrets to the terminal — clear scrollback afterwards.
|
|
135
|
+
- This is a hot-wallet tool; keep meaningful funds on hardware wallets.
|
|
136
|
+
|
|
137
|
+
## Development
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
pip install -e ".[dev]"
|
|
141
|
+
ruff check .
|
|
142
|
+
pytest
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The tests never touch `~/.crypto-wallet-manager`; they run against
|
|
146
|
+
temporary keystores with a lowered scrypt cost. Known-answer vectors cover
|
|
147
|
+
BIP39 → BIP44/BIP84 derivation, and the tamper tests mutate the keystore
|
|
148
|
+
JSON directly.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
# crypto-wallet-manager
|
|
2
|
+
|
|
3
|
+
A local CLI for managing crypto wallets: generate BIP39 HD wallets, derive
|
|
4
|
+
Bitcoin (native segwit, BIP84) and Ethereum (BIP44) addresses, keep secrets
|
|
5
|
+
encrypted at rest, and check on-chain balances via public APIs.
|
|
6
|
+
|
|
7
|
+
It deliberately does **not** sign or send transactions — it manages keys and
|
|
8
|
+
watches balances only.
|
|
9
|
+
|
|
10
|
+
## Install
|
|
11
|
+
|
|
12
|
+
Requires Python 3.10+.
|
|
13
|
+
|
|
14
|
+
```sh
|
|
15
|
+
pipx install crypto-wallet-manager # from PyPI; puts `wallet-manager` on PATH
|
|
16
|
+
# or, from a checkout:
|
|
17
|
+
pipx install .
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
For development, or to run it without installing:
|
|
21
|
+
|
|
22
|
+
```sh
|
|
23
|
+
python3 -m venv .venv
|
|
24
|
+
.venv/bin/pip install -r requirements.txt # exact pinned versions
|
|
25
|
+
.venv/bin/python wallet_manager.py --help
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
```sh
|
|
31
|
+
wallet-manager create savings # generate a new 24-word wallet
|
|
32
|
+
wallet-manager create hot --words 12 # 12-word variant
|
|
33
|
+
wallet-manager list # names + addresses (no password needed)
|
|
34
|
+
wallet-manager balance # on-chain balances for all wallets
|
|
35
|
+
wallet-manager balance savings # ... or just one
|
|
36
|
+
wallet-manager show savings # details incl. derivation paths
|
|
37
|
+
wallet-manager import old-wallet # import an existing recovery phrase
|
|
38
|
+
wallet-manager import mm --eth-private-key # import a raw ETH private key
|
|
39
|
+
wallet-manager export savings # reveal the recovery phrase (guarded)
|
|
40
|
+
wallet-manager export savings --eth-key # reveal derived ETH private key (guarded)
|
|
41
|
+
wallet-manager delete old-wallet # remove a wallet (password + typed confirmation)
|
|
42
|
+
wallet-manager change-password # re-encrypt keystore with a new password
|
|
43
|
+
wallet-manager verify # prove stored addresses match their secrets
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
The first `create`/`import` asks you to set a master password for the
|
|
47
|
+
keystore. Every command that touches or destroys secret material asks for
|
|
48
|
+
it again; `list`, `show`, and `balance` never need it.
|
|
49
|
+
|
|
50
|
+
`create` prints the new recovery phrase only when stdout is a terminal, so
|
|
51
|
+
it never lands in a log file or pipe by accident. Write it on paper.
|
|
52
|
+
|
|
53
|
+
## Where things live
|
|
54
|
+
|
|
55
|
+
The keystore is a single JSON file (default
|
|
56
|
+
`~/.crypto-wallet-manager/wallets.json`, permissions `0600`, written
|
|
57
|
+
atomically). Override the location with `--file <path>` or
|
|
58
|
+
`$WALLET_MANAGER_FILE`.
|
|
59
|
+
|
|
60
|
+
Wallet names and public addresses are plaintext; recovery phrases / private
|
|
61
|
+
keys are encrypted with Fernet (AES-128-CBC + HMAC-SHA256). scrypt
|
|
62
|
+
(N=2¹⁷, r=8, p=1 — the OWASP minimum, ~128 MiB and about half a second per
|
|
63
|
+
unlock) stretches your master password into 64 bytes: half becomes the
|
|
64
|
+
Fernet key, half an HMAC key that seals every wallet record, ciphertext
|
|
65
|
+
included.
|
|
66
|
+
|
|
67
|
+
That seal means anyone who edits the file — to swap your deposit addresses
|
|
68
|
+
for theirs, swap secrets between wallets, add or rename a wallet — is caught
|
|
69
|
+
the next time you enter your password, and a keystore whose seal is missing
|
|
70
|
+
is refused outright. `list` and `balance` skip the password, so they can't
|
|
71
|
+
check the seal — if the file has been somewhere you don't trust, run
|
|
72
|
+
`verify`, which additionally re-derives every address from its decrypted
|
|
73
|
+
secret.
|
|
74
|
+
|
|
75
|
+
Derivation paths: ETH `m/44'/60'/0'/0/0`, BTC `m/84'/0'/0'/0/0`.
|
|
76
|
+
These are the standard first-account paths, so any generated wallet can be
|
|
77
|
+
restored in MetaMask, Sparrow, Electrum, Ledger, etc. from its phrase.
|
|
78
|
+
|
|
79
|
+
Balance sources: `ethereum-rpc.publicnode.com` (JSON-RPC) and
|
|
80
|
+
`blockstream.info` (REST). Only your public addresses are sent to these
|
|
81
|
+
services. `balance` exits non-zero if any lookup fails.
|
|
82
|
+
|
|
83
|
+
## Limitations
|
|
84
|
+
|
|
85
|
+
- One address per wallet per chain (account 0, index 0). Funds received on
|
|
86
|
+
other addresses of the same seed are not shown by `balance`.
|
|
87
|
+
- No BIP39 passphrase ("25th word") support.
|
|
88
|
+
- English BIP39 word list only.
|
|
89
|
+
- Keystores written by pre-release builds (format v1/v2) are not read.
|
|
90
|
+
Recreate the keystore by importing each wallet from its recovery phrase.
|
|
91
|
+
|
|
92
|
+
## Automation
|
|
93
|
+
|
|
94
|
+
`$WALLET_MANAGER_PASSWORD` (and `$WALLET_MANAGER_NEW_PASSWORD` for
|
|
95
|
+
`change-password`) bypass the interactive prompts — meant for scripts and
|
|
96
|
+
tests. When stdin is not a terminal, `import` reads the phrase or key from
|
|
97
|
+
it, and `export`/`delete` read their confirmation from it. Don't put your
|
|
98
|
+
real master password in shell history or dotfiles.
|
|
99
|
+
|
|
100
|
+
## Security notes
|
|
101
|
+
|
|
102
|
+
- Write recovery phrases on paper. The encrypted file protects against
|
|
103
|
+
casual file theft, not against a compromised machine or a weak password.
|
|
104
|
+
- `export` prints secrets to the terminal — clear scrollback afterwards.
|
|
105
|
+
- This is a hot-wallet tool; keep meaningful funds on hardware wallets.
|
|
106
|
+
|
|
107
|
+
## Development
|
|
108
|
+
|
|
109
|
+
```sh
|
|
110
|
+
pip install -e ".[dev]"
|
|
111
|
+
ruff check .
|
|
112
|
+
pytest
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
The tests never touch `~/.crypto-wallet-manager`; they run against
|
|
116
|
+
temporary keystores with a lowered scrypt cost. Known-answer vectors cover
|
|
117
|
+
BIP39 → BIP44/BIP84 derivation, and the tamper tests mutate the keystore
|
|
118
|
+
JSON directly.
|
|
119
|
+
|
|
120
|
+
## License
|
|
121
|
+
|
|
122
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,152 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: crypto-wallet-manager
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Local CLI for BIP39 HD wallets: derive BTC/ETH addresses, keep secrets encrypted at rest, check balances.
|
|
5
|
+
Author: R. Kürşat Vuruşan
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/RKursatV/crypto-wallet-manager
|
|
8
|
+
Project-URL: Repository, https://github.com/RKursatV/crypto-wallet-manager
|
|
9
|
+
Project-URL: Changelog, https://github.com/RKursatV/crypto-wallet-manager/blob/main/CHANGELOG.md
|
|
10
|
+
Project-URL: Issues, https://github.com/RKursatV/crypto-wallet-manager/issues
|
|
11
|
+
Keywords: bitcoin,ethereum,bip39,bip44,bip84,wallet,cli
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
18
|
+
Classifier: Topic :: Security :: Cryptography
|
|
19
|
+
Classifier: Topic :: Utilities
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: bip-utils<3,>=2.9
|
|
24
|
+
Requires-Dist: cryptography>=42
|
|
25
|
+
Requires-Dist: requests>=2.31
|
|
26
|
+
Provides-Extra: dev
|
|
27
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
28
|
+
Requires-Dist: ruff>=0.5; extra == "dev"
|
|
29
|
+
Dynamic: license-file
|
|
30
|
+
|
|
31
|
+
# crypto-wallet-manager
|
|
32
|
+
|
|
33
|
+
A local CLI for managing crypto wallets: generate BIP39 HD wallets, derive
|
|
34
|
+
Bitcoin (native segwit, BIP84) and Ethereum (BIP44) addresses, keep secrets
|
|
35
|
+
encrypted at rest, and check on-chain balances via public APIs.
|
|
36
|
+
|
|
37
|
+
It deliberately does **not** sign or send transactions — it manages keys and
|
|
38
|
+
watches balances only.
|
|
39
|
+
|
|
40
|
+
## Install
|
|
41
|
+
|
|
42
|
+
Requires Python 3.10+.
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pipx install crypto-wallet-manager # from PyPI; puts `wallet-manager` on PATH
|
|
46
|
+
# or, from a checkout:
|
|
47
|
+
pipx install .
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
For development, or to run it without installing:
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
python3 -m venv .venv
|
|
54
|
+
.venv/bin/pip install -r requirements.txt # exact pinned versions
|
|
55
|
+
.venv/bin/python wallet_manager.py --help
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## Usage
|
|
59
|
+
|
|
60
|
+
```sh
|
|
61
|
+
wallet-manager create savings # generate a new 24-word wallet
|
|
62
|
+
wallet-manager create hot --words 12 # 12-word variant
|
|
63
|
+
wallet-manager list # names + addresses (no password needed)
|
|
64
|
+
wallet-manager balance # on-chain balances for all wallets
|
|
65
|
+
wallet-manager balance savings # ... or just one
|
|
66
|
+
wallet-manager show savings # details incl. derivation paths
|
|
67
|
+
wallet-manager import old-wallet # import an existing recovery phrase
|
|
68
|
+
wallet-manager import mm --eth-private-key # import a raw ETH private key
|
|
69
|
+
wallet-manager export savings # reveal the recovery phrase (guarded)
|
|
70
|
+
wallet-manager export savings --eth-key # reveal derived ETH private key (guarded)
|
|
71
|
+
wallet-manager delete old-wallet # remove a wallet (password + typed confirmation)
|
|
72
|
+
wallet-manager change-password # re-encrypt keystore with a new password
|
|
73
|
+
wallet-manager verify # prove stored addresses match their secrets
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
The first `create`/`import` asks you to set a master password for the
|
|
77
|
+
keystore. Every command that touches or destroys secret material asks for
|
|
78
|
+
it again; `list`, `show`, and `balance` never need it.
|
|
79
|
+
|
|
80
|
+
`create` prints the new recovery phrase only when stdout is a terminal, so
|
|
81
|
+
it never lands in a log file or pipe by accident. Write it on paper.
|
|
82
|
+
|
|
83
|
+
## Where things live
|
|
84
|
+
|
|
85
|
+
The keystore is a single JSON file (default
|
|
86
|
+
`~/.crypto-wallet-manager/wallets.json`, permissions `0600`, written
|
|
87
|
+
atomically). Override the location with `--file <path>` or
|
|
88
|
+
`$WALLET_MANAGER_FILE`.
|
|
89
|
+
|
|
90
|
+
Wallet names and public addresses are plaintext; recovery phrases / private
|
|
91
|
+
keys are encrypted with Fernet (AES-128-CBC + HMAC-SHA256). scrypt
|
|
92
|
+
(N=2¹⁷, r=8, p=1 — the OWASP minimum, ~128 MiB and about half a second per
|
|
93
|
+
unlock) stretches your master password into 64 bytes: half becomes the
|
|
94
|
+
Fernet key, half an HMAC key that seals every wallet record, ciphertext
|
|
95
|
+
included.
|
|
96
|
+
|
|
97
|
+
That seal means anyone who edits the file — to swap your deposit addresses
|
|
98
|
+
for theirs, swap secrets between wallets, add or rename a wallet — is caught
|
|
99
|
+
the next time you enter your password, and a keystore whose seal is missing
|
|
100
|
+
is refused outright. `list` and `balance` skip the password, so they can't
|
|
101
|
+
check the seal — if the file has been somewhere you don't trust, run
|
|
102
|
+
`verify`, which additionally re-derives every address from its decrypted
|
|
103
|
+
secret.
|
|
104
|
+
|
|
105
|
+
Derivation paths: ETH `m/44'/60'/0'/0/0`, BTC `m/84'/0'/0'/0/0`.
|
|
106
|
+
These are the standard first-account paths, so any generated wallet can be
|
|
107
|
+
restored in MetaMask, Sparrow, Electrum, Ledger, etc. from its phrase.
|
|
108
|
+
|
|
109
|
+
Balance sources: `ethereum-rpc.publicnode.com` (JSON-RPC) and
|
|
110
|
+
`blockstream.info` (REST). Only your public addresses are sent to these
|
|
111
|
+
services. `balance` exits non-zero if any lookup fails.
|
|
112
|
+
|
|
113
|
+
## Limitations
|
|
114
|
+
|
|
115
|
+
- One address per wallet per chain (account 0, index 0). Funds received on
|
|
116
|
+
other addresses of the same seed are not shown by `balance`.
|
|
117
|
+
- No BIP39 passphrase ("25th word") support.
|
|
118
|
+
- English BIP39 word list only.
|
|
119
|
+
- Keystores written by pre-release builds (format v1/v2) are not read.
|
|
120
|
+
Recreate the keystore by importing each wallet from its recovery phrase.
|
|
121
|
+
|
|
122
|
+
## Automation
|
|
123
|
+
|
|
124
|
+
`$WALLET_MANAGER_PASSWORD` (and `$WALLET_MANAGER_NEW_PASSWORD` for
|
|
125
|
+
`change-password`) bypass the interactive prompts — meant for scripts and
|
|
126
|
+
tests. When stdin is not a terminal, `import` reads the phrase or key from
|
|
127
|
+
it, and `export`/`delete` read their confirmation from it. Don't put your
|
|
128
|
+
real master password in shell history or dotfiles.
|
|
129
|
+
|
|
130
|
+
## Security notes
|
|
131
|
+
|
|
132
|
+
- Write recovery phrases on paper. The encrypted file protects against
|
|
133
|
+
casual file theft, not against a compromised machine or a weak password.
|
|
134
|
+
- `export` prints secrets to the terminal — clear scrollback afterwards.
|
|
135
|
+
- This is a hot-wallet tool; keep meaningful funds on hardware wallets.
|
|
136
|
+
|
|
137
|
+
## Development
|
|
138
|
+
|
|
139
|
+
```sh
|
|
140
|
+
pip install -e ".[dev]"
|
|
141
|
+
ruff check .
|
|
142
|
+
pytest
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
The tests never touch `~/.crypto-wallet-manager`; they run against
|
|
146
|
+
temporary keystores with a lowered scrypt cost. Known-answer vectors cover
|
|
147
|
+
BIP39 → BIP44/BIP84 derivation, and the tamper tests mutate the keystore
|
|
148
|
+
JSON directly.
|
|
149
|
+
|
|
150
|
+
## License
|
|
151
|
+
|
|
152
|
+
MIT — see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
wallet_manager.py
|
|
5
|
+
crypto_wallet_manager.egg-info/PKG-INFO
|
|
6
|
+
crypto_wallet_manager.egg-info/SOURCES.txt
|
|
7
|
+
crypto_wallet_manager.egg-info/dependency_links.txt
|
|
8
|
+
crypto_wallet_manager.egg-info/entry_points.txt
|
|
9
|
+
crypto_wallet_manager.egg-info/requires.txt
|
|
10
|
+
crypto_wallet_manager.egg-info/top_level.txt
|
|
11
|
+
tests/test_wallet_manager.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
wallet_manager
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "crypto-wallet-manager"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Local CLI for BIP39 HD wallets: derive BTC/ETH addresses, keep secrets encrypted at rest, check balances."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.10"
|
|
13
|
+
authors = [{ name = "R. Kürşat Vuruşan" }]
|
|
14
|
+
keywords = ["bitcoin", "ethereum", "bip39", "bip44", "bip84", "wallet", "cli"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 4 - Beta",
|
|
17
|
+
"Environment :: Console",
|
|
18
|
+
"Intended Audience :: End Users/Desktop",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Programming Language :: Python :: 3",
|
|
21
|
+
"Programming Language :: Python :: 3 :: Only",
|
|
22
|
+
"Topic :: Security :: Cryptography",
|
|
23
|
+
"Topic :: Utilities",
|
|
24
|
+
]
|
|
25
|
+
dependencies = [
|
|
26
|
+
"bip-utils>=2.9,<3",
|
|
27
|
+
"cryptography>=42",
|
|
28
|
+
"requests>=2.31",
|
|
29
|
+
]
|
|
30
|
+
|
|
31
|
+
[project.optional-dependencies]
|
|
32
|
+
dev = ["pytest>=8", "ruff>=0.5"]
|
|
33
|
+
|
|
34
|
+
[project.urls]
|
|
35
|
+
Homepage = "https://github.com/RKursatV/crypto-wallet-manager"
|
|
36
|
+
Repository = "https://github.com/RKursatV/crypto-wallet-manager"
|
|
37
|
+
Changelog = "https://github.com/RKursatV/crypto-wallet-manager/blob/main/CHANGELOG.md"
|
|
38
|
+
Issues = "https://github.com/RKursatV/crypto-wallet-manager/issues"
|
|
39
|
+
|
|
40
|
+
[project.scripts]
|
|
41
|
+
wallet-manager = "wallet_manager:main"
|
|
42
|
+
|
|
43
|
+
[tool.setuptools]
|
|
44
|
+
py-modules = ["wallet_manager"]
|
|
45
|
+
|
|
46
|
+
[tool.pytest.ini_options]
|
|
47
|
+
testpaths = ["tests"]
|
|
48
|
+
addopts = "-q"
|
|
49
|
+
|
|
50
|
+
[tool.ruff]
|
|
51
|
+
line-length = 100
|
|
52
|
+
target-version = "py310"
|
|
53
|
+
|
|
54
|
+
[tool.ruff.lint]
|
|
55
|
+
select = ["E", "F", "W", "I", "B", "UP", "S"]
|
|
56
|
+
ignore = [
|
|
57
|
+
"S101", # assert is fine in tests
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
[tool.ruff.lint.isort]
|
|
61
|
+
known-first-party = ["wallet_manager", "conftest"]
|
|
62
|
+
|
|
63
|
+
[tool.ruff.lint.per-file-ignores]
|
|
64
|
+
"tests/*" = ["S105", "S106"] # hard-coded test passwords
|