Metadata-Version: 2.4
Name: fastweb3-keypass
Version: 0.1.2
Summary: EVM account management tool.
Author: iamdefinitelyahuman
License: MIT
Project-URL: Homepage, https://github.com/iamdefinitelyahuman/fastweb3-keypass
Project-URL: Repository, https://github.com/iamdefinitelyahuman/fastweb3-keypass
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
Requires-Dist: argon2-cffi>=23.1.0
Requires-Dist: cryptography>=42.0.0
Requires-Dist: platformdirs>=4.0
Requires-Dist: pycryptodome>=3.20
Provides-Extra: dev
Requires-Dist: pytest>=8; extra == "dev"
Requires-Dist: pytest-cov>=5; extra == "dev"
Requires-Dist: hypothesis>=6.0; extra == "dev"
Requires-Dist: eth-account<0.14,>=0.13.7; extra == "dev"
Requires-Dist: ruff>=0.9; extra == "dev"
Requires-Dist: pre-commit>=3; extra == "dev"
Requires-Dist: build; extra == "dev"
Requires-Dist: twine; extra == "dev"
Requires-Dist: mkdocs>=1.6; extra == "dev"
Requires-Dist: mkdocs-material>=9.5; extra == "dev"
Provides-Extra: docs
Requires-Dist: mkdocs>=1.6; extra == "docs"
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
Dynamic: license-file

# fastweb3-keypass

Simple EVM account management tool.

**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.

## Installation

You can install the latest release via `pip`:

```bash
pip install fastweb3-keypass
```

Or clone the repository for the most up-to-date version:

```bash
git clone https://github.com/iamdefinitelyahuman/fastweb3-keypass.git
cd fastweb3-keypass
pip install -e .
```

## Usage

### 1. Create and access a Keypass

Creating a keypass is a single function call. The result is a persistent database stored on disk.

```py
>>> import fw3_keypass

>>> kp = fw3_keypass.create("main")
Create password for new keypass 'main': ***

>>> kp
<KeypassDB path=/home/user/.local/share/fastweb3-keypass/main.sqlite3 unlocked>
```

Once created, it can be opened and unlocked in another session.

```py
>>> import fw3_keypass

>>> kp = fw3_keypass.open("main")
>>> kp.unlock()
Enter the password for keypass 'main': ***

# alternatively use the top-level "unlock" to open and unlock in a single action
>>> kp = fw3_keypass.unlock("main", password="mypassword")
```

### 2. Create an account

A new account can be generated directly inside the keypass. Its private key is encrypted and stored in the database.

```py
>>> acct = kp.create_account()
>>> acct
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>
```

### 3. Import existing accounts

A keypass can hold multiple accounts.

You can import an existing account from a raw private key:

```py
>>> kp.add_private_key(
...     "0x0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef",
...     alias="imported-key",
... )
<Account 0xFCAd0B19bB29D4674531d6f115237E16AfCE377c signable>
```

Or import from an Ethereum keystore JSON:

```py
>>> kp.import_keystore(
...     "./my-keystore.json",
...     password="keystore-password",
...     alias="imported-json",
... )
<Account 0x104da57BF95262B119553181bA62dD5B8F204f49 signable>
```

### 4. Set aliases

You can set aliases for accounts to simplify retrieval later. A single account can have multiple aliases.

```py
>>> kp.set_alias(acct, "hot")
>>> kp.set_alias(acct, "trading")

>>> kp["hot"]
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>

>>> kp["0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68"]
<Account 0x0D3AaC9458167352493864Af54D1CBD7F1B8fF68 signable>

>>> kp["hot"] == kp["trading"] == acct
True
```

### 5. Add watch-only accounts

If you assign an alias to an address that has no private key in the keypass, it is stored as a watch-only account.

This lets you keep named references to important addresses and retrieve them later by alias.

```py
>>> kp.set_alias("0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045", "vitalik")

>>> kp["vitalik"]
<Account 0xd8dA6BF26964aF9D7eEd9e03E53415D37aA96045 watch-only>
```

### 6. Sign a transaction

Here we build a transaction from one of our signing accounts to send to one of our watch-only accounts.

```py
>>> tx = {
...     "to": kp["vitalik"],
...     "value": 10**18,
...     "gas": 21_000,
...     "maxFeePerGas": 30_000_000_000,
...     "maxPriorityFeePerGas": 2_000_000_000,
...     "nonce": 0,
...     "chainId": 1
... }
>>> signed = kp["hot"].sign_transaction(tx)

>>> signed
SignedTransaction(raw_transaction=b'\x02...', hash=b'\xa1...', r=..., s=..., v=1)
```

### 7. Sign messages

The `Account` object also exposes methods for signing messages and authorizations.

```py
Account.sign_authorization(authorization_dict: dict[str, Any])
```

```py
Account.sign_message(signable_message: Any)
```

```py
Account.sign_typed_data(
    domain_data: dict[str, Any] | None = None,
    message_types: dict[str, Any] | None = None,
    message_data: dict[str, Any] | None = None,
    full_message: dict[str, Any] | None = None,
)
```

All signing methods implement an equivalent API to the same-named functions in the [`eth-account`](https://github.com/ethereum/eth-account) library.

### 8. Default keypass and accounts

You can create a "default" keypass by calling `create` with no arguments:

```py
>>> fw3_keypass.create()
Create password for new keypass 'default':
<KeypassDB path=/home/user/.local/share/fw3-keypass/default.sqlite3 unlocked>
```

Every keypass also maintains a default account.

```py
>>> kp.default_account
fw3_keypass.errors.NoDefaultAccountError: database has no default account set

>>> kp.create_account(alias="degen", set_as_default=True)
<Account 0xcc27b3Be484E3692737993ca8273349e9483454D signable>

>>> kp.default_account
<Account 0xcc27b3Be484E3692737993ca8273349e9483454D signable>
```

This makes portable scripts possible. Each user signs using **their own default keypass and account**.

```py
import fw3_keypass

kp = fw3_keypass.unlock()

acct = kp.default_account
acct.sign_transaction(...)
```

## Tests

First, install the dev dependencies:

```bash
pip install -e ".[dev]"
```

To run the test suite:

```bash
pytest
```

## License

This project is licensed under the [MIT license](LICENSE).
