From a909d50e2d0052fc9f6a3da3d76bbd03a9534a81 Mon Sep 17 00:00:00 2001 From: Corentin Mercier Date: Tue, 19 Nov 2019 16:22:26 +0200 Subject: [PATCH 1/6] Replaced Blockdozer API with Bitcore.io --- bitcash/network/services.py | 58 +++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 21 deletions(-) diff --git a/bitcash/network/services.py b/bitcash/network/services.py index 333cee91..b644f13b 100644 --- a/bitcash/network/services.py +++ b/bitcash/network/services.py @@ -147,23 +147,39 @@ def get_unspent(cls, address): ] -class BlockdozerAPI(InsightAPI): - MAIN_ENDPOINT = 'https://blockdozer.com/api/' - MAIN_ADDRESS_API = MAIN_ENDPOINT + 'addr/{}' +class BitcoreAPI(InsightAPI): + """ Insight API v8 """ + MAIN_ENDPOINT = 'https://api.bitcore.io/api/BCH/mainnet/' + MAIN_ADDRESS_API = MAIN_ENDPOINT + 'address/{}' MAIN_BALANCE_API = MAIN_ADDRESS_API + '/balance' - MAIN_UNSPENT_API = MAIN_ADDRESS_API + '/utxo' - MAIN_TX_PUSH_API = MAIN_ENDPOINT + 'tx/send' + MAIN_UNSPENT_API = MAIN_ADDRESS_API + '/?unspent=true' + MAIN_TX_PUSH_API = MAIN_ENDPOINT + 'tx/send' # to fix MAIN_TX_API = MAIN_ENDPOINT + 'tx/{}' MAIN_TX_AMOUNT_API = MAIN_TX_API - TEST_ENDPOINT = 'https://tbch.blockdozer.com/api/' - TEST_ADDRESS_API = TEST_ENDPOINT + 'addr/{}' + TEST_ENDPOINT = 'https://api.bitcore.io/api/BCH/mainnet/' + TEST_ADDRESS_API = TEST_ENDPOINT + 'address/{}' TEST_BALANCE_API = TEST_ADDRESS_API + '/balance' - TEST_UNSPENT_API = TEST_ADDRESS_API + '/utxo' + TEST_UNSPENT_API = TEST_ADDRESS_API + '/?unspent=true' TEST_TX_PUSH_API = TEST_ENDPOINT + 'tx/send' TEST_TX_API = TEST_ENDPOINT + 'tx/{}' TEST_TX_AMOUNT_API = TEST_TX_API TX_PUSH_PARAM = 'rawtx' + @classmethod + def get_unspent(cls, address): + address = address.replace('bitcoincash:', '') + r = requests.get(cls.MAIN_UNSPENT_API.format(address), timeout=DEFAULT_TIMEOUT) + if r.status_code != 200: # pragma: no cover + raise ConnectionError + return [ + Unspent(currency_to_satoshi(tx['value'], 'satoshi'), + tx['confirmations'], + tx['script'], + tx['mintTxid'], + tx['mintIndex']) + for tx in r.json() + ] + @classmethod def get_balance_testnet(cls, address): r = requests.get(cls.TEST_BALANCE_API.format(address), timeout=DEFAULT_TIMEOUT) @@ -250,24 +266,24 @@ class NetworkAPI: requests.exceptions.ReadTimeout) GET_BALANCE_MAIN = [CashExplorerBitcoinDotComAPI.get_balance, - BlockdozerAPI.get_balance] + BitcoreAPI.get_balance] GET_TRANSACTIONS_MAIN = [CashExplorerBitcoinDotComAPI.get_transactions, - BlockdozerAPI.get_transactions] + BitcoreAPI.get_transactions] GET_UNSPENT_MAIN = [CashExplorerBitcoinDotComAPI.get_unspent, - BlockdozerAPI.get_unspent] + BitcoreAPI.get_unspent] BROADCAST_TX_MAIN = [CashExplorerBitcoinDotComAPI.broadcast_tx, - BlockdozerAPI.broadcast_tx] + BitcoreAPI.broadcast_tx] GET_TX_MAIN = [CashExplorerBitcoinDotComAPI.get_transaction, - BlockdozerAPI.get_transaction] + BitcoreAPI.get_transaction] GET_TX_AMOUNT_MAIN = [CashExplorerBitcoinDotComAPI.get_tx_amount, - BlockdozerAPI.get_tx_amount] - - GET_BALANCE_TEST = [BlockdozerAPI.get_balance_testnet] - GET_TRANSACTIONS_TEST = [BlockdozerAPI.get_transactions_testnet] - GET_UNSPENT_TEST = [BlockdozerAPI.get_unspent_testnet] - BROADCAST_TX_TEST = [BlockdozerAPI.broadcast_tx_testnet] - GET_TX_TEST = [BlockdozerAPI.get_transaction_testnet] - GET_TX_AMOUNT_TEST = [BlockdozerAPI.get_tx_amount_testnet] + BitcoreAPI.get_tx_amount] + + GET_BALANCE_TEST = [BitcoreAPI.get_balance_testnet] + GET_TRANSACTIONS_TEST = [BitcoreAPI.get_transactions_testnet] + GET_UNSPENT_TEST = [BitcoreAPI.get_unspent_testnet] + BROADCAST_TX_TEST = [BitcoreAPI.broadcast_tx_testnet] + GET_TX_TEST = [BitcoreAPI.get_transaction_testnet] + GET_TX_AMOUNT_TEST = [BitcoreAPI.get_tx_amount_testnet] @classmethod def get_balance(cls, address): From d0d7ed99a16ac934bc9d86979db5d261d278cdd2 Mon Sep 17 00:00:00 2001 From: Corentin Mercier Date: Tue, 19 Nov 2019 16:34:35 +0200 Subject: [PATCH 2/6] Fixed get_unspent_testnet() --- bitcash/network/services.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/bitcash/network/services.py b/bitcash/network/services.py index b644f13b..5af68260 100644 --- a/bitcash/network/services.py +++ b/bitcash/network/services.py @@ -156,7 +156,7 @@ class BitcoreAPI(InsightAPI): MAIN_TX_PUSH_API = MAIN_ENDPOINT + 'tx/send' # to fix MAIN_TX_API = MAIN_ENDPOINT + 'tx/{}' MAIN_TX_AMOUNT_API = MAIN_TX_API - TEST_ENDPOINT = 'https://api.bitcore.io/api/BCH/mainnet/' + TEST_ENDPOINT = 'https://api.bitcore.io/api/BCH/testnet/' TEST_ADDRESS_API = TEST_ENDPOINT + 'address/{}' TEST_BALANCE_API = TEST_ADDRESS_API + '/balance' TEST_UNSPENT_API = TEST_ADDRESS_API + '/?unspent=true' @@ -232,18 +232,22 @@ def get_tx_amount_testnet(cls, txid, txindex): @classmethod def get_unspent_testnet(cls, address): + address = address.replace('bchtest:', '') r = requests.get(cls.TEST_UNSPENT_API.format(address), timeout=DEFAULT_TIMEOUT) if r.status_code != 200: # pragma: no cover raise ConnectionError unspents = [] for tx in r.json(): - # In weird conditions, the API will send back unspents without a scriptPubKey. - if 'scriptPubKey' in tx: - unspents.append(Unspent(currency_to_satoshi(tx['amount'], 'bch'), - tx['confirmations'], - tx['scriptPubKey'], - tx['txid'], - tx['vout'])) + # In weird conditions, the API will send back unspents + # without a scriptPubKey. + if 'script' in tx: + unspents.append(Unspent(currency_to_satoshi( + tx['value'], 'satoshi'), + tx['confirmations'], + tx['script'], + tx['mintTxid'], + tx['mintIndex']) + ) else: logging.warning('Unspent without scriptPubKey.') From 0a9f6ce8e663f42cf376460e40332523019c75ea Mon Sep 17 00:00:00 2001 From: Corentin Mercier Date: Tue, 19 Nov 2019 16:39:14 +0200 Subject: [PATCH 3/6] Fixed import BlockdozerAPI -> BitcoreAPI --- tests/network/test_services.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/network/test_services.py b/tests/network/test_services.py index 11eb747d..5ca4ece0 100644 --- a/tests/network/test_services.py +++ b/tests/network/test_services.py @@ -2,7 +2,7 @@ import bitcash from bitcash.network.services import ( - CashExplorerBitcoinDotComAPI, BlockdozerAPI, NetworkAPI, set_service_timeout + CashExplorerBitcoinDotComAPI, BitcoreAPI, NetworkAPI, set_service_timeout ) from tests.utils import ( catch_errors_raise_warnings, decorate_methods, raise_connection_error From d570814ffbe4266d3d3d06d94b525e9346c2af0a Mon Sep 17 00:00:00 2001 From: Corentin Mercier Date: Wed, 20 Nov 2019 20:28:42 +0100 Subject: [PATCH 4/6] Fixed get_transactions() --- bitcash/network/services.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/bitcash/network/services.py b/bitcash/network/services.py index 5af68260..10e5f9c4 100644 --- a/bitcash/network/services.py +++ b/bitcash/network/services.py @@ -180,6 +180,14 @@ def get_unspent(cls, address): for tx in r.json() ] + @classmethod + def get_transactions(cls, address): + address = address.replace('bitcoincash:', '') + r = requests.get(cls.MAIN_ADDRESS_API.format(address), timeout=DEFAULT_TIMEOUT) + if r.status_code != 200: # pragma: no cover + raise ConnectionError + return [tx['mintTxid'] for tx in r.json()] + @classmethod def get_balance_testnet(cls, address): r = requests.get(cls.TEST_BALANCE_API.format(address), timeout=DEFAULT_TIMEOUT) From 426f549b0f0c21977688aba9edc3e078c4edb127 Mon Sep 17 00:00:00 2001 From: Corentin Mercier Date: Wed, 20 Nov 2019 20:31:38 +0100 Subject: [PATCH 5/6] Fixed get_transactions() testnet --- bitcash/network/services.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/bitcash/network/services.py b/bitcash/network/services.py index 10e5f9c4..c82fae9d 100644 --- a/bitcash/network/services.py +++ b/bitcash/network/services.py @@ -197,10 +197,11 @@ def get_balance_testnet(cls, address): @classmethod def get_transactions_testnet(cls, address): + address = address.replace('bchtest:', '') r = requests.get(cls.TEST_ADDRESS_API.format(address), timeout=DEFAULT_TIMEOUT) if r.status_code != 200: # pragma: no cover raise ConnectionError - return r.json()['transactions'] + return [tx['mintTxid'] for tx in r.json()] @classmethod def get_transaction_testnet(cls, txid): From 05e0395c7da759e4f45c1bb0e8a2947aab11a722 Mon Sep 17 00:00:00 2001 From: Corentin Mercier Date: Fri, 22 Nov 2019 07:20:25 +0100 Subject: [PATCH 6/6] Fixed broadcast_tx() and broadcast_tx_testnet() --- bitcash/network/services.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/bitcash/network/services.py b/bitcash/network/services.py index c82fae9d..d5da3b05 100644 --- a/bitcash/network/services.py +++ b/bitcash/network/services.py @@ -94,7 +94,7 @@ def get_unspent(cls, address): @classmethod def broadcast_tx(cls, tx_hex): # pragma: no cover - r = requests.post(cls.MAIN_TX_PUSH_API, json={cls.TX_PUSH_PARAM: tx_hex}, timeout=DEFAULT_TIMEOUT) + r = requests.post(cls.MAIN_TX_PUSH_API, json={cls.TX_PUSH_PARAM: tx_hex, 'network': 'mainnet', 'coin': 'BCH'}, timeout=DEFAULT_TIMEOUT) return True if r.status_code == 200 else False @@ -153,7 +153,7 @@ class BitcoreAPI(InsightAPI): MAIN_ADDRESS_API = MAIN_ENDPOINT + 'address/{}' MAIN_BALANCE_API = MAIN_ADDRESS_API + '/balance' MAIN_UNSPENT_API = MAIN_ADDRESS_API + '/?unspent=true' - MAIN_TX_PUSH_API = MAIN_ENDPOINT + 'tx/send' # to fix + MAIN_TX_PUSH_API = MAIN_ENDPOINT + 'tx/send' MAIN_TX_API = MAIN_ENDPOINT + 'tx/{}' MAIN_TX_AMOUNT_API = MAIN_TX_API TEST_ENDPOINT = 'https://api.bitcore.io/api/BCH/testnet/' @@ -163,7 +163,7 @@ class BitcoreAPI(InsightAPI): TEST_TX_PUSH_API = TEST_ENDPOINT + 'tx/send' TEST_TX_API = TEST_ENDPOINT + 'tx/{}' TEST_TX_AMOUNT_API = TEST_TX_API - TX_PUSH_PARAM = 'rawtx' + TX_PUSH_PARAM = 'rawTx' @classmethod def get_unspent(cls, address): @@ -264,12 +264,8 @@ def get_unspent_testnet(cls, address): @classmethod def broadcast_tx_testnet(cls, tx_hex): # pragma: no cover - r = requests.post(cls.TEST_TX_PUSH_API, json={cls.TX_PUSH_PARAM: tx_hex}, timeout=DEFAULT_TIMEOUT) - if r.status_code == 200: - return True - else: - logging.error(r.text) - return False + r = requests.post(cls.TEST_TX_PUSH_API, json={cls.TX_PUSH_PARAM: tx_hex, 'network': 'testnet', 'coin': 'BCH'}, timeout=DEFAULT_TIMEOUT) + return True if r.status_code == 200 else False class NetworkAPI: