# Path: jmbase/jmbase/support.py
# def jmprint(msg, level="info"):
#     """ Provides the ability to print messages
#     with consistent formatting, outside the logging system
#     (in case you don't want the standard log format).
#     Example applications are: REPL style stuff, and/or
#     some very important / user workflow affecting communication.
#     Note that this exclusively for console printout, NOT for
#     logging to file (chromalog will handle file streams
#     properly, but this will not).
#     """
#     if not level in jm_color_map.keys():
#         raise Exception("Unsupported formatting")
# 
#     if sys.stdout.isatty():
#         # .colorize_message function does a .format() on the string,
#         # which does not work with string-ified json; this should
#         # result in output as intended:
#         msg = msg.replace('{', '{{')
#         msg = msg.replace('}', '}}')
# 
#     fmtfn = eval(level)
#     fmtd_msg = fmtfn(msg)
#     if sys.stdout.isatty():
#         print(jm_colorizer.colorize_message(fmtd_msg))
#     else:
#         print(fmtd_msg)
# 
# def hextobin(h):
#     """Convert a hex string to bytes"""
#     return binascii.unhexlify(h.encode('utf8'))
# 
# def utxo_to_utxostr(u):
#     if not isinstance(u, tuple):
#         return (False, "utxo is not a tuple.")
#     if not len(u) == 2:
#         return (False, "utxo should have two elements.")
#     if not isinstance(u[0], bytes):
#         return (False, "txid should be bytes.")
#     if not isinstance(u[1], int):
#         return (False, "index should be int.")
#     if u[1] < 0:
#         return (False, "index must be a positive integer.")
#     if not len(u[0]) == 32:
#         return (False, "txid must be 32 bytes.")
#     txid = binascii.hexlify(u[0]).decode("ascii")
#     return (True, txid + ":" + str(u[1]))
# 
# EXIT_SUCCESS = 0
# 
# Path: jmbase/jmbase/twisted_utils.py
# def stop_reactor():
#     if not _custom_stop_reactor_is_set:
#         _stop_reactor()
#     else:
#         custom_stop_reactor()


import collections
import time
import sys
import jmbitcoin as btc
from decimal import Decimal
from copy import deepcopy
from twisted.internet import reactor
from twisted.internet import task
from twisted.application.service import Service
from numbers import Integral
from jmclient.configure import jm_single, get_log
from jmclient.output import fmt_tx_data
from jmclient.blockchaininterface import (INF_HEIGHT, BitcoinCoreInterface,
    BitcoinCoreNoHistoryInterface)
from jmclient.wallet import FidelityBondMixin, BaseWallet
from jmbase import (stop_reactor, hextobin, utxo_to_utxostr,
                    jmprint, EXIT_SUCCESS)

    def check_callback_called(self, txinfo, callback, cbtype, msg):
        """ Intended to be a deferred Task to be scheduled some
        set time after the callback was registered. "all" type
        callbacks do not expire and are not included.
        If the callback was previously called, return True, otherwise False.
        """
        assert cbtype in ["unconfirmed", "confirmed"]
        if txinfo in self.callbacks[cbtype]:
            if callback in self.callbacks[cbtype][txinfo]:
                # the callback was not called, drop it and warn
                self.callbacks[cbtype][txinfo].remove(callback)
                # TODO - dangling txids in self.active_txids will
                # be caused by this, but could also happen for
                # other reasons; possibly add logic to ensure that
                # this never occurs, although their presence should
                # not cause a functional error.
                jlog.info("Timed out: " + msg)
                return False
            # if callback is not in the list, it was already
            # processed and so do nothing.
        return True

    def log_new_tx(self, removed_utxos, added_utxos, txid):
        """ Changes to the wallet are logged at INFO level by
        the WalletService.
        """
        def report_changed(x, utxos):
            if len(utxos.keys()) > 0:
                jlog.info(x + ' utxos=\n{}'.format('\n'.join(

# Path: jmbase/jmbase/support.py
# def jmprint(msg, level="info"):
#     """ Provides the ability to print messages
#     with consistent formatting, outside the logging system
#     (in case you don't want the standard log format).
#     Example applications are: REPL style stuff, and/or
#     some very important / user workflow affecting communication.
#     Note that this exclusively for console printout, NOT for
#     logging to file (chromalog will handle file streams
#     properly, but this will not).
#     """
#     if not level in jm_color_map.keys():
#         raise Exception("Unsupported formatting")
# 
#     if sys.stdout.isatty():
#         # .colorize_message function does a .format() on the string,
#         # which does not work with string-ified json; this should
#         # result in output as intended:
#         msg = msg.replace('{', '{{')
#         msg = msg.replace('}', '}}')
# 
#     fmtfn = eval(level)
#     fmtd_msg = fmtfn(msg)
#     if sys.stdout.isatty():
#         print(jm_colorizer.colorize_message(fmtd_msg))
#     else:
#         print(fmtd_msg)
# 
# def hextobin(h):
#     """Convert a hex string to bytes"""
#     return binascii.unhexlify(h.encode('utf8'))
# 
# def utxo_to_utxostr(u):
#     if not isinstance(u, tuple):
#         return (False, "utxo is not a tuple.")
#     if not len(u) == 2:
#         return (False, "utxo should have two elements.")
#     if not isinstance(u[0], bytes):
#         return (False, "txid should be bytes.")
#     if not isinstance(u[1], int):
#         return (False, "index should be int.")
#     if u[1] < 0:
#         return (False, "index must be a positive integer.")
#     if not len(u[0]) == 32:
#         return (False, "txid must be 32 bytes.")
#     txid = binascii.hexlify(u[0]).decode("ascii")
#     return (True, txid + ":" + str(u[1]))
# 
# EXIT_SUCCESS = 0
# 
# Path: jmbase/jmbase/twisted_utils.py
# def stop_reactor():
#     if not _custom_stop_reactor_is_set:
#         _stop_reactor()
#     else:
#         custom_stop_reactor()


# Path: jmclient/jmclient/wallet_service.py
import collections
import time
import sys
import jmbitcoin as btc
from decimal import Decimal
from copy import deepcopy
from twisted.internet import reactor
from twisted.internet import task
from twisted.application.service import Service
from numbers import Integral
from jmclient.configure import jm_single, get_log
from jmclient.output import fmt_tx_data
from jmclient.blockchaininterface import (INF_HEIGHT, BitcoinCoreInterface,
    BitcoinCoreNoHistoryInterface)
from jmclient.wallet import FidelityBondMixin, BaseWallet
from jmbase import (stop_reactor, hextobin, utxo_to_utxostr,
                    jmprint, EXIT_SUCCESS)


    def check_callback_called(self, txinfo, callback, cbtype, msg):
        """ Intended to be a deferred Task to be scheduled some
        set time after the callback was registered. "all" type
        callbacks do not expire and are not included.
        If the callback was previously called, return True, otherwise False.
        """
        assert cbtype in ["unconfirmed", "confirmed"]
        if txinfo in self.callbacks[cbtype]:
            if callback in self.callbacks[cbtype][txinfo]:
                # the callback was not called, drop it and warn
                self.callbacks[cbtype][txinfo].remove(callback)
                # TODO - dangling txids in self.active_txids will
                # be caused by this, but could also happen for
                # other reasons; possibly add logic to ensure that
                # this never occurs, although their presence should
                # not cause a functional error.
                jlog.info("Timed out: " + msg)
                return False
            # if callback is not in the list, it was already
            # processed and so do nothing.
        return True

    def log_new_tx(self, removed_utxos, added_utxos, txid):
        """ Changes to the wallet are logged at INFO level by
        the WalletService.
        """
        def report_changed(x, utxos):
            if len(utxos.keys()) > 0:
                jlog.info(x + ' utxos=\n{}'.format('\n'.join(

                    '{} - {}'.format(utxo_to_utxostr(u)[1],