Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -56,13 +56,13 @@ jobs:

- name: Create and fund an account
run: |
go run ./cmd/golembase account create
go run ./cmd/golembase account fund
printf "password" | go run ./cmd/golembase account create
printf "password" | go run ./cmd/golembase account fund
working-directory: ./gb-op-geth

- name: Run the example SDK app
run: >
nix develop --no-write-lock-file --reference-lock-file ../flake.lock --command
printf "password" | nix develop --no-write-lock-file --reference-lock-file ../flake.lock --command
./result/bin/main --instance local
working-directory: ./example

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ The repo also contains an example application to showcase how you can use this S

(Note: As an alternative to installing the demo CLI, you can build the [actual CLI](https://github.com/Golem-Base/golembase-op-geth/blob/main/cmd/golembase/README.md) as it's included in the golembase-op-geth repo.)

When you create a user, it will generate a private key file called `private.key` and store it in:
When you create a user, it will generate a private key file called `wallet.json` and store it in:

* `~/.config/golembase/` on **Linux**
* `~/Library/Application Support/golembase/` on **macOS**
Expand Down
15 changes: 8 additions & 7 deletions example/golem_base_sdk_example/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,16 +5,16 @@
import logging
import logging.config

import anyio
from golem_base_sdk import (
Annotation,
GolemBaseClient,
GolemBaseCreate,
GolemBaseDelete,
GolemBaseExtend,
GolemBaseUpdate,
WalletError,
decrypt_wallet,
)
from xdg import BaseDirectory

logging.config.dictConfig(
{
Expand Down Expand Up @@ -59,11 +59,12 @@

async def run_example(instance: str) -> None: # noqa: PLR0915
"""Run the example."""
async with await anyio.open_file(
BaseDirectory.xdg_config_home + "/golembase/private.key",
"rb",
) as private_key_file:
key_bytes = await private_key_file.read(32)
try:
key_bytes = await decrypt_wallet()
except WalletError as e:
print(f"Error: {e}")
except KeyboardInterrupt:
print("\nOperation cancelled by user.")

client = await GolemBaseClient.create(
rpc_url=INSTANCE_URLS[instance]["rpc"],
Expand Down
7 changes: 7 additions & 0 deletions golem_base_sdk/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,10 @@
WatchLogsHandle,
)
from .utils import rlp_encode_transaction
from .wallet import (
WalletError,
decrypt_wallet,
)

__all__: Sequence[str] = [
# Exports from .types
Expand All @@ -73,6 +77,9 @@
# Exports from .constants
"GOLEM_BASE_ABI",
"STORAGE_ADDRESS",
# Exports from .wallet
"decrypt_wallet",
"WalletError",
# Exports from this file
"GolemBaseClient",
# Re-exports
Expand Down
44 changes: 44 additions & 0 deletions golem_base_sdk/wallet.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
"""Wallet module for creating and decrypting Ethereum wallets."""

import getpass
import json
import sys
from pathlib import Path
from typing import cast

import anyio
from eth_account import Account
from xdg import BaseDirectory

WALLET_PATH = Path(BaseDirectory.xdg_config_home) / "golembase" / "wallet.json"

class WalletError(Exception):
"""Base class for wallet-related errors."""

pass

async def decrypt_wallet() -> bytes:
"""Decrypts the wallet and returns the private key bytes."""
if not WALLET_PATH.exists():
raise WalletError(f"Expected wallet file to exist at '{WALLET_PATH}'")

async with await anyio.open_file(
WALLET_PATH,
"r",
) as f:
keyfile_json = json.loads(await f.read())

if not sys.stdin.isatty():
password = sys.stdin.read().rstrip()
else:
password = getpass.getpass("Enter password to decrypt wallet: ")

try:
print(f"Attempting to decrypt wallet at '{WALLET_PATH}'")
private_key = Account.decrypt(keyfile_json, password)
print("Successfully decrypted wallet")
except ValueError as e:
raise WalletError("Incorrect password or corrupted wallet file.") from e

return cast(bytes, private_key)

1 change: 1 addition & 0 deletions nix/devshell.nix
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ perSystem.devshell.mkShell {
packages = [
virtualenvDev
pkgs.uv
pkgs.ruff
];

env = [
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ requires-python = ">=3.12"
dynamic = ["description"]

dependencies = [
"anyio>=4.10.0",
"pyxdg>=0.28",
"rlp>=1.2.0",
"web3>=4.7.2",
]
Expand Down
36 changes: 36 additions & 0 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.