bitcoinwatcher 2.1__tar.gz → 2.2__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.
Files changed (36) hide show
  1. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/PKG-INFO +1 -1
  2. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/address_listener/address_listener.py +4 -2
  3. bitcoinwatcher-2.2/bitcoin/tests/test_bitcoin_rpc.py +33 -0
  4. bitcoinwatcher-2.2/bitcoin/tx_extractors/abstract_extractor.py +11 -0
  5. bitcoinwatcher-2.2/bitcoin/tx_extractors/bitcoin_rpc.py +62 -0
  6. bitcoinwatcher-2.2/bitcoin/tx_extractors/default.py +29 -0
  7. bitcoinwatcher-2.1/bitcoin/utils/tx_address_data_extractor.py → bitcoinwatcher-2.2/bitcoin/tx_extractors/mempool.py +2 -34
  8. bitcoinwatcher-2.2/bitcoin/utils/__init__.py +0 -0
  9. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/utils/benchmark.py +8 -8
  10. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/utils/bitcoin_rpc.py +2 -4
  11. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoinwatcher.egg-info/PKG-INFO +1 -1
  12. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoinwatcher.egg-info/SOURCES.txt +6 -1
  13. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/pyproject.toml +1 -1
  14. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/LICENSE +0 -0
  15. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/README.md +0 -0
  16. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/__init__.py +0 -0
  17. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/address_listener/__init__.py +0 -0
  18. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/address_listener/simple_address_listener.py +0 -0
  19. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/models/__init__.py +0 -0
  20. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/models/address_tx_data.py +0 -0
  21. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/tests/__init__.py +0 -0
  22. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/tests/data/__init__.py +0 -0
  23. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/tests/data/transactions.py +0 -0
  24. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/tests/test_address_listener.py +0 -0
  25. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/tests/test_bitcoin_utils.py +0 -0
  26. {bitcoinwatcher-2.1/bitcoin/tx_listener → bitcoinwatcher-2.2/bitcoin/tx_extractors}/__init__.py +0 -0
  27. {bitcoinwatcher-2.1/bitcoin/utils → bitcoinwatcher-2.2/bitcoin/tx_listener}/__init__.py +0 -0
  28. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/tx_listener/abstract_tx_listener.py +0 -0
  29. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/tx_listener/zmq_listener.py +0 -0
  30. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/utils/bitcoin_utils.py +0 -0
  31. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/utils/constants.py +0 -0
  32. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoin/utils/inscription_utils.py +0 -0
  33. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoinwatcher.egg-info/dependency_links.txt +0 -0
  34. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoinwatcher.egg-info/requires.txt +0 -0
  35. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/bitcoinwatcher.egg-info/top_level.txt +0 -0
  36. {bitcoinwatcher-2.1 → bitcoinwatcher-2.2}/setup.cfg +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bitcoinwatcher
3
- Version: 2.1
3
+ Version: 2.2
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
@@ -5,9 +5,11 @@ from bitcoinlib.transactions import Transaction
5
5
  from ordipool.ordipool.mempoolio import Mempool
6
6
 
7
7
  from bitcoin.models.address_tx_data import AddressTxData
8
+ from bitcoin.tx_extractors.bitcoin_rpc import BitcoinRPCAddressDataExtractor
9
+ from bitcoin.tx_extractors.default import DefaultTxAddressDataExtractor
10
+ from bitcoin.tx_extractors.mempool import MempoolTxAddressDataExtractor
8
11
  from bitcoin.tx_listener.abstract_tx_listener import AbstractTxListener
9
12
  from bitcoin.utils.constants import default_host
10
- from bitcoin.utils.tx_address_data_extractor import DefaultTxAddressDataExtractor, MempoolTxAddressDataExtractor
11
13
 
12
14
 
13
15
  class AbstractAddressListener(AbstractTxListener, ABC):
@@ -16,7 +18,7 @@ class AbstractAddressListener(AbstractTxListener, ABC):
16
18
  base_url = f"http://{host}:3006/api"
17
19
  mempool = Mempool(base_url=base_url)
18
20
  default_tx_extractor = DefaultTxAddressDataExtractor()
19
- mempool_tx_extractor = MempoolTxAddressDataExtractor(mempool)
21
+ mempool_tx_extractor = BitcoinRPCAddressDataExtractor()
20
22
 
21
23
  def __init__(self, addresses_to_listen: {str}):
22
24
  self.addresses_to_listen = addresses_to_listen
@@ -0,0 +1,33 @@
1
+ from unittest import TestCase, skip
2
+
3
+ from bitcoinlib.transactions import Transaction
4
+
5
+ from bitcoin.tx_extractors.bitcoin_rpc import BitcoinRPCAddressDataExtractor
6
+
7
+
8
+ class TestBitcoinRPCAddressDataExtractor(TestCase):
9
+ @skip("This test is being ignored.")
10
+ def test_extract(self):
11
+ hex = "02000000000101f2a69b3ac92464aa2783b27b4e680339aaf568a2f2dfb57b35514ead52a68c200000000000fdffffff0188a6a30000000000160014e19cffc3dac9b6db7dbcbfb33b0dbdbe3bb1282b02473044022079d28834e1b49fe68d49abc61ed9e42cb3975e90e20224c9b81eba7836c9d1d302205e42205de0380a16aae83a9d73f8950e7cbbc051d345d1a2d281680831b2a0aa0121025165993582dc7d93ac11fd5bb3eabd721acdddf94c94f58008f157c3b7bbaa6400000000"
12
+ tx = Transaction.parse_hex(hex, strict=False)
13
+ tx_id = tx.txid
14
+ print(tx_id)
15
+ for intput in tx.inputs:
16
+ prev_tx = intput.prev_txid;
17
+ prev_tx_id_hex = prev_tx.hex();
18
+ print(prev_tx_id_hex);
19
+ print(intput.output_n_int);
20
+ bitcoin_rpc_address_data_extractor = BitcoinRPCAddressDataExtractor()
21
+ address_tx_data = bitcoin_rpc_address_data_extractor.extract(tx)
22
+ self.assertEqual(len(address_tx_data), 2)
23
+
24
+ @skip("This test is being ignored.")
25
+ def test_extract_marketplace_tx(self):
26
+ hex = "0200000000010615f726f9506e458b6a9a3871bbbc7162ce7a360ee2adb0b4e153cdd4792329eb0f000000171600140d2d83b034e88a7d69bfff06a23745ed402d8ec2ffffffff943175fe63f613886b4cae9dc62e781da91bb00c29b327a38e152c84f261502705000000171600140d2d83b034e88a7d69bfff06a23745ed402d8ec2ffffffff15f726f9506e458b6a9a3871bbbc7162ce7a360ee2adb0b4e153cdd4792329eb10000000171600140d2d83b034e88a7d69bfff06a23745ed402d8ec2ffffffff837fe5d79eed2be634092c72f6602ecc9e57699f1d66eb33375b0152284efee90100000000ffffffff094a2725d5e5857aaf7f210b58fa35bea92a4070d007c880c1ae79bde4e713780600000000ffffffff0123fddb864eab59349587b02ae169eeb5b46fe3025f1e564268616527b0578708000000171600140d2d83b034e88a7d69bfff06a23745ed402d8ec2ffffffff0a080700000000000017a9141e281d4ef25d46790dc2d8cd5954a1cb568dd5cb872202000000000000225120f182ae8cd3e98896ddc19585dff7356c888a8b71f6b5a15f68a57f54c85448ab2202000000000000225120f182ae8cd3e98896ddc19585dff7356c888a8b71f6b5a15f68a57f54c85448ab1239010000000000225120b2a8278e2bac9a1318ce327a4b5c302e2b6a6b306c15dafdebc5a9e8cd82da8212390100000000002251205176221bf37b5c1ae2ba8a907af749e710a87633849f2b9f3234e6862f3021f4a00f000000000000160014c015c65276d5f38d599d445c4cb03aa7aa0dc365580200000000000017a9141e281d4ef25d46790dc2d8cd5954a1cb568dd5cb87580200000000000017a9141e281d4ef25d46790dc2d8cd5954a1cb568dd5cb87580200000000000017a9141e281d4ef25d46790dc2d8cd5954a1cb568dd5cb878d6700000000000017a9141e281d4ef25d46790dc2d8cd5954a1cb568dd5cb8702483045022100ad8ee8d9431bbdca0e21af30fa6d9a29f162e868ea4411cc10c18b99a7959d12022014d49a39f19e35800b1bbfaa6e825789b1fab16bafbee6655f273bd88c07a21f0121028492755e1e8131ddb226c8957f11d64bd18c77d91297ade0ec11f7a74a22b88d0247304402202388e40a1d6a588d2679efc433ec696dc956aa723902f72105f60c25c6300f850220505e6b55920a9125da4af76d3c13fac91572d5da1c24c0cefe10e7fa8d46166c0121028492755e1e8131ddb226c8957f11d64bd18c77d91297ade0ec11f7a74a22b88d02483045022100fb1b18e09ceccfc1d1164d7c82be56574cf8f0af1ea2d2eda4288ece65c13aaa022020de635ae416db1ae98ad7c9ae5c794472666d3ea3b7c26c97244de1a48359120121028492755e1e8131ddb226c8957f11d64bd18c77d91297ade0ec11f7a74a22b88d014196c68e1dc21ce99a86a3652050dc0253ed12835998c57ef76bb611bf5e466f29075b66efbc304e357167d1c2931b46a05d99fd41752b775386d668ddd530cafd830141547edc099b1e1fb79fe343193864ab43694d89468421b4a69e595f3346faaa3e2c5d1c0a5c39754cc43ddb9b7eee7b59b4ffb06c584abe67947980117a35a2328302483045022100d8b5cf136dfaf3b58a6300da6f682b6623b997cc848179a272fec8c3de57efc502203defeb5d711112938a98a25238399fe3bd704a1d6b4c84846a5b5e7a9bd1fdee0121028492755e1e8131ddb226c8957f11d64bd18c77d91297ade0ec11f7a74a22b88d00000000"
27
+ tx = Transaction.parse_hex(hex, strict=False)
28
+ tx_id = tx.txid;
29
+ print(tx_id);
30
+ bitcoinrpc_address_data_extractor = BitcoinRPCAddressDataExtractor()
31
+ address_tx_data = bitcoinrpc_address_data_extractor.extract(tx)
32
+ self.assertEqual(len(address_tx_data), 16)
33
+
@@ -0,0 +1,11 @@
1
+ from abc import ABC, abstractmethod
2
+
3
+ from bitcoinlib.transactions import Transaction
4
+
5
+ from bitcoin.address_listener.address_listener import AddressTxData
6
+
7
+
8
+ class AbstractTxAddressDataExtractor(ABC):
9
+ @abstractmethod
10
+ def extract(self, tx: Transaction) -> [AddressTxData]:
11
+ pass
@@ -0,0 +1,62 @@
1
+ import os
2
+ from multiprocessing.pool import ThreadPool
3
+
4
+ from bitcoinlib.transactions import Transaction
5
+
6
+ from bitcoin.address_listener.address_listener import AddressTxData
7
+ from bitcoin.models.address_tx_data import AddressTxType
8
+ from bitcoin.utils.bitcoin_rpc import BitcoinRPC
9
+ from bitcoin.tx_extractors.abstract_extractor import AbstractTxAddressDataExtractor
10
+
11
+
12
+ class BitcoinRPCAddressDataExtractor(AbstractTxAddressDataExtractor):
13
+ bitcoinrpc: BitcoinRPC
14
+ thread_pool = ThreadPool(processes=os.environ.get("THREAD_POOL_SIZE", 5))
15
+
16
+ def __init__(self):
17
+ self.bitcoinrpc = BitcoinRPC()
18
+
19
+ def fetch_all_inputs(self, inputs):
20
+ rpc_calls = [["getrawtransaction", input.prev_txid.hex(), True] for input in inputs]
21
+ data = self.bitcoinrpc.rpc_connection.batch_(rpc_calls)
22
+ list_of_vouts = []
23
+ for input in inputs:
24
+ vout = data.pop(0)["vout"][input.output_n_int]
25
+ list_of_vouts.append(vout)
26
+ return list_of_vouts
27
+
28
+ def get_address_tx_from_inputdata(self, tx_id, tx_status, input_data):
29
+ address = input_data["scriptPubKey"]["address"]
30
+ amount = int(input_data.get("value", 0).real * 100000000)
31
+ return AddressTxData(tx_id=tx_id, tx_status=tx_status, address=address, _amount=amount,
32
+ type=AddressTxType.INPUT)
33
+
34
+ def extract(self, tx: Transaction) -> [AddressTxData]:
35
+ outputs = tx.outputs
36
+ tx_id = tx.txid
37
+ address_tx_data = []
38
+ inputs = tx.inputs
39
+ # bulk get all the inputs from BitcoinRPC using thread pool
40
+ inputs_data = self.fetch_all_inputs(inputs)
41
+ tx_status = tx.status
42
+ for input in inputs:
43
+ address = input.address
44
+ amount = 0
45
+ if len(inputs_data) > 0:
46
+ input_data = inputs_data.pop(0)
47
+ input_tx_data = self.get_address_tx_from_inputdata(tx_id, tx_status, input_data)
48
+ address_tx_data.append(input_tx_data)
49
+ else:
50
+ address_tx_data.append(AddressTxData(tx_status=tx_status,
51
+ address=address,
52
+ type=AddressTxType.INPUT,
53
+ _amount=amount,
54
+ tx_id=tx.txid))
55
+ for output in outputs:
56
+ amount = output.value
57
+ address_tx_data.append(AddressTxData(tx_status=tx_status,
58
+ address=output.address,
59
+ _amount=amount,
60
+ type=AddressTxType.OUTPUT,
61
+ tx_id=tx.txid))
62
+ return address_tx_data
@@ -0,0 +1,29 @@
1
+ from bitcoinlib.transactions import Transaction
2
+
3
+ from bitcoin.address_listener.address_listener import AddressTxData
4
+ from bitcoin.models.address_tx_data import AddressTxType
5
+ from bitcoin.tx_extractors.abstract_extractor import AbstractTxAddressDataExtractor
6
+
7
+
8
+ class DefaultTxAddressDataExtractor(AbstractTxAddressDataExtractor):
9
+ def extract(self, tx: Transaction) -> [AddressTxData]:
10
+ outputs = tx.outputs
11
+ address_tx_data = []
12
+ inputs = tx.inputs
13
+ tx_status = tx.status
14
+ for input in inputs:
15
+ address = input.address
16
+ amount = 0
17
+ address_tx_data.append(AddressTxData(tx_status=tx_status,
18
+ address=address,
19
+ type=AddressTxType.INPUT,
20
+ _amount=amount,
21
+ tx_id=tx.txid))
22
+ for output in outputs:
23
+ amount = output.value
24
+ address_tx_data.append(AddressTxData(tx_status=tx_status,
25
+ address=output.address,
26
+ _amount=amount,
27
+ type=AddressTxType.OUTPUT,
28
+ tx_id=tx.txid))
29
+ return address_tx_data
@@ -1,18 +1,10 @@
1
- from abc import ABC, abstractmethod
2
-
3
-
4
1
  from bitcoinlib.transactions import Transaction
5
2
  from ordipool.ordipool.mempoolio import Mempool
6
3
 
7
4
  from bitcoin.address_listener.address_listener import AddressTxData
8
5
  from bitcoin.models.address_tx_data import AddressTxType, TransactionStatus
9
- from bitcoin.utils.bitcoin_utils import is_reveal_tx, count_reveal_inputs
10
-
11
-
12
- class AbstractTxAddressDataExtractor(ABC):
13
- @abstractmethod
14
- def extract(self, tx: Transaction) -> [AddressTxData]:
15
- pass
6
+ from bitcoin.utils.bitcoin_utils import is_reveal_tx
7
+ from bitcoin.tx_extractors.abstract_extractor import AbstractTxAddressDataExtractor
16
8
 
17
9
 
18
10
  class MempoolTxAddressDataExtractor(AbstractTxAddressDataExtractor):
@@ -50,27 +42,3 @@ class MempoolTxAddressDataExtractor(AbstractTxAddressDataExtractor):
50
42
  tx_id=tx_id))
51
43
 
52
44
  return address_tx_data
53
-
54
-
55
- class DefaultTxAddressDataExtractor(AbstractTxAddressDataExtractor):
56
- def extract(self, tx: Transaction) -> [AddressTxData]:
57
- outputs = tx.outputs
58
- address_tx_data = []
59
- inputs = tx.inputs
60
- tx_status = tx.status
61
- for input in inputs:
62
- address = input.address
63
- amount = 0
64
- address_tx_data.append(AddressTxData(tx_status=tx_status,
65
- address=address,
66
- type=AddressTxType.INPUT,
67
- _amount=amount,
68
- tx_id=tx.txid))
69
- for output in outputs:
70
- amount = output.value
71
- address_tx_data.append(AddressTxData(tx_status=tx_status,
72
- address=output.address,
73
- _amount=amount,
74
- type=AddressTxType.OUTPUT,
75
- tx_id=tx.txid))
76
- return address_tx_data
File without changes
@@ -17,17 +17,17 @@ if __name__ == '__main__':
17
17
 
18
18
  txid = 'a6293e898b056fbea0329d071b1b237e4449ff464cdbc7a9ed8a770b97aafd4c'
19
19
  times = 1000
20
- start = time.time()
21
- print("mempool starting")
22
- for i in range(times):
23
- print(i)
24
- mempool.get_transaction(txid)
25
- end = time.time()
26
- print(f"mempool took: {end - start}")
20
+ # start = time.time()
21
+ # print("mempool starting")
22
+ # for i in range(times):
23
+ # print(i)
24
+ # mempool.get_transaction(txid)
25
+ # end = time.time()
26
+ # print(f"mempool took: {end - start}")
27
27
 
28
28
  start = time.time()
29
29
  for i in range(times):
30
- bitcoinrpc.get_transaction(txid)
30
+ tx = bitcoinrpc.get_transaction(txid)
31
31
  end = time.time()
32
32
  print(f"bitcoinrpc took: {end - start}")
33
33
 
@@ -10,11 +10,9 @@ class BitcoinRPC:
10
10
  rpc_password = os.environ.get("RPC_PASSWORD")
11
11
  rpc_host = os.environ.get("RPC_HOST", default_host)
12
12
  rpc_port = os.environ.get("RPC_PORT", 8332)
13
- rpc_connection: AuthServiceProxy
14
13
 
15
14
  def __init__(self):
16
15
  rpc_string = f"http://{self.rpc_user}:{self.rpc_password}@{self.rpc_host}:{self.rpc_port}"
17
- print("rpc_string: ", rpc_string)
18
16
  self.rpc_connection = AuthServiceProxy(rpc_string)
19
17
 
20
18
  def get_transaction(self, txid: str) -> dict:
@@ -23,9 +21,9 @@ class BitcoinRPC:
23
21
 
24
22
  if __name__ == '__main__':
25
23
  rpc = BitcoinRPC()
26
- txid = 'a6293e898b056fbea0329d071b1b237e4449ff464cdbc7a9ed8a770b97aafd4c'
24
+ txid = '8dc035d6816cf61074d12148777b28d28aa2f76b0f45ceafd310a85b1518aab8'
27
25
  try:
28
26
  transaction = rpc.get_transaction(txid)
29
27
  print(transaction)
30
28
  except JSONRPCException as e:
31
- print(f"An error occurred: {e}")
29
+ print(f"An error occurred: {e}")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: bitcoinwatcher
3
- Version: 2.1
3
+ Version: 2.2
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
@@ -9,9 +9,15 @@ bitcoin/models/__init__.py
9
9
  bitcoin/models/address_tx_data.py
10
10
  bitcoin/tests/__init__.py
11
11
  bitcoin/tests/test_address_listener.py
12
+ bitcoin/tests/test_bitcoin_rpc.py
12
13
  bitcoin/tests/test_bitcoin_utils.py
13
14
  bitcoin/tests/data/__init__.py
14
15
  bitcoin/tests/data/transactions.py
16
+ bitcoin/tx_extractors/__init__.py
17
+ bitcoin/tx_extractors/abstract_extractor.py
18
+ bitcoin/tx_extractors/bitcoin_rpc.py
19
+ bitcoin/tx_extractors/default.py
20
+ bitcoin/tx_extractors/mempool.py
15
21
  bitcoin/tx_listener/__init__.py
16
22
  bitcoin/tx_listener/abstract_tx_listener.py
17
23
  bitcoin/tx_listener/zmq_listener.py
@@ -21,7 +27,6 @@ bitcoin/utils/bitcoin_rpc.py
21
27
  bitcoin/utils/bitcoin_utils.py
22
28
  bitcoin/utils/constants.py
23
29
  bitcoin/utils/inscription_utils.py
24
- bitcoin/utils/tx_address_data_extractor.py
25
30
  bitcoinwatcher.egg-info/PKG-INFO
26
31
  bitcoinwatcher.egg-info/SOURCES.txt
27
32
  bitcoinwatcher.egg-info/dependency_links.txt
@@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta"
5
5
 
6
6
  [project]
7
7
  name = "bitcoinwatcher"
8
- version = "2.1"
8
+ version = "2.2"
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"}]
File without changes
File without changes
File without changes