bitcoinwatcher 2.1__py3-none-any.whl → 2.3__py3-none-any.whl

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.
@@ -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
+
File without changes
@@ -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
@@ -24,8 +24,11 @@ class ZMQTXListener:
24
24
  self.socket.setsockopt_string(zmq.SUBSCRIBE, "rawtx")
25
25
  while True:
26
26
  topic, body, seq = self.socket.recv_multipart()
27
- tx = Transaction.parse(body, strict=False)
28
- self.tx_listener.on_tx(tx)
27
+ try:
28
+ tx = Transaction.parse(body, strict=False)
29
+ self.tx_listener.on_tx(tx)
30
+ except Exception as e:
31
+ print(f"Error in parsing tx: {e}")
29
32
 
30
33
  def stop(self):
31
34
  self.socket.close()
@@ -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.3
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
@@ -1,26 +1,31 @@
1
1
  bitcoin/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  bitcoin/address_listener/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- bitcoin/address_listener/address_listener.py,sha256=K8SqR9oAJJJ1XrSGDbEDAamGyPB659xaPNlwtB53ed4,2252
3
+ bitcoin/address_listener/address_listener.py,sha256=32gDEYpYTv53nD0TKLYyrIzHpImYBzzT3XdCoGUD1fI,2354
4
4
  bitcoin/address_listener/simple_address_listener.py,sha256=WG8eTrd3AdkrIs1TAGRsXe_erAtE_Ep8hidZDksGk8g,1625
5
5
  bitcoin/models/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  bitcoin/models/address_tx_data.py,sha256=0zIleuEHern42zk1Pp7IteR5jQqVdAM1l4Gvy6YzGe0,754
7
7
  bitcoin/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
8
  bitcoin/tests/test_address_listener.py,sha256=USK3BMGnRsTBmCXcbnC9WkX6kF-W_sHt7RKARv39IDg,3125
9
+ bitcoin/tests/test_bitcoin_rpc.py,sha256=Xt9Mh71YQqE_gskgLMfPLs0J0YcCT7z5UimT42LOris,4137
9
10
  bitcoin/tests/test_bitcoin_utils.py,sha256=nc5HhCNQ3kQIxesd_l8zFruE0l2OiEH0j2ukjAHtRX8,1426
10
11
  bitcoin/tests/data/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
11
12
  bitcoin/tests/data/transactions.py,sha256=qIX9seGYguQ1lvLOCF8oe3NQhMJZP0SsBmz1iFbszhg,396279
13
+ bitcoin/tx_extractors/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
+ bitcoin/tx_extractors/abstract_extractor.py,sha256=YLnuqc3jva15NpOX8xV4oB5PEXc6rXbG8Lx0cBXW66s,291
15
+ bitcoin/tx_extractors/bitcoin_rpc.py,sha256=PFyX5DfJspj9AM3KCVJG91dYxTtb73PW10JKzHDljww,2800
16
+ bitcoin/tx_extractors/default.py,sha256=ZW9bJjq4-gvp-jJzNTrTFRRTReb4mOO0OmpTnDenhBQ,1377
17
+ bitcoin/tx_extractors/mempool.py,sha256=mPPY1GOvBmZWn7UVP2sUaXtfcyeTCj-LmRDl2F4WhC8,2090
12
18
  bitcoin/tx_listener/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
13
19
  bitcoin/tx_listener/abstract_tx_listener.py,sha256=rGp9na-aOSl_aPaIqf44RTZaFF3SvrxIhZBujTnWqao,189
14
- bitcoin/tx_listener/zmq_listener.py,sha256=_edaee2PYj9T1jxLenv68ekZRTM8-LUN3DloDLNQ5Bc,999
20
+ bitcoin/tx_listener/zmq_listener.py,sha256=V4-WIt5PYJaYoipn0rYhcFfg1BBYxqqQGucKhGXTmkg,1110
15
21
  bitcoin/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
16
- bitcoin/utils/benchmark.py,sha256=ZCfhIe4_meUNpQ7NEioZj3_uudCisg7J8d_LTMoRFto,875
17
- bitcoin/utils/bitcoin_rpc.py,sha256=Uq3eZnLaGOgltybEWeBRubnUhTHyB8gVI_L_SnrZ-ug,1012
22
+ bitcoin/utils/benchmark.py,sha256=kaTTlo6k_5uDVIt8FMeY4nH7ZxxsoWUiMsZgHfpWsMo,894
23
+ bitcoin/utils/bitcoin_rpc.py,sha256=yEHS8BPI_Y4uLFL1ygUti8OI68JW67d_c1vshjEfQbA,932
18
24
  bitcoin/utils/bitcoin_utils.py,sha256=mrnRPqUa2U2EMKu7rrPV_bW1sL2CJUfbAom0Zdamydk,631
19
25
  bitcoin/utils/constants.py,sha256=irZLlArgica2VckyckEYxH5D5KjvdF52dtBMWswqw8k,52
20
26
  bitcoin/utils/inscription_utils.py,sha256=8QbOJ1o1n1bMFsPREGLzwFjnGzfuARgJCPr6ORhP44o,193
21
- bitcoin/utils/tx_address_data_extractor.py,sha256=M_WvBNNXYwd2qBG6oyfu8Vn6P8F0Rt5w1FnfvFO6IZc,3321
22
- bitcoinwatcher-2.1.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
23
- bitcoinwatcher-2.1.dist-info/METADATA,sha256=t7GDjAoRaQmKbUSGGEuDRxbHF-kqeQirzNyyZYiIe0c,14938
24
- bitcoinwatcher-2.1.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
25
- bitcoinwatcher-2.1.dist-info/top_level.txt,sha256=YdUgzLdCiMlrwaKyDqHA1acEd23QFko5bv7D6nBANJ0,8
26
- bitcoinwatcher-2.1.dist-info/RECORD,,
27
+ bitcoinwatcher-2.3.dist-info/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
28
+ bitcoinwatcher-2.3.dist-info/METADATA,sha256=6dlhp29bUJsGG38h9gRRhR-OMDhDayLFMRJyyJs-eec,14938
29
+ bitcoinwatcher-2.3.dist-info/WHEEL,sha256=y4mX-SOX4fYIkonsAGA5N0Oy-8_gI4FXw5HNI1xqvWg,91
30
+ bitcoinwatcher-2.3.dist-info/top_level.txt,sha256=YdUgzLdCiMlrwaKyDqHA1acEd23QFko5bv7D6nBANJ0,8
31
+ bitcoinwatcher-2.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: bdist_wheel (0.43.0)
2
+ Generator: setuptools (70.2.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5