btc-toolkit 1.0.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Davi de Jesus
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,256 @@
1
+ Metadata-Version: 2.4
2
+ Name: btc-toolkit
3
+ Version: 1.0.0
4
+ Summary: Bitcoin CLI toolkit — OP_RETURN decoder, balance checker, fee estimator & more. Zero deps, no Bitcoin Core required.
5
+ Author-email: Davi de Jesus <devdavidejesus@users.noreply.github.com>
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/devdavidejesus/btc-toolkit
8
+ Project-URL: Repository, https://github.com/devdavidejesus/btc-toolkit
9
+ Project-URL: Issues, https://github.com/devdavidejesus/btc-toolkit/issues
10
+ Keywords: bitcoin,op_return,balance,mempool,cli,blockchain
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Environment :: Console
13
+ Classifier: Intended Audience :: Developers
14
+ Classifier: License :: OSI Approved :: MIT License
15
+ Classifier: Operating System :: OS Independent
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Topic :: Software Development :: Libraries
22
+ Classifier: Topic :: Utilities
23
+ Requires-Python: >=3.10
24
+ Description-Content-Type: text/markdown
25
+ License-File: LICENSE
26
+ Dynamic: license-file
27
+
28
+ <div align="center">
29
+
30
+ # ₿ btc-toolkit
31
+
32
+ **Bitcoin CLI toolkit — zero dependencies, no Bitcoin Core required.**
33
+
34
+ Query the Bitcoin network directly via the [Mempool.space](https://mempool.space) public API.
35
+
36
+ [![Tests](https://github.com/devdavidejesus/btc-toolkit/actions/workflows/tests.yml/badge.svg)](https://github.com/devdavidejesus/btc-toolkit/actions/workflows/tests.yml)
37
+ [![Version](https://img.shields.io/github/v/tag/devdavidejesus/btc-toolkit?label=version&color=F7931A)](https://github.com/devdavidejesus/btc-toolkit/tags)
38
+ [![Python](https://img.shields.io/badge/python-3.10%2B-3776AB?logo=python&logoColor=white)](https://github.com/devdavidejesus/btc-toolkit/blob/main/pyproject.toml)
39
+ [![Dependencies](https://img.shields.io/badge/dependencies-zero-success)](https://github.com/devdavidejesus/btc-toolkit/blob/main/pyproject.toml)
40
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
41
+
42
+ </div>
43
+
44
+ ---
45
+
46
+ ## Commands
47
+
48
+ | Command | Description | Status |
49
+ |---|---|---|
50
+ | `btc-toolkit opreturn <txid>` | Decode OP_RETURN messages from a transaction | ✅ Phase 1 |
51
+ | `btc-toolkit balance <address>` | Confirmed + unconfirmed balance of any address | ✅ Phase 2 |
52
+ | `btc-toolkit fees` | Recommended fee rates + mempool backlog | ✅ Phase 3 |
53
+ | `btc-toolkit block <height\|hash>` | Block metadata by height, hash, or latest | ✅ Phase 4 |
54
+ | `btc-toolkit utxo <address>` | Unspent outputs of any address | ✅ Phase 5 |
55
+
56
+ ## Installation
57
+
58
+ **Requirements:** Python 3.10+
59
+
60
+ ```bash
61
+ git clone https://github.com/devdavidejesus/btc-toolkit.git
62
+ cd btc-toolkit
63
+ pip install -e .
64
+ ```
65
+
66
+ ## Usage
67
+
68
+ ### balance — check any address
69
+
70
+ ```bash
71
+ btc-toolkit balance 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
72
+ ```
73
+
74
+ Shows confirmed balance, unconfirmed (mempool) balance, and total — in BTC and satoshis. Supports all address types: Legacy (P2PKH), P2SH, SegWit (Bech32), and Taproot.
75
+
76
+ ```bash
77
+ # JSON output for scripting
78
+ btc-toolkit balance <address> --json
79
+
80
+ # Testnet
81
+ btc-toolkit balance <address> --network testnet
82
+ ```
83
+
84
+ BTC conversion uses integer arithmetic (no floats) — satoshi-exact, always.
85
+
86
+ ### fees — current rates and mempool backlog
87
+
88
+ ```bash
89
+ btc-toolkit fees
90
+ ```
91
+
92
+ Shows the five recommended fee tiers (sat/vB) — fastest, half hour, hour, economy, minimum — plus mempool backlog: pending tx count, size in vMB, and a rough estimate of blocks needed to clear it.
93
+
94
+ ```bash
95
+ # JSON output for scripting
96
+ btc-toolkit fees --json
97
+
98
+ # Testnet
99
+ btc-toolkit fees --network testnet
100
+ ```
101
+
102
+ ### block — inspect any block
103
+
104
+ ```bash
105
+ btc-toolkit block latest # chain tip
106
+ btc-toolkit block 0 # by height (genesis)
107
+ btc-toolkit block 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f # by hash
108
+ ```
109
+
110
+ Shows height, hash, mined timestamp (UTC), tx count, size, weight, difficulty, nonce, and previous block hash.
111
+
112
+ ```bash
113
+ # JSON output for scripting
114
+ btc-toolkit block latest --json
115
+
116
+ # Testnet
117
+ btc-toolkit block latest --network testnet
118
+ ```
119
+
120
+ ### utxo — unspent outputs of any address
121
+
122
+ ```bash
123
+ btc-toolkit utxo bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq
124
+ ```
125
+
126
+ Lists every UTXO sorted by value (largest first), with txid:vout, value in BTC and sats, confirmation status, and block height. Shows aggregate count and total value.
127
+
128
+ > **Known limitation:** addresses with tens of thousands of UTXOs (e.g. Satoshi's genesis address, ~76k donation outputs) exceed the upstream electrs response limit and return HTTP 400. Use `balance` for aggregate stats on such addresses — discovered and verified in production.
129
+
130
+ ```bash
131
+ # Only confirmed UTXOs
132
+ btc-toolkit utxo <address> --confirmed-only
133
+
134
+ # Show more than 15 entries
135
+ btc-toolkit utxo <address> --limit 50
136
+
137
+ # JSON output (always includes all UTXOs)
138
+ btc-toolkit utxo <address> --json
139
+ ```
140
+
141
+ ### opreturn — decode embedded messages
142
+
143
+ ```bash
144
+ btc-toolkit opreturn f4ac7abcb689df30ec5e8d829733622f389ca91367c47b319bc582e653cd8cab
145
+ ```
146
+
147
+ ![OP_RETURN Reader demo](assets/demo.png)
148
+
149
+ ```bash
150
+ # JSON output
151
+ btc-toolkit opreturn <txid> --json
152
+
153
+ # Raw hex only
154
+ btc-toolkit opreturn <txid> --raw
155
+ ```
156
+
157
+ ### Transactions to Try
158
+
159
+ Real, verified OP_RETURN transactions on mainnet. Verify each one yourself on [mempool.space](https://mempool.space).
160
+
161
+ | TXID | Description |
162
+ |---|---|
163
+ | `f4ac7abcb689df30ec5e8d829733622f389ca91367c47b319bc582e653cd8cab` | "Craig Wright is a liar and a fraud" — 34 bytes ([verify on-chain](https://mempool.space/tx/f4ac7abcb689df30ec5e8d829733622f389ca91367c47b319bc582e653cd8cab)) |
164
+ | `2033435de7ce307341231e818ed937cd3a5e8597381fd83a7e5b0234f61b38d3` | "learnmeabitcoin" — 75-byte OP_RETURN with null-padded ASCII ([verify on-chain](https://mempool.space/tx/2033435de7ce307341231e818ed937cd3a5e8597381fd83a7e5b0234f61b38d3)) |
165
+
166
+ > **Note:** Satoshi's famous "Chancellor on brink of second bailout for banks" message is in the
167
+ > **coinbase scriptSig** of the genesis block — NOT in an OP_RETURN output. That's a common
168
+ > misconception. This tool reads OP_RETURN outputs only, which is the standard mechanism
169
+ > for embedding data in Bitcoin transactions (introduced as standard in Bitcoin Core v0.9.0, March 2014).
170
+
171
+ ## Architecture
172
+
173
+ ```
174
+ btc-toolkit/
175
+ ├── btc_toolkit/
176
+ │ ├── __init__.py # Package version
177
+ │ ├── __main__.py # python -m entry point
178
+ │ ├── cli.py # Unified CLI with subcommands
179
+ │ ├── api.py # Shared Mempool.space HTTP client
180
+ │ ├── colors.py # Shared terminal color helpers
181
+ │ ├── opreturn.py # Phase 1 — OP_RETURN decoder
182
+ │ ├── balance.py # Phase 2 — Address balance checker
183
+ │ ├── fees.py # Phase 3 — Fee estimator
184
+ │ ├── block.py # Phase 4 — Block info explorer
185
+ │ └── utxo.py # Phase 5 — UTXO set inspector
186
+ ├── tests/
187
+ │ ├── test_opreturn.py # 18 tests (mocked API + parser validation)
188
+ │ ├── test_balance.py # 18 tests (sats math + API response parsing)
189
+ │ ├── test_fees.py # 6 tests (rates + backlog parsing)
190
+ │ ├── test_block.py # 12 tests (ref detection + genesis data)
191
+ │ └── test_utxo.py # 8 tests (aggregates + filters)
192
+ ├── pyproject.toml
193
+ ├── LICENSE # MIT
194
+ └── README.md
195
+ ```
196
+
197
+ Every subcommand shares one HTTP client (`api.py`) — new phases add a module + a subcommand, nothing else.
198
+
199
+ Zero external dependencies — Python standard library only (`urllib`, `json`, `argparse`).
200
+
201
+ ## Testing
202
+
203
+ ```bash
204
+ python -m pytest tests/ -v
205
+ ```
206
+
207
+ 62 tests, all API calls mocked — the suite runs offline.
208
+
209
+ ![Tests passing](assets/tests.png)
210
+
211
+ ## How balance is computed
212
+
213
+ The Mempool.space `/address` endpoint returns `chain_stats` (confirmed) and `mempool_stats` (unconfirmed), each with `funded_txo_sum` and `spent_txo_sum` in satoshis.
214
+
215
+ ```
216
+ confirmed = chain_stats.funded_txo_sum - chain_stats.spent_txo_sum
217
+ unconfirmed = mempool_stats.funded_txo_sum - mempool_stats.spent_txo_sum
218
+ total = confirmed + unconfirmed
219
+ ```
220
+
221
+ This is the same model used by Esplora/Electrs. Don't trust this README — verify against `https://mempool.space/api/address/<address>` yourself.
222
+
223
+ ## Roadmap
224
+
225
+ - [x] **Phase 1** — OP_RETURN Reader
226
+ - [x] **Phase 2** — Address Balance Checker
227
+ - [x] **Phase 3** — Fee Estimator (mempool-based)
228
+ - [x] **Phase 4** — Block Info Explorer
229
+ - [x] **Phase 5** — UTXO Set Inspector
230
+
231
+ All five phases complete — one philosophy throughout: **zero dependencies, no Bitcoin Core, verify everything on-chain.**
232
+
233
+ ## Don't Trust, Verify
234
+
235
+ Every txid, address, hex value, and technical claim in this README can be independently verified:
236
+ - Transaction data: `https://mempool.space/api/tx/<txid>`
237
+ - Address data: `https://mempool.space/api/address/<address>`
238
+ - Fee data: `https://mempool.space/api/v1/fees/recommended`
239
+ - Block data: `https://mempool.space/api/block/<hash>`
240
+ - UTXO data: `https://mempool.space/api/address/<address>/utxo`
241
+ - OP_RETURN spec: [learnmeabitcoin.com/technical/script/return](https://learnmeabitcoin.com/technical/script/return/)
242
+ - Esplora API model: [github.com/Blockstream/esplora/blob/master/API.md](https://github.com/Blockstream/esplora/blob/master/API.md)
243
+
244
+ ## Contributing
245
+
246
+ Found a bug or want to help with a phase from the roadmap? Open an [issue](https://github.com/devdavidejesus/btc-toolkit/issues) or a PR. Every contribution must keep the core rules: stdlib only, tests mocked, claims verifiable on-chain.
247
+
248
+ ---
249
+
250
+ <div align="center">
251
+
252
+ Licensed under [MIT](LICENSE) · Built by [@devdavidejesus](https://github.com/devdavidejesus)
253
+
254
+ *"Don't Trust, Verify."*
255
+
256
+ </div>
@@ -0,0 +1,229 @@
1
+ <div align="center">
2
+
3
+ # ₿ btc-toolkit
4
+
5
+ **Bitcoin CLI toolkit — zero dependencies, no Bitcoin Core required.**
6
+
7
+ Query the Bitcoin network directly via the [Mempool.space](https://mempool.space) public API.
8
+
9
+ [![Tests](https://github.com/devdavidejesus/btc-toolkit/actions/workflows/tests.yml/badge.svg)](https://github.com/devdavidejesus/btc-toolkit/actions/workflows/tests.yml)
10
+ [![Version](https://img.shields.io/github/v/tag/devdavidejesus/btc-toolkit?label=version&color=F7931A)](https://github.com/devdavidejesus/btc-toolkit/tags)
11
+ [![Python](https://img.shields.io/badge/python-3.10%2B-3776AB?logo=python&logoColor=white)](https://github.com/devdavidejesus/btc-toolkit/blob/main/pyproject.toml)
12
+ [![Dependencies](https://img.shields.io/badge/dependencies-zero-success)](https://github.com/devdavidejesus/btc-toolkit/blob/main/pyproject.toml)
13
+ [![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)
14
+
15
+ </div>
16
+
17
+ ---
18
+
19
+ ## Commands
20
+
21
+ | Command | Description | Status |
22
+ |---|---|---|
23
+ | `btc-toolkit opreturn <txid>` | Decode OP_RETURN messages from a transaction | ✅ Phase 1 |
24
+ | `btc-toolkit balance <address>` | Confirmed + unconfirmed balance of any address | ✅ Phase 2 |
25
+ | `btc-toolkit fees` | Recommended fee rates + mempool backlog | ✅ Phase 3 |
26
+ | `btc-toolkit block <height\|hash>` | Block metadata by height, hash, or latest | ✅ Phase 4 |
27
+ | `btc-toolkit utxo <address>` | Unspent outputs of any address | ✅ Phase 5 |
28
+
29
+ ## Installation
30
+
31
+ **Requirements:** Python 3.10+
32
+
33
+ ```bash
34
+ git clone https://github.com/devdavidejesus/btc-toolkit.git
35
+ cd btc-toolkit
36
+ pip install -e .
37
+ ```
38
+
39
+ ## Usage
40
+
41
+ ### balance — check any address
42
+
43
+ ```bash
44
+ btc-toolkit balance 1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa
45
+ ```
46
+
47
+ Shows confirmed balance, unconfirmed (mempool) balance, and total — in BTC and satoshis. Supports all address types: Legacy (P2PKH), P2SH, SegWit (Bech32), and Taproot.
48
+
49
+ ```bash
50
+ # JSON output for scripting
51
+ btc-toolkit balance <address> --json
52
+
53
+ # Testnet
54
+ btc-toolkit balance <address> --network testnet
55
+ ```
56
+
57
+ BTC conversion uses integer arithmetic (no floats) — satoshi-exact, always.
58
+
59
+ ### fees — current rates and mempool backlog
60
+
61
+ ```bash
62
+ btc-toolkit fees
63
+ ```
64
+
65
+ Shows the five recommended fee tiers (sat/vB) — fastest, half hour, hour, economy, minimum — plus mempool backlog: pending tx count, size in vMB, and a rough estimate of blocks needed to clear it.
66
+
67
+ ```bash
68
+ # JSON output for scripting
69
+ btc-toolkit fees --json
70
+
71
+ # Testnet
72
+ btc-toolkit fees --network testnet
73
+ ```
74
+
75
+ ### block — inspect any block
76
+
77
+ ```bash
78
+ btc-toolkit block latest # chain tip
79
+ btc-toolkit block 0 # by height (genesis)
80
+ btc-toolkit block 000000000019d6689c085ae165831e934ff763ae46a2a6c172b3f1b60a8ce26f # by hash
81
+ ```
82
+
83
+ Shows height, hash, mined timestamp (UTC), tx count, size, weight, difficulty, nonce, and previous block hash.
84
+
85
+ ```bash
86
+ # JSON output for scripting
87
+ btc-toolkit block latest --json
88
+
89
+ # Testnet
90
+ btc-toolkit block latest --network testnet
91
+ ```
92
+
93
+ ### utxo — unspent outputs of any address
94
+
95
+ ```bash
96
+ btc-toolkit utxo bc1qar0srrr7xfkvy5l643lydnw9re59gtzzwf5mdq
97
+ ```
98
+
99
+ Lists every UTXO sorted by value (largest first), with txid:vout, value in BTC and sats, confirmation status, and block height. Shows aggregate count and total value.
100
+
101
+ > **Known limitation:** addresses with tens of thousands of UTXOs (e.g. Satoshi's genesis address, ~76k donation outputs) exceed the upstream electrs response limit and return HTTP 400. Use `balance` for aggregate stats on such addresses — discovered and verified in production.
102
+
103
+ ```bash
104
+ # Only confirmed UTXOs
105
+ btc-toolkit utxo <address> --confirmed-only
106
+
107
+ # Show more than 15 entries
108
+ btc-toolkit utxo <address> --limit 50
109
+
110
+ # JSON output (always includes all UTXOs)
111
+ btc-toolkit utxo <address> --json
112
+ ```
113
+
114
+ ### opreturn — decode embedded messages
115
+
116
+ ```bash
117
+ btc-toolkit opreturn f4ac7abcb689df30ec5e8d829733622f389ca91367c47b319bc582e653cd8cab
118
+ ```
119
+
120
+ ![OP_RETURN Reader demo](assets/demo.png)
121
+
122
+ ```bash
123
+ # JSON output
124
+ btc-toolkit opreturn <txid> --json
125
+
126
+ # Raw hex only
127
+ btc-toolkit opreturn <txid> --raw
128
+ ```
129
+
130
+ ### Transactions to Try
131
+
132
+ Real, verified OP_RETURN transactions on mainnet. Verify each one yourself on [mempool.space](https://mempool.space).
133
+
134
+ | TXID | Description |
135
+ |---|---|
136
+ | `f4ac7abcb689df30ec5e8d829733622f389ca91367c47b319bc582e653cd8cab` | "Craig Wright is a liar and a fraud" — 34 bytes ([verify on-chain](https://mempool.space/tx/f4ac7abcb689df30ec5e8d829733622f389ca91367c47b319bc582e653cd8cab)) |
137
+ | `2033435de7ce307341231e818ed937cd3a5e8597381fd83a7e5b0234f61b38d3` | "learnmeabitcoin" — 75-byte OP_RETURN with null-padded ASCII ([verify on-chain](https://mempool.space/tx/2033435de7ce307341231e818ed937cd3a5e8597381fd83a7e5b0234f61b38d3)) |
138
+
139
+ > **Note:** Satoshi's famous "Chancellor on brink of second bailout for banks" message is in the
140
+ > **coinbase scriptSig** of the genesis block — NOT in an OP_RETURN output. That's a common
141
+ > misconception. This tool reads OP_RETURN outputs only, which is the standard mechanism
142
+ > for embedding data in Bitcoin transactions (introduced as standard in Bitcoin Core v0.9.0, March 2014).
143
+
144
+ ## Architecture
145
+
146
+ ```
147
+ btc-toolkit/
148
+ ├── btc_toolkit/
149
+ │ ├── __init__.py # Package version
150
+ │ ├── __main__.py # python -m entry point
151
+ │ ├── cli.py # Unified CLI with subcommands
152
+ │ ├── api.py # Shared Mempool.space HTTP client
153
+ │ ├── colors.py # Shared terminal color helpers
154
+ │ ├── opreturn.py # Phase 1 — OP_RETURN decoder
155
+ │ ├── balance.py # Phase 2 — Address balance checker
156
+ │ ├── fees.py # Phase 3 — Fee estimator
157
+ │ ├── block.py # Phase 4 — Block info explorer
158
+ │ └── utxo.py # Phase 5 — UTXO set inspector
159
+ ├── tests/
160
+ │ ├── test_opreturn.py # 18 tests (mocked API + parser validation)
161
+ │ ├── test_balance.py # 18 tests (sats math + API response parsing)
162
+ │ ├── test_fees.py # 6 tests (rates + backlog parsing)
163
+ │ ├── test_block.py # 12 tests (ref detection + genesis data)
164
+ │ └── test_utxo.py # 8 tests (aggregates + filters)
165
+ ├── pyproject.toml
166
+ ├── LICENSE # MIT
167
+ └── README.md
168
+ ```
169
+
170
+ Every subcommand shares one HTTP client (`api.py`) — new phases add a module + a subcommand, nothing else.
171
+
172
+ Zero external dependencies — Python standard library only (`urllib`, `json`, `argparse`).
173
+
174
+ ## Testing
175
+
176
+ ```bash
177
+ python -m pytest tests/ -v
178
+ ```
179
+
180
+ 62 tests, all API calls mocked — the suite runs offline.
181
+
182
+ ![Tests passing](assets/tests.png)
183
+
184
+ ## How balance is computed
185
+
186
+ The Mempool.space `/address` endpoint returns `chain_stats` (confirmed) and `mempool_stats` (unconfirmed), each with `funded_txo_sum` and `spent_txo_sum` in satoshis.
187
+
188
+ ```
189
+ confirmed = chain_stats.funded_txo_sum - chain_stats.spent_txo_sum
190
+ unconfirmed = mempool_stats.funded_txo_sum - mempool_stats.spent_txo_sum
191
+ total = confirmed + unconfirmed
192
+ ```
193
+
194
+ This is the same model used by Esplora/Electrs. Don't trust this README — verify against `https://mempool.space/api/address/<address>` yourself.
195
+
196
+ ## Roadmap
197
+
198
+ - [x] **Phase 1** — OP_RETURN Reader
199
+ - [x] **Phase 2** — Address Balance Checker
200
+ - [x] **Phase 3** — Fee Estimator (mempool-based)
201
+ - [x] **Phase 4** — Block Info Explorer
202
+ - [x] **Phase 5** — UTXO Set Inspector
203
+
204
+ All five phases complete — one philosophy throughout: **zero dependencies, no Bitcoin Core, verify everything on-chain.**
205
+
206
+ ## Don't Trust, Verify
207
+
208
+ Every txid, address, hex value, and technical claim in this README can be independently verified:
209
+ - Transaction data: `https://mempool.space/api/tx/<txid>`
210
+ - Address data: `https://mempool.space/api/address/<address>`
211
+ - Fee data: `https://mempool.space/api/v1/fees/recommended`
212
+ - Block data: `https://mempool.space/api/block/<hash>`
213
+ - UTXO data: `https://mempool.space/api/address/<address>/utxo`
214
+ - OP_RETURN spec: [learnmeabitcoin.com/technical/script/return](https://learnmeabitcoin.com/technical/script/return/)
215
+ - Esplora API model: [github.com/Blockstream/esplora/blob/master/API.md](https://github.com/Blockstream/esplora/blob/master/API.md)
216
+
217
+ ## Contributing
218
+
219
+ Found a bug or want to help with a phase from the roadmap? Open an [issue](https://github.com/devdavidejesus/btc-toolkit/issues) or a PR. Every contribution must keep the core rules: stdlib only, tests mocked, claims verifiable on-chain.
220
+
221
+ ---
222
+
223
+ <div align="center">
224
+
225
+ Licensed under [MIT](LICENSE) · Built by [@devdavidejesus](https://github.com/devdavidejesus)
226
+
227
+ *"Don't Trust, Verify."*
228
+
229
+ </div>
@@ -0,0 +1,3 @@
1
+ """btc-toolkit — Bitcoin CLI tools. Zero dependencies, no Bitcoin Core required."""
2
+
3
+ __version__ = "1.0.0"
@@ -0,0 +1,6 @@
1
+ """Allow running as: python -m btc_toolkit <command> ..."""
2
+
3
+ import sys
4
+ from .cli import run
5
+
6
+ sys.exit(run())
@@ -0,0 +1,94 @@
1
+ """
2
+ Shared Mempool.space API client.
3
+
4
+ Centralizes all HTTP communication with the Mempool.space REST API.
5
+ Every subcommand (opreturn, balance, fees, block, utxo) uses this module
6
+ instead of duplicating connection logic.
7
+
8
+ No external dependencies — standard library only.
9
+ """
10
+
11
+ import json
12
+ import urllib.request
13
+ import urllib.error
14
+
15
+ from . import __version__
16
+
17
+ # Mempool.space API base URLs
18
+ MEMPOOL_API = "https://mempool.space/api"
19
+ MEMPOOL_TESTNET_API = "https://mempool.space/testnet/api"
20
+
21
+ SUPPORTED_NETWORKS = ("mainnet", "testnet")
22
+
23
+ _USER_AGENT = f"btc-toolkit/{__version__}"
24
+ _TIMEOUT = 15
25
+
26
+
27
+ class MempoolAPIError(Exception):
28
+ """Raised when the Mempool.space API returns an error."""
29
+
30
+
31
+ class NotFoundError(MempoolAPIError):
32
+ """Raised when a requested resource (tx, address, block) is not found."""
33
+
34
+
35
+ def get_api_base(network: str) -> str:
36
+ """Return the correct API base URL for the given network."""
37
+ if network not in SUPPORTED_NETWORKS:
38
+ raise ValueError(
39
+ f"Unsupported network: {network}. Use one of: {SUPPORTED_NETWORKS}"
40
+ )
41
+ if network == "testnet":
42
+ return MEMPOOL_TESTNET_API
43
+ return MEMPOOL_API
44
+
45
+
46
+ def get_json(path: str, network: str = "mainnet") -> dict | list:
47
+ """
48
+ GET a Mempool.space API endpoint and return parsed JSON.
49
+
50
+ Args:
51
+ path: API path beginning with '/', e.g. '/tx/<txid>' or '/address/<addr>'.
52
+ network: 'mainnet' or 'testnet'.
53
+
54
+ Returns:
55
+ Parsed JSON (dict or list).
56
+
57
+ Raises:
58
+ NotFoundError: On HTTP 404.
59
+ MempoolAPIError: On other HTTP or connection errors.
60
+ """
61
+ api_base = get_api_base(network)
62
+ url = f"{api_base}{path}"
63
+
64
+ try:
65
+ req = urllib.request.Request(url, headers={"User-Agent": _USER_AGENT})
66
+ with urllib.request.urlopen(req, timeout=_TIMEOUT) as resp:
67
+ return json.loads(resp.read().decode("utf-8"))
68
+ except urllib.error.HTTPError as e:
69
+ if e.code == 404:
70
+ raise NotFoundError(f"Not found: {path}") from e
71
+ raise MempoolAPIError(f"API error {e.code}: {e.reason}") from e
72
+ except urllib.error.URLError as e:
73
+ raise MempoolAPIError(f"Connection error: {e.reason}") from e
74
+
75
+
76
+ def get_text(path: str, network: str = "mainnet") -> str:
77
+ """
78
+ GET a Mempool.space API endpoint that returns plain text (not JSON).
79
+
80
+ Used for endpoints like /blocks/tip/height that return a bare number.
81
+ """
82
+ api_base = get_api_base(network)
83
+ url = f"{api_base}{path}"
84
+
85
+ try:
86
+ req = urllib.request.Request(url, headers={"User-Agent": _USER_AGENT})
87
+ with urllib.request.urlopen(req, timeout=_TIMEOUT) as resp:
88
+ return resp.read().decode("utf-8").strip()
89
+ except urllib.error.HTTPError as e:
90
+ if e.code == 404:
91
+ raise NotFoundError(f"Not found: {path}") from e
92
+ raise MempoolAPIError(f"API error {e.code}: {e.reason}") from e
93
+ except urllib.error.URLError as e:
94
+ raise MempoolAPIError(f"Connection error: {e.reason}") from e