Skip to content

Commit 2865dd9

Browse files
committed
Merge pull request vbuterin#129 from wizardofozzie/patch-10
Auto-detect testnet for unspent/fetchtx
2 parents 5ba8caf + df5f9c4 commit 2865dd9

File tree

1 file changed

+66
-10
lines changed

1 file changed

+66
-10
lines changed

bitcoin/bci.py

Lines changed: 66 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,26 +23,82 @@ def make_request(*args):
2323
raise Exception(p)
2424

2525

26+
def is_testnet(inp):
27+
'''Checks if inp is a testnet address or if UTXO is a known testnet TxID'''
28+
if isinstance(inp, (list, tuple)) and len(inp) >= 1:
29+
return any([is_testnet(x) for x in inp])
30+
elif not isinstance(inp, basestring): # sanity check
31+
raise TypeError("Input must be str/unicode, not type %s" % str(type(inp)))
32+
33+
if not inp or (inp.lower() in ("btc", "testnet")):
34+
pass
35+
36+
## ADDRESSES
37+
if inp[0] in "123mn":
38+
if re.match("^[2mn][a-km-zA-HJ-NP-Z0-9]{26,33}$", inp):
39+
return True
40+
elif re.match("^[13][a-km-zA-HJ-NP-Z0-9]{26,33}$", inp):
41+
return False
42+
else:
43+
#sys.stderr.write("Bad address format %s")
44+
return None
45+
46+
## TXID
47+
elif re.match('^[0-9a-fA-F]{64}$', inp):
48+
base_url = "http://api.blockcypher.com/v1/btc/{network}/txs/{txid}?includesHex=false"
49+
try:
50+
# try testnet fetchtx
51+
make_request(base_url.format(network="test3", txid=inp.lower()))
52+
return True
53+
except:
54+
# try mainnet fetchtx
55+
make_request(base_url.format(network="main", txid=inp.lower()))
56+
return False
57+
sys.stderr.write("TxID %s has no match for testnet or mainnet (Bad TxID)")
58+
return None
59+
else:
60+
raise TypeError("{0} is unknown input".format(inp))
61+
62+
63+
def set_network(*args):
64+
'''Decides if args for unspent/fetchtx/pushtx are mainnet or testnet'''
65+
r = []
66+
for arg in args:
67+
if not arg:
68+
pass
69+
if isinstance(arg, basestring):
70+
r.append(is_testnet(arg))
71+
elif isinstance(arg, (list, tuple)):
72+
return set_network(*arg)
73+
if any(r) and not all(r):
74+
raise Exception("Mixed Testnet/Mainnet queries")
75+
return "testnet" if any(r) else "btc"
76+
77+
2678
def parse_addr_args(*args):
27-
# Valid input formats: blockr_unspent([addr1, addr2,addr3])
28-
# blockr_unspent(addr1, addr2, addr3)
29-
# blockr_unspent([addr1, addr2, addr3], network)
30-
# blockr_unspent(addr1, addr2, addr3, network)
31-
# Where network is 'btc' or 'testnet'
32-
network = 'btc'
79+
# Valid input formats: unspent([addr1, addr2, addr3])
80+
# unspent([addr1, addr2, addr3], network)
81+
# unspent(addr1, addr2, addr3)
82+
# unspent(addr1, addr2, addr3, network)
3383
addr_args = args
84+
network = "btc"
85+
if len(args) == 0:
86+
return [], 'btc'
3487
if len(args) >= 1 and args[-1] in ('testnet', 'btc'):
3588
network = args[-1]
3689
addr_args = args[:-1]
3790
if len(addr_args) == 1 and isinstance(addr_args, list):
91+
network = set_network(*addr_args[0])
3892
addr_args = addr_args[0]
39-
40-
return network, addr_args
93+
if addr_args and isinstance(addr_args, tuple) and isinstance(addr_args[0], list):
94+
addr_args = addr_args[0]
95+
network = set_network(addr_args)
96+
return addr_args, network # note params are "reversed" now
4197

4298

4399
# Gets the unspent outputs of one or more addresses
44100
def bci_unspent(*args):
45-
network, addrs = parse_addr_args(*args)
101+
addrs, network = parse_addr_args(*args)
46102
u = []
47103
for a in addrs:
48104
try:
@@ -102,7 +158,7 @@ def blockr_unspent(*args):
102158

103159

104160
def helloblock_unspent(*args):
105-
network, addrs = parse_addr_args(*args)
161+
addrs, network = parse_addr_args(*args)
106162
if network == 'testnet':
107163
url = 'https://testnet.helloblock.io/v1/addresses/%s/unspents?limit=500&offset=%s'
108164
elif network == 'btc':

0 commit comments

Comments
 (0)