eth-keypass 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.
- eth_keypass-0.1.0/LICENSE +21 -0
- eth_keypass-0.1.0/PKG-INFO +242 -0
- eth_keypass-0.1.0/README.md +211 -0
- eth_keypass-0.1.0/pyproject.toml +64 -0
- eth_keypass-0.1.0/setup.cfg +4 -0
- eth_keypass-0.1.0/src/eth_keypass/__init__.py +12 -0
- eth_keypass-0.1.0/src/eth_keypass/account.py +192 -0
- eth_keypass-0.1.0/src/eth_keypass/crypto/__init__.py +36 -0
- eth_keypass-0.1.0/src/eth_keypass/crypto/common.py +129 -0
- eth_keypass-0.1.0/src/eth_keypass/crypto/keystore.py +175 -0
- eth_keypass-0.1.0/src/eth_keypass/crypto/rlp.py +47 -0
- eth_keypass-0.1.0/src/eth_keypass/crypto/secp256k1.py +255 -0
- eth_keypass-0.1.0/src/eth_keypass/crypto/signing.py +627 -0
- eth_keypass-0.1.0/src/eth_keypass/crypto/symmetric.py +233 -0
- eth_keypass-0.1.0/src/eth_keypass/db/__init__.py +7 -0
- eth_keypass-0.1.0/src/eth_keypass/db/base.py +282 -0
- eth_keypass-0.1.0/src/eth_keypass/db/constants.py +50 -0
- eth_keypass-0.1.0/src/eth_keypass/db/core.py +143 -0
- eth_keypass-0.1.0/src/eth_keypass/db/keys.py +85 -0
- eth_keypass-0.1.0/src/eth_keypass/db/mutations.py +426 -0
- eth_keypass-0.1.0/src/eth_keypass/errors.py +57 -0
- eth_keypass-0.1.0/src/eth_keypass/utils.py +115 -0
- eth_keypass-0.1.0/src/eth_keypass.egg-info/PKG-INFO +242 -0
- eth_keypass-0.1.0/src/eth_keypass.egg-info/SOURCES.txt +25 -0
- eth_keypass-0.1.0/src/eth_keypass.egg-info/dependency_links.txt +1 -0
- eth_keypass-0.1.0/src/eth_keypass.egg-info/requires.txt +20 -0
- eth_keypass-0.1.0/src/eth_keypass.egg-info/top_level.txt +1 -0
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 iamdefinitelyahuman
|
|
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,242 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: eth-keypass
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: EVM account management tool.
|
|
5
|
+
Author: iamdefinitelyahuman
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://github.com/iamdefinitelyahuman/eth-keypass
|
|
8
|
+
Project-URL: Repository, https://github.com/iamdefinitelyahuman/eth-keypass
|
|
9
|
+
Requires-Python: >=3.12
|
|
10
|
+
Description-Content-Type: text/markdown
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Requires-Dist: argon2-cffi>=23.1.0
|
|
13
|
+
Requires-Dist: cryptography>=42.0.0
|
|
14
|
+
Requires-Dist: platformdirs>=4.0
|
|
15
|
+
Requires-Dist: pycryptodome>=3.20
|
|
16
|
+
Provides-Extra: dev
|
|
17
|
+
Requires-Dist: pytest>=8; extra == "dev"
|
|
18
|
+
Requires-Dist: pytest-cov>=5; extra == "dev"
|
|
19
|
+
Requires-Dist: hypothesis>=6.0; extra == "dev"
|
|
20
|
+
Requires-Dist: eth-account<0.14,>=0.13.7; extra == "dev"
|
|
21
|
+
Requires-Dist: ruff>=0.9; extra == "dev"
|
|
22
|
+
Requires-Dist: pre-commit>=3; extra == "dev"
|
|
23
|
+
Requires-Dist: build; extra == "dev"
|
|
24
|
+
Requires-Dist: twine; extra == "dev"
|
|
25
|
+
Requires-Dist: mkdocs>=1.6; extra == "dev"
|
|
26
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "dev"
|
|
27
|
+
Provides-Extra: docs
|
|
28
|
+
Requires-Dist: mkdocs>=1.6; extra == "docs"
|
|
29
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
30
|
+
Dynamic: license-file
|
|
31
|
+
|
|
32
|
+
# eth-keypass
|
|
33
|
+
|
|
34
|
+
Simple EVM account management tool.
|
|
35
|
+
|
|
36
|
+
**NOTE**: This library is still in early alpha development. Prior to a `v1.0.0` (which may never come), expect breaking changes and no backward compatibility between versions.
|
|
37
|
+
|
|
38
|
+
## Installation
|
|
39
|
+
|
|
40
|
+
You can install the latest release via `pip`:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
pip install eth_keypass
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Or clone the repository for the most up-to-date version:
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
git clone https://github.com/iamdefinitelyahuman/eth-keypass.git
|
|
50
|
+
cd eth-keypass
|
|
51
|
+
pip install -e .
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Usage
|
|
55
|
+
|
|
56
|
+
### 1. Create and access a Keypass
|
|
57
|
+
|
|
58
|
+
Creating a keypass is a single function call. The result is a persistent database stored on disk.
|
|
59
|
+
|
|
60
|
+
```py
|
|
61
|
+
>>> import eth_keypass
|
|
62
|
+
|
|
63
|
+
>>> kp = eth_keypass.create("main")
|
|
64
|
+
Create password for new keypass 'main': ***
|
|
65
|
+
|
|
66
|
+
>>> kp
|
|
67
|
+
<KeypassDB path=/home/user/.local/share/eth-keypass/main.sqlite3 unlocked>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Once created, it can be opened and unlocked in another session.
|
|
71
|
+
|
|
72
|
+
```py
|
|
73
|
+
>>> import eth_keypass
|
|
74
|
+
|
|
75
|
+
>>> kp = eth_keypass.open("main")
|
|
76
|
+
>>> kp.unlock()
|
|
77
|
+
Enter the password for keypass 'main': ***
|
|
78
|
+
|
|
79
|
+
# alternatively use the top-level "unlock" to open and unlock in a single action
|
|
80
|
+
>>> kp = eth_keypass.unlock("main", password="mypassword")
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
### 2. Create an account
|
|
84
|
+
|
|
85
|
+
A new account can be generated directly inside the keypass. Its private key is encrypted and stored in the database.
|
|
86
|
+
|
|
87
|
+
```py
|
|
88
|
+
>>> acct = kp.create_account()
|
|
89
|
+
>>> acct
|
|
90
|
+
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### 3. Import existing accounts
|
|
94
|
+
|
|
95
|
+
A keypass can hold multiple accounts.
|
|
96
|
+
|
|
97
|
+
You can import an existing account from a raw private key:
|
|
98
|
+
|
|
99
|
+
```py
|
|
100
|
+
>>> kp.add_private_key(
|
|
101
|
+
... "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
102
|
+
... alias="imported-key",
|
|
103
|
+
... )
|
|
104
|
+
<Account 0xFCAd0B19bB29D4674531d6f115237E16AfCE377c signable>
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Or import from an Ethereum keystore JSON:
|
|
108
|
+
|
|
109
|
+
```py
|
|
110
|
+
>>> kp.import_keystore(
|
|
111
|
+
... "./my-keystore.json",
|
|
112
|
+
... password="keystore-password",
|
|
113
|
+
... alias="imported-json",
|
|
114
|
+
... )
|
|
115
|
+
<Account 0x104da57BF95262B119553181bA62dD5B8F204f49 signable>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 4. Set aliases
|
|
119
|
+
|
|
120
|
+
You can set aliases for accounts to simplify retrieval later. A single account can have multiple aliases.
|
|
121
|
+
|
|
122
|
+
```py
|
|
123
|
+
>>> kp.set_alias(acct, "hot")
|
|
124
|
+
>>> kp.set_alias(acct, "trading")
|
|
125
|
+
|
|
126
|
+
>>> kp["hot"]
|
|
127
|
+
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>
|
|
128
|
+
|
|
129
|
+
>>> kp["0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68"]
|
|
130
|
+
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>
|
|
131
|
+
|
|
132
|
+
>>> kp["hot"] == kp["trading"] == acct
|
|
133
|
+
True
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
### 5. Add watch-only accounts
|
|
137
|
+
|
|
138
|
+
If you assign an alias to an address that has no private key in the keypass, it is stored as a watch-only account.
|
|
139
|
+
|
|
140
|
+
This lets you keep named references to important addresses and retrieve them later by alias.
|
|
141
|
+
|
|
142
|
+
```py
|
|
143
|
+
>>> kp.set_alias("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "vitalik")
|
|
144
|
+
|
|
145
|
+
>>> kp["vitalik"]
|
|
146
|
+
<Account 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 watch-only>
|
|
147
|
+
```
|
|
148
|
+
|
|
149
|
+
### 6. Sign a transaction
|
|
150
|
+
|
|
151
|
+
Here we build a transaction from one of our signing accounts to send to one of our watch-only accounts.
|
|
152
|
+
|
|
153
|
+
```py
|
|
154
|
+
>>> tx = {
|
|
155
|
+
... "to": kp["vitalik"],
|
|
156
|
+
... "value": 10**18,
|
|
157
|
+
... "gas": 21_000,
|
|
158
|
+
... "maxFeePerGas": 30_000_000_000,
|
|
159
|
+
... "maxPriorityFeePerGas": 2_000_000_000,
|
|
160
|
+
... "nonce": 0,
|
|
161
|
+
... "chainId": 1
|
|
162
|
+
... }
|
|
163
|
+
>>> signed = kp["hot"].sign_transaction(tx)
|
|
164
|
+
|
|
165
|
+
>>> signed
|
|
166
|
+
SignedTransaction(raw_transaction=b'\x02...', hash=b'\xa1...', r=..., s=..., v=1)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
### 7. Sign messages
|
|
170
|
+
|
|
171
|
+
The `Account` object also exposes methods for signing messages and authorizations.
|
|
172
|
+
|
|
173
|
+
```py
|
|
174
|
+
Account.sign_authorization(authorization_dict: dict[str, Any])
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```py
|
|
178
|
+
Account.sign_message(signable_message: Any)
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
```py
|
|
182
|
+
Account.sign_typed_data(
|
|
183
|
+
domain_data: dict[str, Any] | None = None,
|
|
184
|
+
message_types: dict[str, Any] | None = None,
|
|
185
|
+
message_data: dict[str, Any] | None = None,
|
|
186
|
+
full_message: dict[str, Any] | None = None,
|
|
187
|
+
)
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
All signing methods implement an equivalent API to the same-named functions in the [`eth-account`](https://github.com/ethereum/eth-account) library.
|
|
191
|
+
|
|
192
|
+
### 8. Default keypass and accounts
|
|
193
|
+
|
|
194
|
+
You can create a "default" keypass by calling `create` with no arguments:
|
|
195
|
+
|
|
196
|
+
```py
|
|
197
|
+
>>> eth_keypass.create()
|
|
198
|
+
Create password for new keypass 'default':
|
|
199
|
+
<KeypassDB path=/home/user/.local/share/eth-keypass/default.sqlite3 unlocked>
|
|
200
|
+
```
|
|
201
|
+
|
|
202
|
+
Every keypass also maintains a default account.
|
|
203
|
+
|
|
204
|
+
```py
|
|
205
|
+
>>> kp.default_account
|
|
206
|
+
eth_keypass.errors.NoDefaultAccountError: database has no default account set
|
|
207
|
+
|
|
208
|
+
>>> kp.create_account(alias="degen", set_as_default=True)
|
|
209
|
+
<Account 0xcc27b3Be484E3692737993ca8273349e9483454D signable>
|
|
210
|
+
|
|
211
|
+
>>> kp.default_account
|
|
212
|
+
<Account 0xcc27b3Be484E3692737993ca8273349e9483454D signable>
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
This makes portable scripts possible. Each user signs using **their own default keypass and account**.
|
|
216
|
+
|
|
217
|
+
```py
|
|
218
|
+
import eth_keypass
|
|
219
|
+
|
|
220
|
+
kp = eth_keypass.unlock()
|
|
221
|
+
|
|
222
|
+
acct = kp.default_account
|
|
223
|
+
acct.sign_transaction(...)
|
|
224
|
+
```
|
|
225
|
+
|
|
226
|
+
## Tests
|
|
227
|
+
|
|
228
|
+
First, install the dev dependencies:
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
pip install -e ".[dev]"
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
To run the test suite:
|
|
235
|
+
|
|
236
|
+
```bash
|
|
237
|
+
pytest
|
|
238
|
+
```
|
|
239
|
+
|
|
240
|
+
## License
|
|
241
|
+
|
|
242
|
+
This project is licensed under the [MIT license](LICENSE).
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
# eth-keypass
|
|
2
|
+
|
|
3
|
+
Simple EVM account management tool.
|
|
4
|
+
|
|
5
|
+
**NOTE**: This library is still in early alpha development. Prior to a `v1.0.0` (which may never come), expect breaking changes and no backward compatibility between versions.
|
|
6
|
+
|
|
7
|
+
## Installation
|
|
8
|
+
|
|
9
|
+
You can install the latest release via `pip`:
|
|
10
|
+
|
|
11
|
+
```bash
|
|
12
|
+
pip install eth_keypass
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
Or clone the repository for the most up-to-date version:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
git clone https://github.com/iamdefinitelyahuman/eth-keypass.git
|
|
19
|
+
cd eth-keypass
|
|
20
|
+
pip install -e .
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage
|
|
24
|
+
|
|
25
|
+
### 1. Create and access a Keypass
|
|
26
|
+
|
|
27
|
+
Creating a keypass is a single function call. The result is a persistent database stored on disk.
|
|
28
|
+
|
|
29
|
+
```py
|
|
30
|
+
>>> import eth_keypass
|
|
31
|
+
|
|
32
|
+
>>> kp = eth_keypass.create("main")
|
|
33
|
+
Create password for new keypass 'main': ***
|
|
34
|
+
|
|
35
|
+
>>> kp
|
|
36
|
+
<KeypassDB path=/home/user/.local/share/eth-keypass/main.sqlite3 unlocked>
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Once created, it can be opened and unlocked in another session.
|
|
40
|
+
|
|
41
|
+
```py
|
|
42
|
+
>>> import eth_keypass
|
|
43
|
+
|
|
44
|
+
>>> kp = eth_keypass.open("main")
|
|
45
|
+
>>> kp.unlock()
|
|
46
|
+
Enter the password for keypass 'main': ***
|
|
47
|
+
|
|
48
|
+
# alternatively use the top-level "unlock" to open and unlock in a single action
|
|
49
|
+
>>> kp = eth_keypass.unlock("main", password="mypassword")
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### 2. Create an account
|
|
53
|
+
|
|
54
|
+
A new account can be generated directly inside the keypass. Its private key is encrypted and stored in the database.
|
|
55
|
+
|
|
56
|
+
```py
|
|
57
|
+
>>> acct = kp.create_account()
|
|
58
|
+
>>> acct
|
|
59
|
+
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Import existing accounts
|
|
63
|
+
|
|
64
|
+
A keypass can hold multiple accounts.
|
|
65
|
+
|
|
66
|
+
You can import an existing account from a raw private key:
|
|
67
|
+
|
|
68
|
+
```py
|
|
69
|
+
>>> kp.add_private_key(
|
|
70
|
+
... "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
|
|
71
|
+
... alias="imported-key",
|
|
72
|
+
... )
|
|
73
|
+
<Account 0xFCAd0B19bB29D4674531d6f115237E16AfCE377c signable>
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Or import from an Ethereum keystore JSON:
|
|
77
|
+
|
|
78
|
+
```py
|
|
79
|
+
>>> kp.import_keystore(
|
|
80
|
+
... "./my-keystore.json",
|
|
81
|
+
... password="keystore-password",
|
|
82
|
+
... alias="imported-json",
|
|
83
|
+
... )
|
|
84
|
+
<Account 0x104da57BF95262B119553181bA62dD5B8F204f49 signable>
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
### 4. Set aliases
|
|
88
|
+
|
|
89
|
+
You can set aliases for accounts to simplify retrieval later. A single account can have multiple aliases.
|
|
90
|
+
|
|
91
|
+
```py
|
|
92
|
+
>>> kp.set_alias(acct, "hot")
|
|
93
|
+
>>> kp.set_alias(acct, "trading")
|
|
94
|
+
|
|
95
|
+
>>> kp["hot"]
|
|
96
|
+
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>
|
|
97
|
+
|
|
98
|
+
>>> kp["0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68"]
|
|
99
|
+
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>
|
|
100
|
+
|
|
101
|
+
>>> kp["hot"] == kp["trading"] == acct
|
|
102
|
+
True
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### 5. Add watch-only accounts
|
|
106
|
+
|
|
107
|
+
If you assign an alias to an address that has no private key in the keypass, it is stored as a watch-only account.
|
|
108
|
+
|
|
109
|
+
This lets you keep named references to important addresses and retrieve them later by alias.
|
|
110
|
+
|
|
111
|
+
```py
|
|
112
|
+
>>> kp.set_alias("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "vitalik")
|
|
113
|
+
|
|
114
|
+
>>> kp["vitalik"]
|
|
115
|
+
<Account 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 watch-only>
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### 6. Sign a transaction
|
|
119
|
+
|
|
120
|
+
Here we build a transaction from one of our signing accounts to send to one of our watch-only accounts.
|
|
121
|
+
|
|
122
|
+
```py
|
|
123
|
+
>>> tx = {
|
|
124
|
+
... "to": kp["vitalik"],
|
|
125
|
+
... "value": 10**18,
|
|
126
|
+
... "gas": 21_000,
|
|
127
|
+
... "maxFeePerGas": 30_000_000_000,
|
|
128
|
+
... "maxPriorityFeePerGas": 2_000_000_000,
|
|
129
|
+
... "nonce": 0,
|
|
130
|
+
... "chainId": 1
|
|
131
|
+
... }
|
|
132
|
+
>>> signed = kp["hot"].sign_transaction(tx)
|
|
133
|
+
|
|
134
|
+
>>> signed
|
|
135
|
+
SignedTransaction(raw_transaction=b'\x02...', hash=b'\xa1...', r=..., s=..., v=1)
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
### 7. Sign messages
|
|
139
|
+
|
|
140
|
+
The `Account` object also exposes methods for signing messages and authorizations.
|
|
141
|
+
|
|
142
|
+
```py
|
|
143
|
+
Account.sign_authorization(authorization_dict: dict[str, Any])
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```py
|
|
147
|
+
Account.sign_message(signable_message: Any)
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
```py
|
|
151
|
+
Account.sign_typed_data(
|
|
152
|
+
domain_data: dict[str, Any] | None = None,
|
|
153
|
+
message_types: dict[str, Any] | None = None,
|
|
154
|
+
message_data: dict[str, Any] | None = None,
|
|
155
|
+
full_message: dict[str, Any] | None = None,
|
|
156
|
+
)
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
All signing methods implement an equivalent API to the same-named functions in the [`eth-account`](https://github.com/ethereum/eth-account) library.
|
|
160
|
+
|
|
161
|
+
### 8. Default keypass and accounts
|
|
162
|
+
|
|
163
|
+
You can create a "default" keypass by calling `create` with no arguments:
|
|
164
|
+
|
|
165
|
+
```py
|
|
166
|
+
>>> eth_keypass.create()
|
|
167
|
+
Create password for new keypass 'default':
|
|
168
|
+
<KeypassDB path=/home/user/.local/share/eth-keypass/default.sqlite3 unlocked>
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
Every keypass also maintains a default account.
|
|
172
|
+
|
|
173
|
+
```py
|
|
174
|
+
>>> kp.default_account
|
|
175
|
+
eth_keypass.errors.NoDefaultAccountError: database has no default account set
|
|
176
|
+
|
|
177
|
+
>>> kp.create_account(alias="degen", set_as_default=True)
|
|
178
|
+
<Account 0xcc27b3Be484E3692737993ca8273349e9483454D signable>
|
|
179
|
+
|
|
180
|
+
>>> kp.default_account
|
|
181
|
+
<Account 0xcc27b3Be484E3692737993ca8273349e9483454D signable>
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
This makes portable scripts possible. Each user signs using **their own default keypass and account**.
|
|
185
|
+
|
|
186
|
+
```py
|
|
187
|
+
import eth_keypass
|
|
188
|
+
|
|
189
|
+
kp = eth_keypass.unlock()
|
|
190
|
+
|
|
191
|
+
acct = kp.default_account
|
|
192
|
+
acct.sign_transaction(...)
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
## Tests
|
|
196
|
+
|
|
197
|
+
First, install the dev dependencies:
|
|
198
|
+
|
|
199
|
+
```bash
|
|
200
|
+
pip install -e ".[dev]"
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
To run the test suite:
|
|
204
|
+
|
|
205
|
+
```bash
|
|
206
|
+
pytest
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
## License
|
|
210
|
+
|
|
211
|
+
This project is licensed under the [MIT license](LICENSE).
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=69", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "eth-keypass"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "EVM account management tool."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.12"
|
|
11
|
+
license = { text = "MIT" }
|
|
12
|
+
authors = [
|
|
13
|
+
{ name = "iamdefinitelyahuman" }
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
dependencies = [
|
|
17
|
+
"argon2-cffi>=23.1.0",
|
|
18
|
+
"cryptography>=42.0.0",
|
|
19
|
+
"platformdirs>=4.0",
|
|
20
|
+
"pycryptodome>=3.20",
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[project.optional-dependencies]
|
|
24
|
+
dev = [
|
|
25
|
+
"pytest>=8",
|
|
26
|
+
"pytest-cov>=5",
|
|
27
|
+
"hypothesis>=6.0",
|
|
28
|
+
"eth-account>=0.13.7,<0.14",
|
|
29
|
+
"ruff>=0.9",
|
|
30
|
+
"pre-commit>=3",
|
|
31
|
+
"build",
|
|
32
|
+
"twine",
|
|
33
|
+
"mkdocs>=1.6",
|
|
34
|
+
"mkdocs-material>=9.5",
|
|
35
|
+
]
|
|
36
|
+
docs = [
|
|
37
|
+
"mkdocs>=1.6",
|
|
38
|
+
"mkdocs-material>=9.5",
|
|
39
|
+
]
|
|
40
|
+
|
|
41
|
+
[project.urls]
|
|
42
|
+
Homepage = "https://github.com/iamdefinitelyahuman/eth-keypass"
|
|
43
|
+
Repository = "https://github.com/iamdefinitelyahuman/eth-keypass"
|
|
44
|
+
|
|
45
|
+
[tool.setuptools]
|
|
46
|
+
package-dir = {"" = "src"}
|
|
47
|
+
|
|
48
|
+
[tool.setuptools.packages.find]
|
|
49
|
+
where = ["src"]
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
line-length = 100
|
|
53
|
+
target-version = "py312"
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
select = ["E", "F", "I"]
|
|
57
|
+
|
|
58
|
+
[tool.pytest.ini_options]
|
|
59
|
+
addopts = [
|
|
60
|
+
"--cov=eth_keypass",
|
|
61
|
+
"--cov-report=term-missing",
|
|
62
|
+
"--cov-report=xml",
|
|
63
|
+
]
|
|
64
|
+
testpaths = ["tests"]
|