Skip to content

Commit

Permalink
Changes for the 1.0 beta
Browse files Browse the repository at this point in the history
  • Loading branch information
andreasgriffin committed Oct 13, 2024
1 parent e1a0151 commit 064ff05
Show file tree
Hide file tree
Showing 251 changed files with 27,491 additions and 9,388 deletions.
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
* text=auto
*.txt text eol=lf
*.sh text eol=lf
*.py text eol=lf
*.js text eol=lf
*.css text eol=lf
*.html text eol=lf
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -201,3 +201,5 @@ bitcoin_safe.dist-info

screenshots*/
.DS_Store

profile.html
32 changes: 22 additions & 10 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ repos:
types: [python]
files: '\.py$'

- repo: https://github.com/pre-commit/mirrors-isort
rev: v5.10.1 # Use the specified version of isort
- repo: https://github.com/pycqa/isort
rev: 5.13.2 # Use the specified version of isort
hooks:
- id: isort
args:
- --profile=black # Set the import order style (change 'google' to your preferred style)
- repo: https://github.com/myint/autoflake
rev: v2.3.0 # Use the latest version of autoflake
rev: v2.3.1 # Use the latest version of autoflake
hooks:
- id: autoflake
args:
Expand All @@ -26,28 +26,40 @@ repos:
- --exclude=__init__.py
- --remove-duplicate-keys
- repo: https://github.com/ambv/black
rev: 22.3.0
rev: 24.8.0
hooks:
- id: black
language_version: python3.10
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.9.0 # Use the latest MyPy version
rev: v1.11.2 # Use the latest MyPy version
hooks:
- id: mypy
# Additional arguments to MyPy can be added here
files: ^bitcoin_safe/
args:
- --check-untyped-defs
# - --disallow-untyped-defs
# - --disallow-incomplete-defs
# - --strict-optional
# - --no-implicit-optional
- --implicit-optional
- --strict-equality
# - --warn-return-any
- --warn-redundant-casts
# - --warn-unreachable
- --warn-unreachable
# - --disallow-any-generics
# - --strict
- --install-types
- --non-interactive
- --ignore-missing-imports
- --show-error-codes
additional_dependencies:
- types-requests
- types-PyYAML
- types-toml

- types-toml
- pytest-mypy
- types-Pillow
- types-reportlab
- pyqt6
- bdkpython

- repo: local
hooks:
Expand Down
31 changes: 22 additions & 9 deletions .vscode/launch.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@
"--ignore=coding_tests",
],
"console": "integratedTerminal",
"justMyCode": true
// "justMyCode": false
},
{
"name": "Pytest gui",
Expand All @@ -38,7 +38,7 @@
"-s", // Disable all capturing of outputs
],
"console": "integratedTerminal",
"justMyCode": true
"justMyCode": false
},
{
"name": "Pytest non-gui",
Expand All @@ -52,8 +52,21 @@
"-s", // Disable all capturing of outputs
],
"console": "integratedTerminal",
"justMyCode": true
}, {
"justMyCode": false
}, {
"name": "Pytest: Current File",
"type": "python",
"request": "launch",
"module": "pytest",
"args": [
"-vvv",
"${file}",
"-s", // Disable all capturing of outputs
],
"console": "integratedTerminal",
"justMyCode": false
},
{
"name": "taglist",
"type": "python",
"request": "launch",
Expand Down Expand Up @@ -118,11 +131,11 @@
],
"console": "integratedTerminal"
},{
"name": "Python: Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
"name": "Current File",
"type": "python",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal"
}

]
Expand Down
2 changes: 1 addition & 1 deletion .vscode/tasks.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
{
"label": "Poetry Install",
"type": "shell",
"command": "poetry install",
"command": "python -m poetry install",
"options": {
"cwd": "${workspaceFolder}" // Ensures command runs in the project root
},
Expand Down
32 changes: 16 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,31 @@

#### Long-term Bitcoin savings made Easy

#### ⚠️ Currently ALPHA -- Use only on regtest / testnet / signet ⚠️
#### BETA Version -- Use with Caution

## Features

- **Easy** Multisig-Wallet Setup
- Step-by-Step instructions with a PDF backup sheet
- test signing with all hardware signer
- Step-by-Step instructions for a secure MultiSig setup with PDF backup sheets
- Test transactions enure that all hardware signers are ready
- Full support for [Coldcard](https://coldcard.com/), [Coldcard Q](https://coldcard.com/), [Bitbox02](https://shiftcrypto.ch/bitbox02/?ref=MOB4dk7gpm), [Blockstream Jade](https://store.blockstream.com/?code=XEocg5boS77D), and Specter DIY, supporting QR, USB, Sd card
- **Secure**: Hardware signers only
- All wallets require hardware signers/wallets for safe seed storage
- Powered by **[BDK](https://github.com/bitcoindevkit/bdk)**
- **Multi-Language**:
- 🇺🇸 English, 🇨🇳 Chinese - 简体中文, 🇪🇸 Spanish - español de España, 🇯🇵 Japanese - 日本語, 🇷🇺 Russian - русский, 🇵🇹 Portuguese - português europeu, 🇮🇳 Hindi - हिन्दी, Arabic - العربية, 🇮🇹 Italian - italiano, 🇫🇷 French - Français, (more upon request)
- **Simpler** address labels by using categories (e.g. "KYC", "Non-KYC", "Work", "Friends", ...)
- Automatic coin selection within categories
- Transaction flow diagrams, visualizing inputs and outputs
- **Sending** for non-technical users
- 1-click fee selection
- 1-click fee selection via mempool-blocks
- Automatic merging of small utxos when fees are low
- **Collaborative**:
- Wallet chat and sharing of PSBTs (via nostr)
- Label synchronization between trusted devices (via nostr)
- **Multi-Language**:
- 🇺🇸 English, 🇨🇳 Chinese - 简体中文, 🇪🇸 Spanish - español de España, 🇯🇵 Japanese - 日本語, 🇷🇺 Russian - русский, 🇵🇹 Portuguese - português europeu, 🇮🇳 Hindi - हिन्दी, Arabic - العربية, 🇮🇹 Italian - italiano, (more upon request)
- Label synchronization between different computers and encrypted cloud backup
- Wallet chat and PSBTs sharing between different computers
- **Fast**:
- Electrum server connectivity
- Electrum server syncing
- planned upgrade to **Compact Block Filters** for the Bitcoin Safe 2.0 release
- **Secure**: No seed generation or storage (on mainnet).
- A hardware signer/signing device for safe seed storage is needed (storing seeds on a computer is reckless)
- Powered by **[BDK](https://github.com/bitcoindevkit/bdk)**

## Preview

Expand Down Expand Up @@ -53,6 +55,7 @@
- **Import and Export Capabilities**

- CSV export for all lists
- CSV import for batch transactions
- Label import and export using [BIP329](https://bip329.org/)
- Label import from Electrum wallet
- Drag and drop for Transactions, PSBTs, and CSV files
Expand All @@ -69,7 +72,7 @@

- MicroSD (files)
- USB
- QR codes
- QR codes (enhanced QR code detection for Laptop cameras)
- Animated QR codes including [BBQr](https://bbqr.org/) and legacy formats

- **Search and Filtering Options**
Expand Down Expand Up @@ -107,9 +110,6 @@
- Compact Block Filters are **fast** and **private**
- Compact Block Filters (bdk) are being [worked on](https://github.com/bitcoindevkit/bdk/issues/679), and will be included in bdk 1.1. For now RPC, Electrum and Esplora are available, but will be replaced completely with Compact Block Filters.

#### TODOs for beta release

- [ ] Add more pytests

## Installation from Git repository

Expand Down
2 changes: 1 addition & 1 deletion bitcoin_safe/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
# this is the source of the version information
__version__ = "0.7.4a0"
__version__ = "1.0.0b0"
16 changes: 8 additions & 8 deletions bitcoin_safe/config.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,21 +66,21 @@ class UserConfig(BaseSaveableClass):
config_file = config_dir / (app_name + ".conf")

fee_ranges = {
bdk.Network.BITCOIN: [1, 1000],
bdk.Network.REGTEST: [0, 1000],
bdk.Network.SIGNET: [0, 1000],
bdk.Network.TESTNET: [0, 1000],
bdk.Network.BITCOIN: [1.0, 1000],
bdk.Network.REGTEST: [0.0, 1000],
bdk.Network.SIGNET: [0.0, 1000],
bdk.Network.TESTNET: [0.0, 1000],
}

def __init__(self) -> None:
self.network_configs = NetworkConfigs()
self.network = bdk.Network.BITCOIN if DEFAULT_MAINNET else bdk.Network.TESTNET
self.network: bdk.Network = bdk.Network.BITCOIN if DEFAULT_MAINNET else bdk.Network.TESTNET
self.last_wallet_files: Dict[str, List[str]] = {} # network:[file_path0]
self.opened_txlike: Dict[str, List[str]] = {} # network:[serializedtx, serialized psbt]
self.data_dir = appdirs.user_data_dir(self.app_name)
self.is_maximized = False
self.recently_open_wallets: Dict[bdk.Network, deque[str]] = {
network: deque(maxlen=5) for network in bdk.Network
network: deque(maxlen=15) for network in bdk.Network
}
self.language_code: Optional[str] = None

Expand Down Expand Up @@ -178,11 +178,11 @@ def exists(cls, password=None, file_path=None) -> bool:
return os.path.isfile(file_path)

@classmethod
def from_file(cls, password=None, file_path=None) -> "UserConfig":
def from_file(cls, password: str | None = None, file_path: Path | None = None) -> "UserConfig":
if file_path is None:
file_path = cls.config_file
if os.path.isfile(file_path):
return super()._from_file(file_path, password=password)
return super()._from_file(str(file_path), password=password)
else:
return UserConfig()

Expand Down
5 changes: 4 additions & 1 deletion bitcoin_safe/descriptors.py
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ def from_keystores(
for p in change_spk_providers:
p.derivation_path = ConstDerivationPaths.change

return MultipathDescriptor(
return cls(
DescriptorInfo(
address_type=address_type,
spk_providers=receive_spk_providers,
Expand All @@ -84,3 +84,6 @@ def from_keystores(
threshold=threshold,
).get_bdk_descriptor(network),
)

def __str__(self) -> str:
return self.as_string()
31 changes: 21 additions & 10 deletions bitcoin_safe/dynamic_lib_load.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import os
import platform
import sys
from ctypes.util import find_library
from importlib.metadata import PackageMetadata
from typing import Optional

Expand All @@ -52,11 +53,11 @@ def show_message_before_quit(msg: str) -> None:
# Initialize QApplication first
app = QApplication(sys.argv)
# Without an application instance, some features might not work as expected
QMessageBox.warning(None, "Warning", msg, QMessageBox.StandardButton.Ok)
QMessageBox.warning(None, "Warning", msg, QMessageBox.StandardButton.Ok) # type: ignore[arg-type]
sys.exit(app.exec())


def _get_binary_lib_path() -> str:
def _get_binary_lib_path_from_electrumsv() -> str:
# Get the platform-specific path to the binary library
if platform.system() == "Windows":
# On Windows, construct the path to the DLL
Expand All @@ -68,6 +69,19 @@ def _get_binary_lib_path() -> str:
return lib_path


def is_libsecp256k1_available() -> bool:
"""
Try to find the 'libsecp256k1' library in the system's standard library locations.
Returns:
str: The full path to the library if found, otherwise None.
"""
# Define the library name based on the operating system specifics
lib_name = "secp256k1"

return bool(find_library(lib_name))


def setup_libsecp256k1() -> None:
"""The operating system might, or might not provide libsecp256k1 needed for bitcointx
Expand All @@ -79,20 +93,17 @@ def setup_libsecp256k1() -> None:
# which is needed for bitcointx.
# bitcointx and with it the prebuild libsecp256k1 is not used for anything security critical
# key derivation with bitcointx is restricted to testnet/regtest/signet
# and the PSBTFinalizer using bitcointx is safe because it handles no key material
# and the PSBTTools using bitcointx is safe because it handles no key material
"""
from .execute_config import USE_OS_libsecp256k1

if not USE_OS_libsecp256k1:
lib_path = _get_binary_lib_path()
if is_libsecp256k1_available():
logger.info(f"libsecp256k1: Found on OS")
else:
lib_path = _get_binary_lib_path_from_electrumsv()
print(f"setting libsecp256k1 path {lib_path}")
bitcoin_usb.set_custom_secp256k1_path(lib_path)
bitcointx.set_custom_secp256k1_path(lib_path)

print(f"set libsecp256k1 path {lib_path}")
else:
print(f"use libsecp256k1 from os")


def ensure_pyzbar_works() -> None:
"Ensure Visual C++ Redistributable Packages for Visual Studio 2013"
Expand Down
3 changes: 1 addition & 2 deletions bitcoin_safe/execute_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,5 @@
# SOFTWARE.


USE_OS_libsecp256k1 = False
DEFAULT_MAINNET = False
DEFAULT_MAINNET = True
ENABLE_THREADING = True
17 changes: 11 additions & 6 deletions bitcoin_safe/fx.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
from typing import Dict

from bitcoin_safe.signals import SignalsMin
from bitcoin_safe.threading_manager import ThreadingManager

logger = logging.getLogger(__name__)

Expand All @@ -40,12 +41,11 @@
from .mempool import threaded_fetch


class FX(QObject):
class FX(QObject, ThreadingManager):
signal_data_updated = pyqtSignal()

def __init__(self, signals_min: SignalsMin) -> None:
super().__init__()
self.signals_min = signals_min
def __init__(self, signals_min: SignalsMin, threading_parent: ThreadingManager | None = None) -> None:
super().__init__(signals_min=signals_min, threading_parent=threading_parent) # type: ignore

self.rates: Dict[str, Dict] = {}
self.update()
Expand All @@ -59,6 +59,11 @@ def on_success(data) -> None:
self.rates = data.get("rates", {})
self.signal_data_updated.emit()

threaded_fetch(
"https://api.coingecko.com/api/v3/exchange_rates", on_success, self, signals_min=self.signals_min
self.taskthreads.append(
threaded_fetch(
"https://api.coingecko.com/api/v3/exchange_rates",
on_success,
self,
signals_min=self.signals_min,
)
)
Loading

0 comments on commit 064ff05

Please sign in to comment.