# Path: jmbase/jmbase/support.py
# def get_log():
#     """
#     provides joinmarket logging instance
#     :return: log instance
#     """
#     return log
# 
# def bintohex(b):
#     """Convert bytes to a hex string"""
#     return binascii.hexlify(b).decode('utf8')
# 
# def hexbin(func):
#     """ Decorator for functions of taker and maker receiving over
#     the wire AMP arguments that may be in hex or hextxid:n format
#     and converting all to binary.
#     Functions to which this decorator applies should have all arguments
#     be one of:
#     - hex string (keys), converted here to binary
#     - lists of keys or txid:n strings (converted here to binary, or
#       (txidbytes, n))
#     - lists of lists or dicts, to which these rules apply recursively.
#     - any other string (unchanged)
#     - dicts with keys as per above; values are altered recursively according
#       to the rules above.
#     """
#     @wraps(func)
#     def func_wrapper(inst, *args, **kwargs):
#         newargs = []
#         for arg in args:
#             if isinstance(arg, (list, tuple)):
#                 newargs.append(listchanger(arg))
#             elif isinstance(arg, dict):
#                 newargs.append(dictchanger(arg))
#             else:
#                 newargs.append(_convert(arg))
#         return func(inst, *newargs, **kwargs)
# 
#     return func_wrapper
# 
# Path: jmclient/jmclient/cryptoengine.py
# class EngineError(Exception):
#     pass
# 
# Path: jmclient/jmclient/schedule.py
# NO_ROUNDING = 16 #max btc significant figures not including LN


import base64
import pprint
import random
import jmbitcoin as btc
from typing import Any, NamedTuple
from twisted.internet import reactor, task
from jmclient.configure import jm_single, validate_address, get_interest_rate
from jmbase import get_log, bintohex, hexbin
from jmclient.support import (calc_cj_fee, fidelity_bond_weighted_order_choose, choose_orders,
                              choose_sweep_orders)
from jmclient.wallet import estimate_tx_fee, compute_tx_locktime, FidelityBondMixin
from jmclient.podle import generate_podle, get_podle_commitments
from jmclient.wallet_service import WalletService
from jmclient.fidelity_bond import FidelityBondProof
from .output import generate_podle_error_string
from .cryptoengine import EngineError
from .schedule import NO_ROUNDING
            if self.orderbook is None:
                #Failure to get an orderbook means order selection failed
                #for some reason; no action is taken, we let the stallMonitor
                # + the finished callback decide whether to retry.
                return False
            if self.filter_orders_callback:
                accepted = self.filter_orders_callback([self.orderbook,
                                                        self.total_cj_fee],
                                                       self.cjamount)
                if accepted == "retry":
                    #Special condition if Taker is "determined to continue"
                    #(such as tumbler); even though these offers are rejected,
                    #we don't trigger the finished callback; see above note on
                    #`if self.orderbook is None`
                    return False
                if not accepted:
                    return False
        return True

    def prepare_my_bitcoin_data(self):
        """Get a coinjoin address and a change address; prepare inputs
        appropriate for this transaction"""
        if not self.my_cj_addr:
            #previously used for donations; TODO reimplement?
            raise NotImplementedError
        if self.cjamount != 0:
            if self.custom_change_address:
                self.my_change_addr = self.custom_change_address
            else:
                try:

# Path: jmbase/jmbase/support.py
# def get_log():
#     """
#     provides joinmarket logging instance
#     :return: log instance
#     """
#     return log
# 
# def bintohex(b):
#     """Convert bytes to a hex string"""
#     return binascii.hexlify(b).decode('utf8')
# 
# def hexbin(func):
#     """ Decorator for functions of taker and maker receiving over
#     the wire AMP arguments that may be in hex or hextxid:n format
#     and converting all to binary.
#     Functions to which this decorator applies should have all arguments
#     be one of:
#     - hex string (keys), converted here to binary
#     - lists of keys or txid:n strings (converted here to binary, or
#       (txidbytes, n))
#     - lists of lists or dicts, to which these rules apply recursively.
#     - any other string (unchanged)
#     - dicts with keys as per above; values are altered recursively according
#       to the rules above.
#     """
#     @wraps(func)
#     def func_wrapper(inst, *args, **kwargs):
#         newargs = []
#         for arg in args:
#             if isinstance(arg, (list, tuple)):
#                 newargs.append(listchanger(arg))
#             elif isinstance(arg, dict):
#                 newargs.append(dictchanger(arg))
#             else:
#                 newargs.append(_convert(arg))
#         return func(inst, *newargs, **kwargs)
# 
#     return func_wrapper
# 
# Path: jmclient/jmclient/cryptoengine.py
# class EngineError(Exception):
#     pass
# 
# Path: jmclient/jmclient/schedule.py
# NO_ROUNDING = 16 #max btc significant figures not including LN


# Path: jmclient/jmclient/taker.py
import base64
import pprint
import random
import jmbitcoin as btc
from typing import Any, NamedTuple
from twisted.internet import reactor, task
from jmclient.configure import jm_single, validate_address, get_interest_rate
from jmbase import get_log, bintohex, hexbin
from jmclient.support import (calc_cj_fee, fidelity_bond_weighted_order_choose, choose_orders,
                              choose_sweep_orders)
from jmclient.wallet import estimate_tx_fee, compute_tx_locktime, FidelityBondMixin
from jmclient.podle import generate_podle, get_podle_commitments
from jmclient.wallet_service import WalletService
from jmclient.fidelity_bond import FidelityBondProof
from .output import generate_podle_error_string
from .cryptoengine import EngineError
from .schedule import NO_ROUNDING

            if self.orderbook is None:
                #Failure to get an orderbook means order selection failed
                #for some reason; no action is taken, we let the stallMonitor
                # + the finished callback decide whether to retry.
                return False
            if self.filter_orders_callback:
                accepted = self.filter_orders_callback([self.orderbook,
                                                        self.total_cj_fee],
                                                       self.cjamount)
                if accepted == "retry":
                    #Special condition if Taker is "determined to continue"
                    #(such as tumbler); even though these offers are rejected,
                    #we don't trigger the finished callback; see above note on
                    #`if self.orderbook is None`
                    return False
                if not accepted:
                    return False
        return True

    def prepare_my_bitcoin_data(self):
        """Get a coinjoin address and a change address; prepare inputs
        appropriate for this transaction"""
        if not self.my_cj_addr:
            #previously used for donations; TODO reimplement?
            raise NotImplementedError
        if self.cjamount != 0:
            if self.custom_change_address:
                self.my_change_addr = self.custom_change_address
            else:
                try:

                    self.my_change_addr = self.wallet_service.get_internal_addr(self.mixdepth)