def oid_to_order(self, offer, amount): total_amount = amount + offer["txfee"] real_cjfee = calc_cj_fee(offer["ordertype"], offer["cjfee"], amount) required_amount = total_amount + \ jm_single().DUST_THRESHOLD + 1 - real_cjfee mix_balance = self.get_available_mixdepths() filtered_mix_balance = { m: b for m, b in mix_balance.items() if b >= required_amount } if not filtered_mix_balance: return None, None, None jlog.debug('mix depths that have enough = ' + str(filtered_mix_balance)) mixdepth = self.select_input_mixdepth(filtered_mix_balance, offer, amount) if mixdepth is None: return None, None, None jlog.info('filling offer, mixdepth=' + str(mixdepth) + ', amount=' + str(amount)) cj_addr = self.select_output_address(mixdepth, offer, amount) if cj_addr is None: return None, None, None jlog.info('sending output to address=' + str(cj_addr)) change_addr = self.wallet_service.get_internal_addr(mixdepth) utxos = self.wallet_service.select_utxos(mixdepth, required_amount, minconfs=1, includeaddr=True) return utxos, cj_addr, change_addr
def on_tx_confirmed(self, offer, confirmations, txid): if offer["cjaddr"] in self.tx_unconfirm_timestamp: confirm_time = int(time.time()) - self.tx_unconfirm_timestamp[ offer["cjaddr"]] else: confirm_time = 0 timestamp = datetime.datetime.now().strftime("%Y/%m/%d %H:%M:%S") real_cjfee = calc_cj_fee(offer["offer"]["ordertype"], offer["offer"]["cjfee"], offer["amount"]) self.log_statement([timestamp, offer["amount"], len( offer["utxos"]), sum([av['value'] for av in offer["utxos"].values( )]), real_cjfee, real_cjfee - offer["offer"]["txfee"], round( confirm_time / 60.0, 2), '']) return self.on_tx_unconfirmed(offer, txid, None)
def oid_to_order(self, offer, amount): total_amount = amount + offer["txfee"] mix_balance = self.get_available_mixdepths() filtered_mix_balance = { m: b for m, b in mix_balance.items() if b >= total_amount } if not filtered_mix_balance: return None, None, None jlog.debug('mix depths that have enough = ' + str(filtered_mix_balance)) mixdepth = self.select_input_mixdepth(filtered_mix_balance, offer, amount) if mixdepth is None: return None, None, None jlog.info('filling offer, mixdepth=' + str(mixdepth) + ', amount=' + str(amount)) cj_addr = self.select_output_address(mixdepth, offer, amount) if cj_addr is None: return None, None, None jlog.info('sending output to address=' + str(cj_addr)) change_addr = self.wallet_service.get_internal_addr(mixdepth) utxos = self.wallet_service.select_utxos(mixdepth, total_amount, minconfs=1, includeaddr=True) my_total_in = sum([va['value'] for va in utxos.values()]) real_cjfee = calc_cj_fee(offer["ordertype"], offer["cjfee"], amount) change_value = my_total_in - amount - offer["txfee"] + real_cjfee if change_value <= jm_single().DUST_THRESHOLD: jlog.debug(('change value={} below dust threshold, ' 'finding new utxos').format(change_value)) try: utxos = self.wallet_service.select_utxos( mixdepth, total_amount + jm_single().DUST_THRESHOLD, minconfs=1, includeaddr=True) except Exception: jlog.info('dont have the required UTXOs to make a ' 'output above the dust threshold, quitting') return None, None, None return utxos, cj_addr, change_addr
def create_depth_chart(self, cj_amount, args=None): if 'matplotlib' not in sys.modules: return 'matplotlib not installed, charts not available' if args is None: args = {} try: self.taker.dblock.acquire(True) rows = self.taker.db.execute('SELECT * FROM orderbook;').fetchall() finally: self.taker.dblock.release() sqlorders = [ o for o in rows if o["ordertype"] in filtered_offername_list ] orderfees = sorted([ calc_cj_fee(o['ordertype'], o['cjfee'], cj_amount) / 1e8 for o in sqlorders if o['minsize'] <= cj_amount <= o['maxsize'] ]) if len(orderfees) == 0: return 'No orders at amount ' + str(cj_amount / 1e8) fig = plt.figure() scale = args.get("scale") if (scale is not None) and (scale[0] == "log"): orderfees = [float(fee) for fee in orderfees] if orderfees[0] > 0: ratio = orderfees[-1] / orderfees[0] step = ratio**0.0333 # 1/30 bins = [orderfees[0] * (step**i) for i in range(30)] else: ratio = orderfees[-1] / 1e-8 # single satoshi placeholder step = ratio**0.0333 # 1/30 bins = [1e-8 * (step**i) for i in range(30)] bins[0] = orderfees[0] # replace placeholder plt.xscale('log') else: bins = 30 if len(orderfees ) == 1: # these days we have liquidity, but just in case... plt.hist(orderfees, bins, rwidth=0.8, range=(0, orderfees[0] * 2)) else: plt.hist(orderfees, bins, rwidth=0.8) plt.grid() plt.title('CoinJoin Orderbook Depth Chart for amount=' + str(cj_amount / 1e8) + 'btc') plt.xlabel('CoinJoin Fee / btc') plt.ylabel('Frequency') return get_graph_html(fig)
def oid_to_order(self, offer, amount): total_amount = amount + offer["txfee"] mix_balance = self.wallet.get_balance_by_mixdepth() max_mix = max(mix_balance, key=mix_balance.get) filtered_mix_balance = [ m for m in iteritems(mix_balance) if m[1] >= total_amount ] if not filtered_mix_balance: return None, None, None jlog.debug('mix depths that have enough = ' + str(filtered_mix_balance)) filtered_mix_balance = sorted(filtered_mix_balance, key=lambda x: x[0]) mixdepth = filtered_mix_balance[0][0] jlog.info('filling offer, mixdepth=' + str(mixdepth) + ', amount=' + str(amount)) # mixdepth is the chosen depth we'll be spending from cj_addr = self.wallet.get_internal_addr( (mixdepth + 1) % (self.wallet.mixdepth + 1), jm_single().bc_interface) change_addr = self.wallet.get_internal_addr(mixdepth, jm_single().bc_interface) utxos = self.wallet.select_utxos(mixdepth, total_amount) my_total_in = sum([va['value'] for va in utxos.values()]) real_cjfee = calc_cj_fee(offer["ordertype"], offer["cjfee"], amount) change_value = my_total_in - amount - offer["txfee"] + real_cjfee if change_value <= jm_single().DUST_THRESHOLD: jlog.debug(('change value={} below dust threshold, ' 'finding new utxos').format(change_value)) try: utxos = self.wallet.select_utxos( mixdepth, total_amount + jm_single().DUST_THRESHOLD) except Exception: jlog.info('dont have the required UTXOs to make a ' 'output above the dust threshold, quitting') return None, None, None return utxos, cj_addr, change_addr
def oid_to_order(self, offer, amount): total_amount = amount + offer["txfee"] real_cjfee = calc_cj_fee(offer["ordertype"], offer["cjfee"], amount) required_amount = total_amount + \ jm_single().DUST_THRESHOLD + 1 - real_cjfee mix_balance = self.get_available_mixdepths() filtered_mix_balance = { m: b for m, b in mix_balance.items() if b >= required_amount } if not filtered_mix_balance: return None, None, None jlog.debug('mix depths that have enough = ' + str(filtered_mix_balance)) try: mixdepth, utxos = self._get_order_inputs(filtered_mix_balance, offer, required_amount) except NoIoauthInputException: jlog.error( 'unable to fill order, no suitable IOAUTH UTXO found. In ' 'order to spend coins (UTXOs) from a mixdepth using coinjoin,' ' there needs to be at least one standard wallet UTXO (not ' 'fidelity bond or different address type).') return None, None, None jlog.info('filling offer, mixdepth=' + str(mixdepth) + ', amount=' + str(amount)) cj_addr = self.select_output_address(mixdepth, offer, amount) if cj_addr is None: return None, None, None jlog.info('sending output to address=' + str(cj_addr)) change_addr = self.wallet_service.get_internal_addr(mixdepth) return utxos, cj_addr, change_addr