Skip to content
This repository has been archived by the owner on May 13, 2022. It is now read-only.

format tables nicely fixed-width with headers+borders via texttable.py. #539

Open
wants to merge 51 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
51 commits
Select commit Hold shift + click to select a range
e2ac78e
first draft of jm-gui QT app for sendpayment; a number of modificatio…
AdamISZ Jan 24, 2016
c6267f3
fix startsendpayment bug, remove amount debug window, fix transaction…
AdamISZ Jan 24, 2016
1771e5e
Add script for testing GUI against regtest, + modifications for handl…
AdamISZ Jan 25, 2016
818b17c
add transaction history tab and persist transactions to a file
AdamISZ Jan 25, 2016
25ac857
add donate-small-change feature to spending tab, more info on About d…
AdamISZ Jan 25, 2016
b4070f9
window resize
AdamISZ Jan 25, 2016
801c489
more fine control of layout of spend tab; added HelpLabel for clickab…
AdamISZ Jan 25, 2016
bb90911
auto-scroll to bottom of console
AdamISZ Jan 25, 2016
5dc3da2
fix file path for wallet load
AdamISZ Jan 25, 2016
66a4324
enable dynamic update of blockchain interface instance from settings tab
AdamISZ Jan 25, 2016
ec9151d
handle ignored makers in GUI; uses complete restart including IRC res…
AdamISZ Jan 26, 2016
7d36d6f
update txhistory tab immediately on tx success
AdamISZ Jan 26, 2016
fc4853e
add program description, minor comment and code removals
AdamISZ Jan 26, 2016
677631d
Merge branch 'master' of https://github.com/joinmarket-org/joinmarket…
AdamISZ Jan 26, 2016
ac28b3a
removed several globals and magic constants with settings in config, …
AdamISZ Jan 26, 2016
d6a6afb
persist config in text mode for correct Windows newlines
AdamISZ Jan 26, 2016
49f5cf6
improve About dialog, add copyable, clickable links
AdamISZ Jan 26, 2016
4f0d901
removed unwanted prints of secret data and changed other print statem…
AdamISZ Jan 26, 2016
e62680e
create wallets subdirectory if it doesnt exist
AdamISZ Jan 26, 2016
e2c5ecd
dont display new addresses for internal branch
AdamISZ Jan 27, 2016
fcfc6fd
only show txhistory context menu if an item is selected
AdamISZ Jan 27, 2016
d2dc662
signed commit. add logs dir if not there, add detailed version inform…
AdamISZ Jan 27, 2016
3114e3a
add privacy warning for Blockr usage
AdamISZ Feb 9, 2016
f6a1128
Show error if recovery words are wrong, correct wallet load debug line
AdamISZ Feb 9, 2016
bab6951
add sweep; set amount=0BTC in spending tab
AdamISZ Feb 10, 2016
b6d2191
add joinmarket and core alerts to status bar, and very loudly to the …
AdamISZ Feb 11, 2016
291b2c7
update GUI version to 2, change app name fields to JoinMarketQt
AdamISZ Feb 11, 2016
4edb6dc
rename main gui script to joinmarket-qt.py
AdamISZ Feb 11, 2016
f563581
sync wallet before starting tx to avoid spending already spent utxos
AdamISZ Feb 15, 2016
55745e6
Merge branch 'master' of https://github.com/joinmarket-org/joinmarket…
AdamISZ Feb 15, 2016
7dff7f9
update joinmarket version numbers for v0.1.3
AdamISZ Feb 15, 2016
9a114cf
fix order reading for new order dict, display more detailed informati…
AdamISZ Feb 15, 2016
657de21
2
chris-belcher Mar 4, 2016
85d8904
Merge branch 'master' of https://github.com/JoinMarket-Org/joinmarket
chris-belcher Mar 19, 2016
bb76d67
reverted default port change
chris-belcher Mar 19, 2016
d1092f5
Merge branch 'master' of https://github.com/JoinMarket-Org/joinmarket
chris-belcher Apr 23, 2016
f169351
Merge branch 'develop'
chris-belcher May 4, 2016
5916a4f
Merge branch 'develop'
chris-belcher May 4, 2016
087921b
fixed conflict
chris-belcher May 5, 2016
832a397
Fix NotifyThread
wozz May 24, 2016
a889de1
format tables nicely fixed-width with headers+borders via texttable.py.
dan-da May 25, 2016
f1df808
remove unused line
dan-da May 26, 2016
66bd67a
Merge pull request #535 from wozz/patch-1
chris-belcher May 26, 2016
7aa48dd
Merge remote-tracking branch 'upstream/master'
dan-da Jun 8, 2016
2eb3bda
Merge pull request #551 from AdamISZ/fix_filtered_mixdepth
AdamISZ Jun 2, 2016
e2314d0
yg-oscill: fix empty filtered_mix_balance crash
AlexCato Jun 8, 2016
c001e38
Merge remote-tracking branch 'upstream/develop'
dan-da Jun 9, 2016
89e40ae
fix: only summary table should be printed when 'summary' flag is present
dan-da Jun 9, 2016
47c7ef0
fix: external addresses were not printing
dan-da Jun 12, 2016
8a7e05e
add --show-xpub option
dan-da Jun 15, 2016
eb12a0e
show txid in table output
dan-da Jun 16, 2016
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1,426 changes: 1,426 additions & 0 deletions joinmarket-qt.py

Large diffs are not rendered by default.

5 changes: 3 additions & 2 deletions joinmarket/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,10 @@
from .slowaes import decryptData, encryptData
from .taker import Taker, OrderbookWatch, CoinJoinTX
from .wallet import AbstractWallet, BitcoinCoreInterface, Wallet, \
BitcoinCoreWallet
BitcoinCoreWallet, create_wallet_file
from .configure import load_program_config, jm_single, get_p2pk_vbyte, \
get_network, jm_single, get_network, validate_address
get_network, jm_single, get_network, validate_address, \
get_blockchain_interface_instance
from .blockchaininterface import BlockrInterface, BlockchainInterface
# Set default logging handler to avoid "No handler found" warnings.

Expand Down
110 changes: 61 additions & 49 deletions joinmarket/blockchaininterface.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
import subprocess

from joinmarket.jsonrpc import JsonRpcConnectionError, JsonRpcError
from joinmarket.configure import get_p2pk_vbyte, jm_single
from joinmarket.configure import get_p2pk_vbyte, jm_single, get_network
from joinmarket.support import get_log, chunks

log = get_log()
Expand Down Expand Up @@ -112,13 +112,13 @@ def query_utxo_set(self, txouts):
otherwise returns value in satoshis, address and output script
"""
# address and output script contain the same information btw

@abc.abstractmethod
def estimate_fee_per_kb(self, N):
'''Use the blockchain interface to
get an estimate of the transaction fee per kb
required for inclusion in the next N blocks.
'''
'''


class BlockrInterface(BlockchainInterface):
Expand All @@ -128,10 +128,22 @@ def __init__(self, testnet=False):
super(BlockrInterface, self).__init__()

# see bci.py in bitcoin module
self.network = 'testnet' if testnet else 'btc'
self.blockr_domain = 'tbtc' if testnet else 'btc'
#self.network = 'testnet' if testnet else 'btc'
#self.blockr_domain = 'tbtc' if testnet else 'btc'
self.last_sync_unspent = 0

def network_for_blockr_push(self):
if get_network() == 'testnet':
return 'testnet'
else:
return 'btc'

def blockr_domain(self):
if get_network() == 'testnet':
return 'tbtc'
else:
return 'btc'

def sync_addresses(self, wallet):
log.debug('downloading wallet history')
# sets Wallet internal indexes to be at the next unused address
Expand All @@ -140,14 +152,14 @@ def sync_addresses(self, wallet):
unused_addr_count = 0
last_used_addr = ''
while (unused_addr_count < wallet.gaplimit or
not is_index_ahead_of_cache(
wallet, mix_depth, forchange)):
not is_index_ahead_of_cache(
wallet, mix_depth, forchange)):
addrs = [wallet.get_new_addr(mix_depth, forchange)
for _ in range(self.BLOCKR_MAX_ADDR_REQ_COUNT)]

# TODO send a pull request to pybitcointools
# because this surely should be possible with a function from it
blockr_url = 'https://' + self.blockr_domain
blockr_url = 'https://' + self.blockr_domain()
blockr_url += '.blockr.io/api/v1/address/txs/'

res = btc.make_request(blockr_url + ','.join(addrs))
Expand All @@ -162,18 +174,18 @@ def sync_addresses(self, wallet):
wallet.index[mix_depth][forchange] = 0
else:
wallet.index[mix_depth][forchange] = wallet.addr_cache[
last_used_addr][
2] + 1
last_used_addr][
2] + 1

def sync_unspent(self, wallet):
# finds utxos in the wallet
st = time.time()
# dont refresh unspent dict more often than 10 minutes
rate_limit_time = 10 * 60
rate_limit_time = 5 * 6
if st - self.last_sync_unspent < rate_limit_time:
log.debug(
'blockr sync_unspent() happened too recently (%dsec), skipping'
% (st - self.last_sync_unspent))
'blockr sync_unspent() happened too recently (%dsec), skipping'
% (st - self.last_sync_unspent))
return
wallet.unspent = {}

Expand All @@ -191,8 +203,8 @@ def sync_unspent(self, wallet):
# unspent() doesnt tell you which address, you get a bunch of utxos
# but dont know which privkey to sign with

blockr_url = 'https://' + self.blockr_domain + \
'.blockr.io/api/v1/address/unspent/'
blockr_url = 'https://' + self.blockr_domain() + \
'.blockr.io/api/v1/address/unspent/'
res = btc.make_request(blockr_url + ','.join(req))
data = json.loads(res)['data']
if 'unspent' in data:
Expand Down Expand Up @@ -250,8 +262,8 @@ def run(self):
random.shuffle(self.output_addresses
) # seriously weird bug with blockr.io
data = json.loads(
btc.make_request(blockr_url + ','.join(
self.output_addresses
btc.make_request(blockr_url + ','.join(
self.output_addresses
) + '?unconfirmed=1'))['data']

shared_txid = None
Expand All @@ -266,12 +278,12 @@ def run(self):
if len(shared_txid) == 0:
continue
time.sleep(
2
) # here for some race condition bullshit with blockr.io
2
) # here for some race condition bullshit with blockr.io
blockr_url = 'https://' + self.blockr_domain
blockr_url += '.blockr.io/api/v1/tx/raw/'
data = json.loads(btc.make_request(blockr_url + ','.join(
shared_txid)))['data']
shared_txid)))['data']
if not isinstance(data, list):
data = [data]
for txinfo in data:
Expand All @@ -285,7 +297,7 @@ def run(self):
break

self.unconfirmfun(
btc.deserialize(unconfirmed_txhex), unconfirmed_txid)
btc.deserialize(unconfirmed_txhex), unconfirmed_txid)

st = int(time.time())
confirmed_txid = None
Expand All @@ -300,7 +312,7 @@ def run(self):
blockr_url = 'https://' + self.blockr_domain
blockr_url += '.blockr.io/api/v1/address/txs/'
data = json.loads(btc.make_request(blockr_url + ','.join(
self.output_addresses)))['data']
self.output_addresses)))['data']
shared_txid = None
for addrtxs in data:
txs = set(str(txdata['tx'])
Expand All @@ -315,8 +327,8 @@ def run(self):
blockr_url = 'https://' + self.blockr_domain
blockr_url += '.blockr.io/api/v1/tx/raw/'
data = json.loads(
btc.make_request(
blockr_url + ','.join(shared_txid)))['data']
btc.make_request(
blockr_url + ','.join(shared_txid)))['data']
if not isinstance(data, list):
data = [data]
for txinfo in data:
Expand All @@ -329,13 +341,13 @@ def run(self):
confirmed_txhex = str(txinfo['tx']['hex'])
break
self.confirmfun(
btc.deserialize(confirmed_txhex), confirmed_txid, 1)
btc.deserialize(confirmed_txhex), confirmed_txid, 1)

NotifyThread(self.blockr_domain, txd, unconfirmfun, confirmfun, timeoutfun).start()
NotifyThread(self.blockr_domain(), txd, unconfirmfun, confirmfun, timeoutfun).start()

def pushtx(self, txhex):
try:
json_str = btc.blockr_pushtx(txhex, self.network)
json_str = btc.blockr_pushtx(txhex, self.network_for_blockr_push())
data = json.loads(json_str)
if data['status'] != 'success':
log.debug(data)
Expand All @@ -358,9 +370,9 @@ def query_utxo_set(self, txout):
txids = [txids]
data = []
for ids in txids:
blockr_url = 'https://' + self.blockr_domain + '.blockr.io/api/v1/tx/info/'
blockr_url = 'https://' + self.blockr_domain() + '.blockr.io/api/v1/tx/info/'
blockr_data = json.loads(
btc.make_request(blockr_url + ','.join(ids)))['data']
btc.make_request(blockr_url + ','.join(ids)))['data']
if not isinstance(blockr_data, list):
blockr_data = [blockr_data]
data += blockr_data
Expand All @@ -372,7 +384,7 @@ def query_utxo_set(self, txout):
result.append(None)
else:
result.append({'value': int(Decimal(vout['amount']) * Decimal(
'1e8')),
'1e8')),
'address': vout['address'],
'script': vout['extras']['script']})
return result
Expand All @@ -381,14 +393,14 @@ def estimate_fee_per_kb(self, N):
bcypher_fee_estimate_url = 'https://api.blockcypher.com/v1/btc/main'
bcypher_data = json.loads(btc.make_request(bcypher_fee_estimate_url))
log.debug("Got blockcypher result: "+pprint.pformat(bcypher_data))
if N<=2:
fee_per_kb = bcypher_data["high_fee_per_kb"]
elif N <=4:
fee_per_kb = bcypher_data["medium_fee_per_kb"]
else:
fee_per_kb = bcypher_data["low_fee_per_kb"]
return fee_per_kb
if N<=2:
fee_per_kb = bcypher_data["high_fee_per_kb"]
elif N <=4:
fee_per_kb = bcypher_data["medium_fee_per_kb"]
else:
fee_per_kb = bcypher_data["low_fee_per_kb"]

return fee_per_kb

def bitcoincore_timeout_callback(uc_called, txout_set, txnotify_fun_list,
timeoutfun):
Expand All @@ -411,7 +423,7 @@ def __init__(self, request, client_address, base_server):
self.btcinterface = base_server.btcinterface
self.base_server = base_server
BaseHTTPServer.BaseHTTPRequestHandler.__init__(
self, request, client_address, base_server)
self, request, client_address, base_server)

def do_HEAD(self):
pages = ('/walletnotify?', '/alertnotify?')
Expand Down Expand Up @@ -562,7 +574,7 @@ def add_watchonly_addresses(self, addr_list, wallet_name):
for addr in addr_list:
self.rpc('importaddress', [addr, wallet_name, False])
if jm_single().config.get(
"BLOCKCHAIN", "blockchain_source") != 'regtest':
"BLOCKCHAIN", "blockchain_source") != 'regtest':
print('restart Bitcoin Core with -rescan if you\'re '
'recovering an existing wallet from backup seed')
print(' otherwise just restart this joinmarket script')
Expand Down Expand Up @@ -616,16 +628,16 @@ def sync_addresses(self, wallet):
breakloop = False
while not breakloop:
if unused_addr_count >= wallet.gaplimit and \
is_index_ahead_of_cache(wallet, mix_depth,
forchange):
is_index_ahead_of_cache(wallet, mix_depth,
forchange):
break
mix_change_addrs = [
wallet.get_new_addr(mix_depth, forchange)
for _ in range(addr_req_count)]
for mc_addr in mix_change_addrs:
if mc_addr not in imported_addr_list:
too_few_addr_mix_change.append(
(mix_depth, forchange))
(mix_depth, forchange))
breakloop = True
break
if mc_addr in used_addr_list:
Expand Down Expand Up @@ -733,12 +745,12 @@ def query_utxo_set(self, txout):

def estimate_fee_per_kb(self, N):
estimate = Decimal(1e8)*Decimal(self.rpc('estimatefee', [N]))
if estimate < 0:
#This occurs when Core has insufficient data to estimate.
#TODO anything better than a hardcoded default?
return 30000
if estimate < 0:
#This occurs when Core has insufficient data to estimate.
#TODO anything better than a hardcoded default?
return 30000
else:
return estimate
return estimate

# class for regtest chain access
# running on local daemon. Only
Expand Down Expand Up @@ -831,7 +843,7 @@ def get_received_by_addr(self, addresses, query_params):
self.rpc('importaddress', [address, 'watchonly'])
res.append({'address': address,
'balance': int(Decimal(1e8) * Decimal(
self.rpc('getreceivedbyaddress', [address])))})
self.rpc('getreceivedbyaddress', [address])))})
return {'data': res}

# todo: won't run anyways
Expand Down
3 changes: 1 addition & 2 deletions joinmarket/configure.py
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,7 @@ def jm_single():
socks5_port = 9050
#for tor
#host = 6dvj6v5imhny3anf.onion
#onion / i2p have their own ports on CGAN
#port = 6698
#port = 6697
#usessl = true
#socks5 = true

Expand Down