refactoring: deduplicate wallet, rate source, and API handler logic - #237
refactoring: deduplicate wallet, rate source, and API handler logic#237olegsta wants to merge 2 commits into
Conversation
olegsta
commented
Jun 25, 2026
- Extract shared UTXO HTTP wallet logic into UtxoHttpWallet for BTC, LTC, and DOGE
- Consolidate EVM chain classes (ETH, Polygon, Arbitrum, Optimism, BNB, Avalanche, Solana, TON, XRP) into configurable Ethereum base with chain-specific attributes and hooks
- Simplify Binance, Coinbase, Kraken, and KuCoin rate providers to use shared normalization
- Add api/helpers.py with resolve_available_crypto(), api_error_response(), verify_backend_key(), and handle_request_error()
- Refactor api_v1 endpoints to use shared helpers and remove duplicated error/backend-key handling
- Extract shared UTXO HTTP wallet logic into UtxoHttpWallet for BTC, LTC, and DOGE - Consolidate EVM chain classes (ETH, Polygon, Arbitrum, Optimism, BNB, Avalanche, Solana, TON, XRP) into configurable Ethereum base with chain-specific attributes and hooks - Move rate symbol normalization into RateSource.normalize_symbols(), including MATIC→POL and optional TON→GRAM mappings - Simplify Binance, Coinbase, Kraken, and KuCoin rate providers to use shared normalization - Add api/helpers.py with resolve_available_crypto(), api_error_response(), verify_backend_key(), and handle_request_error() - Refactor api_v1 endpoints to use shared helpers and remove duplicated error/backend-key handling - Register inject_theme once at app level in create_app() instead of duplicating it in auth and wallet blueprints
| if error := verify_backend_key(): | ||
| return error | ||
|
|
||
| Crypto.instances[crypto_name] |
There was a problem hiding this comment.
I removed the variable because it was unused. Here we only need to validate that crypto_name exists in Crypto.instances; direct access Crypto.instances[crypto_name] is enough and keeps the intent explicit (raise Exception).
| try: | ||
| crypto = Crypto.instances[crypto_name] | ||
| bkey = environ.get(f"SHKEEPER_BTC_BACKEND_KEY", "shkeeper") | ||
| Crypto.instances[crypto_name] |
There was a problem hiding this comment.
I removed the variable because it was unused. Here we only need to validate that crypto_name exists in Crypto.instances; direct access Crypto.instances[crypto_name] is enough and keeps the intent explicit (raise KeyError if missing).
| bkey = environ.get(f"SHKEEPER_BTC_BACKEND_KEY", "shkeeper") | ||
| Crypto.instances[crypto_name] | ||
| bkey = environ.get("SHKEEPER_BTC_BACKEND_KEY", "shkeeper") | ||
| if request.headers["X-Shkeeper-Backend-Key"] != bkey: |
There was a problem hiding this comment.
why not use verify_backend_key() ?
There was a problem hiding this comment.
Changed to verify_backend_key
There was a problem hiding this comment.
Pull request overview
Refactors the wallet, rate-source, and API layers to centralize repeated logic and make chain/provider-specific behavior configurable via shared base classes and helpers.
Changes:
- Introduces
UtxoHttpWalletfor BTC/LTC/DOGE and refactors those coin classes to inherit from it. - Consolidates multiple chain classes into the
Ethereumbase by moving host/creds/status/payout logic into overridable hooks + chain-specific attributes. - Centralizes rate-symbol normalization in
RateSourceand API error/backend-key handling inshkeeper/api/helpers.py, then refactorsapi_v1endpoints to use them.
Reviewed changes
Copilot reviewed 23 out of 23 changed files in this pull request and generated 5 comments.
Show a summary per file
| File | Description |
|---|---|
| shkeeper/wallet.py | Removes blueprint-level theme injection (now app-level). |
| shkeeper/auth.py | Removes blueprint-level theme injection (now app-level). |
| shkeeper/init.py | Adds app-wide inject_theme() context processor. |
| shkeeper/api/helpers.py | Adds shared API helpers (crypto resolution, backend key, error wrapping). |
| shkeeper/api_v1.py | Refactors endpoints to use shared API helpers. |
| shkeeper/modules/classes/utxo_http_wallet.py | Adds shared HTTP wallet implementation for UTXO coins. |
| shkeeper/modules/classes/btc.py | Switches BTC to UtxoHttpWallet and enables tx logging. |
| shkeeper/modules/classes/ltc.py | Switches LTC to UtxoHttpWallet. |
| shkeeper/modules/classes/doge.py | Switches DOGE to UtxoHttpWallet. |
| shkeeper/modules/classes/ethereum.py | Adds configurable env prefixes/host + hook points for status/payout logic. |
| shkeeper/modules/classes/arbitrum.py | Converts Arbitrum to Ethereum-configured subclass. |
| shkeeper/modules/classes/avalanche.py | Converts Avalanche to Ethereum-configured subclass. |
| shkeeper/modules/classes/bnb.py | Converts BNB to Ethereum-configured subclass. |
| shkeeper/modules/classes/optimism.py | Converts Optimism to Ethereum-configured subclass with distinct creds prefix. |
| shkeeper/modules/classes/polygon.py | Converts Polygon to Ethereum-configured subclass. |
| shkeeper/modules/classes/solana.py | Converts Solana to Ethereum-configured subclass with status tuning. |
| shkeeper/modules/classes/ton.py | Converts TON to Ethereum-configured subclass with float block interval + lag multiplier. |
| shkeeper/modules/classes/xrp.py | Converts XRP to Ethereum-configured subclass with timestamp/fee hooks. |
| shkeeper/modules/classes/rate_source.py | Adds shared symbol normalization + USDT/USD parity handling. |
| shkeeper/modules/rates/binance.py | Uses shared normalization helper. |
| shkeeper/modules/rates/coinbase.py | Uses shared normalization helper. |
| shkeeper/modules/rates/kraken.py | Uses shared normalization helper (including parity shortcut). |
| shkeeper/modules/rates/kucoin.py | Uses shared normalization helper with KuCoin-specific options. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| def _subtract_payout_fee(self, amount, fee): | ||
| # 10 XRP need to keep the fee-deposit account active | ||
| return amount - fee - 10 |
There was a problem hiding this comment.
I fixed it, but that logic was already in the master branch
| block_interval = self.block_interval | ||
| if delta < block_interval * self.sync_lag_multiplier: | ||
| return "Synced" | ||
| else: | ||
| return "Sync In Progress (%d blocks behind)" % (delta // block_interval) |
There was a problem hiding this comment.
The logic is the same as in master. This MR only refactors the code without changing its behavior
3026528 to
5d55a0b
Compare
- Change log text - Change subtractpayout fee logic
5d55a0b to
b3db839
Compare