bitcoinwatcher 2.6__tar.gz → 2.7__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.
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/PKG-INFO +2 -1
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/address_listener/address_listener.py +2 -1
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/address_listener/simple_address_listener.py +2 -2
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_extractors/bitcoin_rpc.py +4 -2
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_extractors/default.py +2 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_listener/zmq_listener.py +1 -1
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/utils/context_aware_logging.py +19 -7
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoinwatcher.egg-info/PKG-INFO +2 -1
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoinwatcher.egg-info/requires.txt +1 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/pyproject.toml +3 -2
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/LICENSE +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/README.md +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/address_listener/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/models/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/models/address_tx_data.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tests/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tests/data/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tests/data/transactions.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tests/test_address_listener.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tests/test_bitcoin_rpc.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tests/test_bitcoin_utils.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_extractors/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_extractors/abstract_extractor.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_extractors/mempool.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_listener/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/tx_listener/abstract_tx_listener.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/utils/__init__.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/utils/benchmark.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/utils/bitcoin_rpc.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/utils/bitcoin_utils.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/utils/constants.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/utils/inscription_utils.py +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoinwatcher.egg-info/SOURCES.txt +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoinwatcher.egg-info/dependency_links.txt +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoinwatcher.egg-info/top_level.txt +0 -0
- {bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: bitcoinwatcher
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.7
|
4
4
|
Summary: bitcoinwatcher is a Python library that implements a ZMQ subscriber and provides abstractions to build custom address watchers. This library is designed to make it easy for developers to monitor Bitcoin addresses and react to changes in their state.
|
5
5
|
Author: twosatsmaxi
|
6
6
|
License: Apache License
|
@@ -229,6 +229,7 @@ Requires-Dist: ordipool==1.2.0
|
|
229
229
|
Requires-Dist: pyzmq==25.1.2
|
230
230
|
Requires-Dist: python-bitcoinrpc==1.0
|
231
231
|
Requires-Dist: pytz~=2024.2
|
232
|
+
Requires-Dist: colorlog~=6.9.0
|
232
233
|
|
233
234
|
# bitcoinwatcher
|
234
235
|
|
@@ -37,6 +37,7 @@ class AbstractAddressListener(AbstractTxListener, ABC):
|
|
37
37
|
# get all address in the inputs and outputs along with the amount
|
38
38
|
if tx.coinbase:
|
39
39
|
return
|
40
|
+
logger.debug(f"Extracting default tx data")
|
40
41
|
address_tx_data = self.default_tx_extractor.extract(tx)
|
41
42
|
# filter the address we are interested in
|
42
43
|
addresses_for_events = self.filter_address_tx_data(address_tx_data)
|
@@ -47,7 +48,7 @@ class AbstractAddressListener(AbstractTxListener, ABC):
|
|
47
48
|
logger.info(f"Extracting rpc tx data")
|
48
49
|
address_tx_data = self.rpc_tx_extractor.extract(tx)
|
49
50
|
except Exception as e:
|
50
|
-
logger.error(f"Error in getting rpc tx data, taking defaults",
|
51
|
+
logger.error(f"Error in getting rpc tx data, taking defaults", exc_info=True)
|
51
52
|
address_tx_data = address_tx_data
|
52
53
|
|
53
54
|
for address in addresses_for_events:
|
{bitcoinwatcher-2.6 → bitcoinwatcher-2.7}/bitcoin/address_listener/simple_address_listener.py
RENAMED
@@ -12,7 +12,7 @@ class SimpleAddressListener(AbstractAddressListener):
|
|
12
12
|
address_tx_data))
|
13
13
|
total_amount_in_input = sum(map(lambda x: x.amount_in_btc(), all_input))
|
14
14
|
# scale ito 4 decimal places
|
15
|
-
print("Transaction status: ", address_tx_data[0].
|
15
|
+
print("Transaction status: ", address_tx_data[0].is_confirmed)
|
16
16
|
total_amount_in_output = round(total_amount_in_output, self.DECIMAL_SCALE)
|
17
17
|
print(f"Address {subscribed_address} received {total_amount_in_output} BTC in tx {address_tx_data[0].tx_id}")
|
18
18
|
print(f"Address {subscribed_address} spent {total_amount_in_input} BTC in tx {address_tx_data[0].tx_id}")
|
@@ -23,7 +23,7 @@ class SimpleAddressListener(AbstractAddressListener):
|
|
23
23
|
|
24
24
|
|
25
25
|
if __name__ == '__main__':
|
26
|
-
address = ["bc1qcq2uv5nk6hec6kvag3wyevp6574qmsm9scjxc2"]
|
26
|
+
address = ["bc1qp8j9sx6609h7llqufurxjgrwsqwt020tqzn0gs", "bc1qcq2uv5nk6hec6kvag3wyevp6574qmsm9scjxc2"]
|
27
27
|
address_watcher = SimpleAddressListener(address)
|
28
28
|
zmq_listener = ZMQTXListener(address_watcher)
|
29
29
|
zmq_listener.start()
|
@@ -7,7 +7,7 @@ from bitcoin.address_listener.address_listener import AddressTxData
|
|
7
7
|
from bitcoin.models.address_tx_data import AddressTxType
|
8
8
|
from bitcoin.utils.bitcoin_rpc import BitcoinRPC
|
9
9
|
from bitcoin.tx_extractors.abstract_extractor import AbstractTxAddressDataExtractor
|
10
|
-
from bitcoin.utils.context_aware_logging import logger
|
10
|
+
from bitcoin.utils.context_aware_logging import logger, ctx_tx_status
|
11
11
|
|
12
12
|
|
13
13
|
class BitcoinRPCAddressDataExtractor(AbstractTxAddressDataExtractor):
|
@@ -33,6 +33,7 @@ class BitcoinRPCAddressDataExtractor(AbstractTxAddressDataExtractor):
|
|
33
33
|
type=AddressTxType.INPUT)
|
34
34
|
|
35
35
|
def extract(self, tx: Transaction) -> [AddressTxData]:
|
36
|
+
logger.info("Extracting rpc tx data")
|
36
37
|
outputs = tx.outputs
|
37
38
|
tx_id = tx.txid
|
38
39
|
address_tx_data = []
|
@@ -40,7 +41,8 @@ class BitcoinRPCAddressDataExtractor(AbstractTxAddressDataExtractor):
|
|
40
41
|
# bulk get all the inputs from BitcoinRPC using thread pool
|
41
42
|
inputs_data = self.fetch_all_inputs(inputs)
|
42
43
|
is_confirmed = self.bitcoinrpc.is_confirmed(tx_id)
|
43
|
-
|
44
|
+
ctx_tx_status.set(is_confirmed)
|
45
|
+
logger.info("Transaction is_confirmed: %s", is_confirmed)
|
44
46
|
for input in inputs:
|
45
47
|
address = input.address
|
46
48
|
amount = 0
|
@@ -3,6 +3,7 @@ from bitcoinlib.transactions import Transaction
|
|
3
3
|
from bitcoin.address_listener.address_listener import AddressTxData
|
4
4
|
from bitcoin.models.address_tx_data import AddressTxType
|
5
5
|
from bitcoin.tx_extractors.abstract_extractor import AbstractTxAddressDataExtractor
|
6
|
+
from bitcoin.utils.context_aware_logging import ctx_tx_status
|
6
7
|
|
7
8
|
|
8
9
|
class DefaultTxAddressDataExtractor(AbstractTxAddressDataExtractor):
|
@@ -11,6 +12,7 @@ class DefaultTxAddressDataExtractor(AbstractTxAddressDataExtractor):
|
|
11
12
|
address_tx_data = []
|
12
13
|
inputs = tx.inputs
|
13
14
|
is_confirmed = tx.status == "confirmed"
|
15
|
+
ctx_tx_status.set(is_confirmed)
|
14
16
|
for input in inputs:
|
15
17
|
address = input.address
|
16
18
|
amount = 0
|
@@ -1,6 +1,7 @@
|
|
1
1
|
import logging
|
2
2
|
from contextvars import ContextVar
|
3
3
|
from datetime import datetime
|
4
|
+
import colorlog
|
4
5
|
|
5
6
|
import pytz
|
6
7
|
|
@@ -8,9 +9,9 @@ logger = logging.getLogger(__name__)
|
|
8
9
|
root = logging.getLogger()
|
9
10
|
root.setLevel(logging.INFO)
|
10
11
|
|
11
|
-
class TimezoneFormatter(
|
12
|
-
def __init__(self, fmt=None, datefmt=None, tz=None):
|
13
|
-
super().__init__(fmt, datefmt)
|
12
|
+
class TimezoneFormatter(colorlog.ColoredFormatter):
|
13
|
+
def __init__(self, fmt=None, datefmt=None, tz=None, log_colors=None):
|
14
|
+
super().__init__(fmt, datefmt, log_colors=log_colors)
|
14
15
|
self.tz = tz
|
15
16
|
|
16
17
|
def formatTime(self, record, datefmt=None):
|
@@ -19,19 +20,29 @@ class TimezoneFormatter(logging.Formatter):
|
|
19
20
|
s = dt.strftime(datefmt)
|
20
21
|
else:
|
21
22
|
s = dt.isoformat()
|
22
|
-
return s
|
23
|
-
|
23
|
+
return f"\033[94m{s}\033[0m" # Adding blue color to the date
|
24
24
|
|
25
25
|
formatter = TimezoneFormatter(
|
26
|
-
' %(asctime)s %(
|
26
|
+
' %(asctime)s %(log_color)s%(levelname)s txid=%(tx_id)s tx_status=%(tx_status)s [%(module)s:%(lineno)d] %(message)s',
|
27
27
|
datefmt='%Y-%m-%d %H:%M:%S',
|
28
|
-
tz=pytz.timezone('Asia/Kolkata')
|
28
|
+
tz=pytz.timezone('Asia/Kolkata'),
|
29
|
+
log_colors={
|
30
|
+
'DEBUG': 'cyan',
|
31
|
+
'INFO': 'green',
|
32
|
+
'WARNING': 'yellow',
|
33
|
+
'ERROR': 'red',
|
34
|
+
'CRITICAL': 'bold_red',
|
35
|
+
}
|
29
36
|
)
|
30
37
|
|
31
38
|
|
32
39
|
ctx_tx = ContextVar('tx_id', default='')
|
33
40
|
ctx_tx_status = ContextVar('tx_status', default='')
|
34
41
|
|
42
|
+
class ExcludeModuleFilter(logging.Filter):
|
43
|
+
def filter(self, record):
|
44
|
+
return not (record.name.startswith('bitcoinlib.transactions') or record.name.startswith('bitcoinlib.scripts'))
|
45
|
+
|
35
46
|
class TXContextFilter(logging.Filter):
|
36
47
|
|
37
48
|
def __init__(self):
|
@@ -48,6 +59,7 @@ ch = logging.StreamHandler()
|
|
48
59
|
f = TXContextFilter()
|
49
60
|
ch.setFormatter(formatter)
|
50
61
|
ch.addFilter(f)
|
62
|
+
ch.addFilter(ExcludeModuleFilter())
|
51
63
|
root.addHandler(ch)
|
52
64
|
|
53
65
|
def get_logger(name):
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: bitcoinwatcher
|
3
|
-
Version: 2.
|
3
|
+
Version: 2.7
|
4
4
|
Summary: bitcoinwatcher is a Python library that implements a ZMQ subscriber and provides abstractions to build custom address watchers. This library is designed to make it easy for developers to monitor Bitcoin addresses and react to changes in their state.
|
5
5
|
Author: twosatsmaxi
|
6
6
|
License: Apache License
|
@@ -229,6 +229,7 @@ Requires-Dist: ordipool==1.2.0
|
|
229
229
|
Requires-Dist: pyzmq==25.1.2
|
230
230
|
Requires-Dist: python-bitcoinrpc==1.0
|
231
231
|
Requires-Dist: pytz~=2024.2
|
232
|
+
Requires-Dist: colorlog~=6.9.0
|
232
233
|
|
233
234
|
# bitcoinwatcher
|
234
235
|
|
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
|
|
5
5
|
|
6
6
|
[project]
|
7
7
|
name = "bitcoinwatcher"
|
8
|
-
version = "2.
|
8
|
+
version = "2.7"
|
9
9
|
description = "bitcoinwatcher is a Python library that implements a ZMQ subscriber and provides abstractions to build custom address watchers. This library is designed to make it easy for developers to monitor Bitcoin addresses and react to changes in their state."
|
10
10
|
readme = "README.md"
|
11
11
|
authors = [{name = "twosatsmaxi"}]
|
@@ -34,7 +34,8 @@ dependencies = [
|
|
34
34
|
"ordipool==1.2.0",
|
35
35
|
"pyzmq==25.1.2",
|
36
36
|
"python-bitcoinrpc==1.0",
|
37
|
-
"pytz~=2024.2"
|
37
|
+
"pytz~=2024.2",
|
38
|
+
"colorlog~=6.9.0"
|
38
39
|
]
|
39
40
|
requires-python = ">=3.10"
|
40
41
|
[project.urls]
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|