|
@@ -14,19 +14,19 @@ proto.btc.tw.txhistory: Bitcoin base protocol tracking wallet transaction histor
|
|
|
|
|
|
from collections import namedtuple
|
|
from collections import namedtuple
|
|
from ....tw.txhistory import TwTxHistory
|
|
from ....tw.txhistory import TwTxHistory
|
|
-from ....tw.shared import get_tw_label,TwMMGenID
|
|
|
|
|
|
+from ....tw.shared import get_tw_label, TwMMGenID
|
|
from ....addr import CoinAddr
|
|
from ....addr import CoinAddr
|
|
-from ....util import msg,msg_r
|
|
|
|
-from ....color import nocolor,red,pink,gray
|
|
|
|
-from ....obj import TwComment,CoinTxID,Int
|
|
|
|
|
|
+from ....util import msg, msg_r
|
|
|
|
+from ....color import nocolor, red, pink, gray
|
|
|
|
+from ....obj import TwComment, CoinTxID, Int
|
|
from .rpc import BitcoinTwRPC
|
|
from .rpc import BitcoinTwRPC
|
|
|
|
|
|
class BitcoinTwTransaction:
|
|
class BitcoinTwTransaction:
|
|
|
|
|
|
- def __init__(self,parent,proto,rpc,
|
|
|
|
|
|
+ def __init__(self, parent, proto, rpc,
|
|
idx, # unique numeric identifier of this transaction in listing
|
|
idx, # unique numeric identifier of this transaction in listing
|
|
- unspent_info, # addrs in wallet with balances: { 'mmid': {'addr','comment','amt'} }
|
|
|
|
- mm_map, # all addrs in wallet: ['addr', ['twmmid','comment']]
|
|
|
|
|
|
+ unspent_info, # addrs in wallet with balances: {'mmid': {'addr', 'comment', 'amt'}}
|
|
|
|
+ mm_map, # all addrs in wallet: ['addr', ['twmmid', 'comment']]
|
|
tx, # the decoded transaction data
|
|
tx, # the decoded transaction data
|
|
wallet_vouts, # list of ints - wallet-related vouts
|
|
wallet_vouts, # list of ints - wallet-related vouts
|
|
prevouts, # list of (txid,vout) pairs
|
|
prevouts, # list of (txid,vout) pairs
|
|
@@ -41,21 +41,21 @@ class BitcoinTwTransaction:
|
|
self.tx = tx
|
|
self.tx = tx
|
|
|
|
|
|
def gen_prevouts_data():
|
|
def gen_prevouts_data():
|
|
- _d = namedtuple('prevout_data',['txid','data'])
|
|
|
|
|
|
+ _d = namedtuple('prevout_data', ['txid', 'data'])
|
|
for tx in prevout_txs:
|
|
for tx in prevout_txs:
|
|
for e in prevouts:
|
|
for e in prevouts:
|
|
if e.txid == tx['txid']:
|
|
if e.txid == tx['txid']:
|
|
- yield _d( e.txid, tx['vout'][e.vout] )
|
|
|
|
|
|
+ yield _d(e.txid, tx['vout'][e.vout])
|
|
|
|
|
|
def gen_wallet_vouts_data():
|
|
def gen_wallet_vouts_data():
|
|
- _d = namedtuple('wallet_vout_data',['txid','data'])
|
|
|
|
|
|
+ _d = namedtuple('wallet_vout_data', ['txid', 'data'])
|
|
txid = self.tx['txid']
|
|
txid = self.tx['txid']
|
|
vouts = self.tx['decoded']['vout']
|
|
vouts = self.tx['decoded']['vout']
|
|
for n in wallet_vouts:
|
|
for n in wallet_vouts:
|
|
- yield _d( txid, vouts[n] )
|
|
|
|
|
|
+ yield _d(txid, vouts[n])
|
|
|
|
|
|
def gen_vouts_info(data):
|
|
def gen_vouts_info(data):
|
|
- _d = namedtuple('vout_info',['txid','coin_addr','twlabel','data'])
|
|
|
|
|
|
+ _d = namedtuple('vout_info', ['txid', 'coin_addr', 'twlabel', 'data'])
|
|
def gen():
|
|
def gen():
|
|
for d in data:
|
|
for d in data:
|
|
addr = d.data['scriptPubKey'].get('address') or d.data['scriptPubKey']['addresses'][0]
|
|
addr = d.data['scriptPubKey'].get('address') or d.data['scriptPubKey']['addresses'][0]
|
|
@@ -63,7 +63,7 @@ class BitcoinTwTransaction:
|
|
txid = d.txid,
|
|
txid = d.txid,
|
|
coin_addr = addr,
|
|
coin_addr = addr,
|
|
twlabel = mm_map[addr] if (addr in mm_map and mm_map[addr].twmmid) else None,
|
|
twlabel = mm_map[addr] if (addr in mm_map and mm_map[addr].twmmid) else None,
|
|
- data = d.data )
|
|
|
|
|
|
+ data = d.data)
|
|
return sorted(
|
|
return sorted(
|
|
gen(),
|
|
gen(),
|
|
# if address is not MMGen, ignore address and sort by TxID + vout only
|
|
# if address is not MMGen, ignore address and sort by TxID + vout only
|
|
@@ -79,7 +79,7 @@ class BitcoinTwTransaction:
|
|
if e.twlabel:
|
|
if e.twlabel:
|
|
mmid = e.twlabel.twmmid
|
|
mmid = e.twlabel.twmmid
|
|
yield (
|
|
yield (
|
|
- (mmid if mmid.type == 'mmgen' else mmid.split(':',1)[1]) +
|
|
|
|
|
|
+ (mmid if mmid.type == 'mmgen' else mmid.split(':', 1)[1]) +
|
|
('*' if mmid in self.unspent_info else '')
|
|
('*' if mmid in self.unspent_info else '')
|
|
)
|
|
)
|
|
else:
|
|
else:
|
|
@@ -93,15 +93,15 @@ class BitcoinTwTransaction:
|
|
find the most relevant comment for tabular (squeezed) display
|
|
find the most relevant comment for tabular (squeezed) display
|
|
"""
|
|
"""
|
|
def vouts_labels(src):
|
|
def vouts_labels(src):
|
|
- return [ d.twlabel.comment for d in self.vouts_info[src] if d.twlabel and d.twlabel.comment ]
|
|
|
|
|
|
+ return [d.twlabel.comment for d in self.vouts_info[src] if d.twlabel and d.twlabel.comment]
|
|
ret = vouts_labels('outputs') or vouts_labels('inputs')
|
|
ret = vouts_labels('outputs') or vouts_labels('inputs')
|
|
return ret[0] if ret else TwComment('')
|
|
return ret[0] if ret else TwComment('')
|
|
|
|
|
|
coin_amt = self.proto.coin_amt
|
|
coin_amt = self.proto.coin_amt
|
|
# 'outputs' refers to wallet-related outputs only
|
|
# 'outputs' refers to wallet-related outputs only
|
|
self.vouts_info = {
|
|
self.vouts_info = {
|
|
- 'inputs': gen_vouts_info( gen_prevouts_data() ),
|
|
|
|
- 'outputs': gen_vouts_info( gen_wallet_vouts_data() )
|
|
|
|
|
|
+ 'inputs': gen_vouts_info(gen_prevouts_data()),
|
|
|
|
+ 'outputs': gen_vouts_info(gen_wallet_vouts_data())
|
|
}
|
|
}
|
|
self.max_addrlen = {
|
|
self.max_addrlen = {
|
|
'inputs': max(len(addr) for addr in gen_all_addrs('inputs')),
|
|
'inputs': max(len(addr) for addr in gen_all_addrs('inputs')),
|
|
@@ -123,13 +123,13 @@ class BitcoinTwTransaction:
|
|
self.time = self.tx.get('blocktime') or self.tx['time']
|
|
self.time = self.tx.get('blocktime') or self.tx['time']
|
|
self.time_received = self.tx.get('timereceived')
|
|
self.time_received = self.tx.get('timereceived')
|
|
|
|
|
|
- def blockheight_disp(self,color):
|
|
|
|
|
|
+ def blockheight_disp(self, color):
|
|
return (
|
|
return (
|
|
# old/altcoin daemons return no 'blockheight' field, so use confirmations instead
|
|
# old/altcoin daemons return no 'blockheight' field, so use confirmations instead
|
|
- Int( self.rpc.blockcount + 1 - self.confirmations ).hl(color=color)
|
|
|
|
- if self.confirmations > 0 else None )
|
|
|
|
|
|
+ Int(self.rpc.blockcount + 1 - self.confirmations).hl(color=color)
|
|
|
|
+ if self.confirmations > 0 else None)
|
|
|
|
|
|
- def age_disp(self,age_fmt,width,color):
|
|
|
|
|
|
+ def age_disp(self, age_fmt, width, color):
|
|
if age_fmt == 'confs':
|
|
if age_fmt == 'confs':
|
|
ret_str = str(self.confirmations).ljust(width)
|
|
ret_str = str(self.confirmations).ljust(width)
|
|
return gray(ret_str) if self.confirmations < 0 and color else ret_str
|
|
return gray(ret_str) if self.confirmations < 0 and color else ret_str
|
|
@@ -138,17 +138,17 @@ class BitcoinTwTransaction:
|
|
ret_str = str(ret).ljust(width)
|
|
ret_str = str(ret).ljust(width)
|
|
return gray(ret_str) if ret < 0 and color else ret_str
|
|
return gray(ret_str) if ret < 0 and color else ret_str
|
|
else:
|
|
else:
|
|
- return self.parent.date_formatter[age_fmt](self.rpc,self.tx.get('blocktime',0))
|
|
|
|
|
|
+ return self.parent.date_formatter[age_fmt](self.rpc, self.tx.get('blocktime', 0))
|
|
|
|
|
|
- def txdate_disp(self,age_fmt):
|
|
|
|
- return self.parent.date_formatter[age_fmt](self.rpc,self.time)
|
|
|
|
|
|
+ def txdate_disp(self, age_fmt):
|
|
|
|
+ return self.parent.date_formatter[age_fmt](self.rpc, self.time)
|
|
|
|
|
|
- def txid_disp(self,color,width=None):
|
|
|
|
- return self.txid.hl(color=color) if width is None else self.txid.truncate(width=width,color=color)
|
|
|
|
|
|
+ def txid_disp(self, color, width=None):
|
|
|
|
+ return self.txid.hl(color=color) if width is None else self.txid.truncate(width=width, color=color)
|
|
|
|
|
|
def vouts_list_disp(self, src, color, indent, addr_view_pref):
|
|
def vouts_list_disp(self, src, color, indent, addr_view_pref):
|
|
|
|
|
|
- fs1,fs2 = {
|
|
|
|
|
|
+ fs1, fs2 = {
|
|
'inputs': ('{i},{n} {a} {A}', '{i},{n} {a} {A} {l}'),
|
|
'inputs': ('{i},{n} {a} {A}', '{i},{n} {a} {A} {l}'),
|
|
'outputs': ( '{n} {a} {A}', '{n} {a} {A} {l}')
|
|
'outputs': ( '{n} {a} {A}', '{n} {a} {A} {l}')
|
|
}[src]
|
|
}[src]
|
|
@@ -159,27 +159,27 @@ class BitcoinTwTransaction:
|
|
if not mmid:
|
|
if not mmid:
|
|
yield fs1.format(
|
|
yield fs1.format(
|
|
i = CoinTxID(e.txid).hl(color=color),
|
|
i = CoinTxID(e.txid).hl(color=color),
|
|
- n = (nocolor,red)[color](str(e.data['n']).ljust(3)),
|
|
|
|
|
|
+ n = (nocolor, red)[color](str(e.data['n']).ljust(3)),
|
|
a = CoinAddr(self.proto, e.coin_addr).fmt(
|
|
a = CoinAddr(self.proto, e.coin_addr).fmt(
|
|
addr_view_pref, width=self.max_addrlen[src], color=color),
|
|
addr_view_pref, width=self.max_addrlen[src], color=color),
|
|
- A = self.proto.coin_amt( e.data['value'] ).fmt(color=color)
|
|
|
|
|
|
+ A = self.proto.coin_amt(e.data['value']).fmt(color=color)
|
|
).rstrip()
|
|
).rstrip()
|
|
else:
|
|
else:
|
|
- bal_star,co = ('*','melon') if mmid in self.unspent_info else ('','brown')
|
|
|
|
- addr_out = mmid if mmid.type == 'mmgen' else mmid.split(':',1)[1]
|
|
|
|
|
|
+ bal_star, co = ('*', 'melon') if mmid in self.unspent_info else ('', 'brown')
|
|
|
|
+ addr_out = mmid if mmid.type == 'mmgen' else mmid.split(':', 1)[1]
|
|
yield fs2.format(
|
|
yield fs2.format(
|
|
i = CoinTxID(e.txid).hl(color=color),
|
|
i = CoinTxID(e.txid).hl(color=color),
|
|
- n = (nocolor,red)[color](str(e.data['n']).ljust(3)),
|
|
|
|
|
|
+ n = (nocolor, red)[color](str(e.data['n']).ljust(3)),
|
|
a = TwMMGenID.hl2(
|
|
a = TwMMGenID.hl2(
|
|
TwMMGenID,
|
|
TwMMGenID,
|
|
- s = '{:{w}}'.format( addr_out + bal_star, w=self.max_addrlen[src] ),
|
|
|
|
|
|
+ s = '{:{w}}'.format(addr_out + bal_star, w=self.max_addrlen[src]),
|
|
color = color,
|
|
color = color,
|
|
- color_override = co ),
|
|
|
|
- A = self.proto.coin_amt( e.data['value'] ).fmt(color=color),
|
|
|
|
|
|
+ color_override = co),
|
|
|
|
+ A = self.proto.coin_amt(e.data['value']).fmt(color=color),
|
|
l = e.twlabel.comment.hl(color=color)
|
|
l = e.twlabel.comment.hl(color=color)
|
|
).rstrip()
|
|
).rstrip()
|
|
|
|
|
|
- return f'\n{indent}'.join( gen_output() ).strip()
|
|
|
|
|
|
+ return f'\n{indent}'.join(gen_output()).strip()
|
|
|
|
|
|
def vouts_disp(self, src, width, color, addr_view_pref):
|
|
def vouts_disp(self, src, width, color, addr_view_pref):
|
|
|
|
|
|
@@ -189,7 +189,7 @@ class BitcoinTwTransaction:
|
|
|
|
|
|
for e in self.vouts_info[src]:
|
|
for e in self.vouts_info[src]:
|
|
mmid = e.twlabel.twmmid if e.twlabel else None
|
|
mmid = e.twlabel.twmmid if e.twlabel else None
|
|
- bal_star,addr_w,co = ('*',16,'melon') if mmid in self.unspent_info else ('',15,'brown')
|
|
|
|
|
|
+ bal_star, addr_w, co = ('*', 16, 'melon') if mmid in self.unspent_info else ('', 15, 'brown')
|
|
if not mmid:
|
|
if not mmid:
|
|
if width and space_left < addr_w:
|
|
if width and space_left < addr_w:
|
|
break
|
|
break
|
|
@@ -199,16 +199,16 @@ class BitcoinTwTransaction:
|
|
mmid_disp = mmid + bal_star
|
|
mmid_disp = mmid + bal_star
|
|
if width and space_left < len(mmid_disp):
|
|
if width and space_left < len(mmid_disp):
|
|
break
|
|
break
|
|
- yield TwMMGenID.hl2( TwMMGenID, s=mmid_disp, color=color, color_override=co )
|
|
|
|
|
|
+ yield TwMMGenID.hl2(TwMMGenID, s=mmid_disp, color=color, color_override=co)
|
|
space_left -= len(mmid_disp)
|
|
space_left -= len(mmid_disp)
|
|
else:
|
|
else:
|
|
if width and space_left < addr_w:
|
|
if width and space_left < addr_w:
|
|
break
|
|
break
|
|
yield TwMMGenID.hl2(
|
|
yield TwMMGenID.hl2(
|
|
TwMMGenID,
|
|
TwMMGenID,
|
|
- s = CoinAddr.fmtc( mmid.split(':',1)[1] + bal_star, width=addr_w ),
|
|
|
|
|
|
+ s = CoinAddr.fmtc(mmid.split(':', 1)[1] + bal_star, width=addr_w),
|
|
color = color,
|
|
color = color,
|
|
- color_override = co )
|
|
|
|
|
|
+ color_override = co)
|
|
space_left -= addr_w
|
|
space_left -= addr_w
|
|
space_left -= 1
|
|
space_left -= 1
|
|
|
|
|
|
@@ -216,20 +216,20 @@ class BitcoinTwTransaction:
|
|
|
|
|
|
return ' '.join(gen_output()) + ' ' * (space_left + 1 if width else 0)
|
|
return ' '.join(gen_output()) + ' ' * (space_left + 1 if width else 0)
|
|
|
|
|
|
- def amt_disp(self,show_total_amt):
|
|
|
|
|
|
+ def amt_disp(self, show_total_amt):
|
|
return (
|
|
return (
|
|
self.outputs_total if show_total_amt else
|
|
self.outputs_total if show_total_amt else
|
|
- self.wallet_outputs_total )
|
|
|
|
|
|
+ self.wallet_outputs_total)
|
|
|
|
|
|
- def fee_disp(self,color):
|
|
|
|
|
|
+ def fee_disp(self, color):
|
|
atomic_unit = self.proto.coin_amt.units[0]
|
|
atomic_unit = self.proto.coin_amt.units[0]
|
|
return '{} {}'.format(
|
|
return '{} {}'.format(
|
|
self.fee.hl(color=color),
|
|
self.fee.hl(color=color),
|
|
- (nocolor,pink)[color]('({:,} {}s/byte)'.format(
|
|
|
|
|
|
+ (nocolor, pink)[color]('({:,} {}s/byte)'.format(
|
|
self.fee.to_unit(atomic_unit) // self.vsize,
|
|
self.fee.to_unit(atomic_unit) // self.vsize,
|
|
- atomic_unit )) )
|
|
|
|
|
|
+ atomic_unit)))
|
|
|
|
|
|
-class BitcoinTwTxHistory(TwTxHistory,BitcoinTwRPC):
|
|
|
|
|
|
+class BitcoinTwTxHistory(TwTxHistory, BitcoinTwRPC):
|
|
|
|
|
|
has_age = True
|
|
has_age = True
|
|
hdr_lbl = 'transaction history'
|
|
hdr_lbl = 'transaction history'
|
|
@@ -259,12 +259,12 @@ class BitcoinTwTxHistory(TwTxHistory,BitcoinTwRPC):
|
|
'v':'a_view',
|
|
'v':'a_view',
|
|
'V':'a_view_detail',
|
|
'V':'a_view_detail',
|
|
'p':'a_print_squeezed',
|
|
'p':'a_print_squeezed',
|
|
- 'P':'a_print_detail' }
|
|
|
|
|
|
+ 'P':'a_print_detail'}
|
|
|
|
|
|
async def get_rpc_data(self):
|
|
async def get_rpc_data(self):
|
|
blockhash = (
|
|
blockhash = (
|
|
- await self.rpc.call( 'getblockhash', self.sinceblock )
|
|
|
|
- if self.sinceblock else '' )
|
|
|
|
|
|
+ await self.rpc.call('getblockhash', self.sinceblock)
|
|
|
|
+ if self.sinceblock else '')
|
|
# bitcoin-cli help listsinceblock:
|
|
# bitcoin-cli help listsinceblock:
|
|
# Arguments:
|
|
# Arguments:
|
|
# 1. blockhash (string, optional) If set, the block hash to list transactions since,
|
|
# 1. blockhash (string, optional) If set, the block hash to list transactions since,
|
|
@@ -277,14 +277,14 @@ class BitcoinTwTxHistory(TwTxHistory,BitcoinTwRPC):
|
|
# 4. include_removed (boolean, optional, default=true) Show transactions that were removed
|
|
# 4. include_removed (boolean, optional, default=true) Show transactions that were removed
|
|
# due to a reorg in the "removed" array (not guaranteed to work on
|
|
# due to a reorg in the "removed" array (not guaranteed to work on
|
|
# pruned nodes)
|
|
# pruned nodes)
|
|
- return (await self.rpc.call('listsinceblock',blockhash,1,True,False))['transactions']
|
|
|
|
|
|
+ return (await self.rpc.call('listsinceblock', blockhash, 1, True, False))['transactions']
|
|
|
|
|
|
- async def gen_data(self,rpc_data,lbl_id):
|
|
|
|
|
|
+ async def gen_data(self, rpc_data, lbl_id):
|
|
|
|
|
|
def gen_parsed_data():
|
|
def gen_parsed_data():
|
|
for o in rpc_data:
|
|
for o in rpc_data:
|
|
if lbl_id in o:
|
|
if lbl_id in o:
|
|
- l = get_tw_label(self.proto,o[lbl_id])
|
|
|
|
|
|
+ l = get_tw_label(self.proto, o[lbl_id])
|
|
else:
|
|
else:
|
|
assert o['category'] == 'send', f"{o['address']}: {o['category']} != 'send'"
|
|
assert o['category'] == 'send', f"{o['address']}: {o['category']} != 'send'"
|
|
l = None
|
|
l = None
|
|
@@ -301,18 +301,18 @@ class BitcoinTwTxHistory(TwTxHistory,BitcoinTwRPC):
|
|
from ....rpc import json_encoder
|
|
from ....rpc import json_encoder
|
|
def do_json_dump(*data):
|
|
def do_json_dump(*data):
|
|
nw = f'{self.proto.coin.lower()}-{self.proto.network}'
|
|
nw = f'{self.proto.coin.lower()}-{self.proto.network}'
|
|
- for d,fn_stem in data:
|
|
|
|
- with open(f'/tmp/{fn_stem}-{nw}.json','w') as fh:
|
|
|
|
- fh.write(json.dumps(d,cls=json_encoder))
|
|
|
|
|
|
+ for d, fn_stem in data:
|
|
|
|
+ with open(f'/tmp/{fn_stem}-{nw}.json', 'w') as fh:
|
|
|
|
+ fh.write(json.dumps(d, cls=json_encoder))
|
|
|
|
|
|
- _mmp = namedtuple('mmap_datum',['twmmid','comment'])
|
|
|
|
|
|
+ _mmp = namedtuple('mmap_datum', ['twmmid', 'comment'])
|
|
|
|
|
|
mm_map = {
|
|
mm_map = {
|
|
i['address']: (
|
|
i['address']: (
|
|
- _mmp( TwMMGenID(self.proto,i['twmmid']), TwComment(i['comment']) )
|
|
|
|
- if i['twmmid'] else _mmp(None,None)
|
|
|
|
|
|
+ _mmp(TwMMGenID(self.proto, i['twmmid']), TwComment(i['comment']))
|
|
|
|
+ if i['twmmid'] else _mmp(None, None)
|
|
)
|
|
)
|
|
- for i in data }
|
|
|
|
|
|
+ for i in data}
|
|
|
|
|
|
if self.sinceblock: # mapping data may be incomplete for inputs, so update from 'listlabels'
|
|
if self.sinceblock: # mapping data may be incomplete for inputs, so update from 'listlabels'
|
|
mm_map.update(
|
|
mm_map.update(
|
|
@@ -323,41 +323,41 @@ class BitcoinTwTxHistory(TwTxHistory,BitcoinTwRPC):
|
|
msg_r('Getting wallet transactions...')
|
|
msg_r('Getting wallet transactions...')
|
|
_wallet_txs = await self.rpc.gathered_icall(
|
|
_wallet_txs = await self.rpc.gathered_icall(
|
|
'gettransaction',
|
|
'gettransaction',
|
|
- [ (i,True,True) for i in {d['txid'] for d in data} ] )
|
|
|
|
|
|
+ [(i, True, True) for i in {d['txid'] for d in data}])
|
|
msg('done')
|
|
msg('done')
|
|
|
|
|
|
if not 'decoded' in _wallet_txs[0]:
|
|
if not 'decoded' in _wallet_txs[0]:
|
|
_decoded_txs = iter(
|
|
_decoded_txs = iter(
|
|
await self.rpc.gathered_call(
|
|
await self.rpc.gathered_call(
|
|
'decoderawtransaction',
|
|
'decoderawtransaction',
|
|
- [ (d['hex'],) for d in _wallet_txs ] ))
|
|
|
|
|
|
+ [(d['hex'],) for d in _wallet_txs]))
|
|
for tx in _wallet_txs:
|
|
for tx in _wallet_txs:
|
|
tx['decoded'] = next(_decoded_txs)
|
|
tx['decoded'] = next(_decoded_txs)
|
|
|
|
|
|
if self.cfg.debug_tw:
|
|
if self.cfg.debug_tw:
|
|
do_json_dump((_wallet_txs, 'wallet-txs'),)
|
|
do_json_dump((_wallet_txs, 'wallet-txs'),)
|
|
|
|
|
|
- _wip = namedtuple('prevout',['txid','vout'])
|
|
|
|
|
|
+ _wip = namedtuple('prevout', ['txid', 'vout'])
|
|
txdata = [
|
|
txdata = [
|
|
{
|
|
{
|
|
'tx': tx,
|
|
'tx': tx,
|
|
'wallet_vouts': sorted({i.vout for i in
|
|
'wallet_vouts': sorted({i.vout for i in
|
|
- [_wip( CoinTxID(d['txid']), d['vout'] ) for d in data]
|
|
|
|
|
|
+ [_wip(CoinTxID(d['txid']), d['vout']) for d in data]
|
|
if i.txid == tx['txid']}),
|
|
if i.txid == tx['txid']}),
|
|
- 'prevouts': [_wip( CoinTxID(vin['txid']), vin['vout'] ) for vin in tx['decoded']['vin']]
|
|
|
|
|
|
+ 'prevouts': [_wip(CoinTxID(vin['txid']), vin['vout']) for vin in tx['decoded']['vin']]
|
|
}
|
|
}
|
|
for tx in _wallet_txs]
|
|
for tx in _wallet_txs]
|
|
|
|
|
|
_prevout_txids = {i.txid for d in txdata for i in d['prevouts']}
|
|
_prevout_txids = {i.txid for d in txdata for i in d['prevouts']}
|
|
|
|
|
|
msg_r('Getting input transactions...')
|
|
msg_r('Getting input transactions...')
|
|
- _prevout_txs = await self.rpc.gathered_call('getrawtransaction', [ (i,True) for i in _prevout_txids ])
|
|
|
|
|
|
+ _prevout_txs = await self.rpc.gathered_call('getrawtransaction', [(i, True) for i in _prevout_txids])
|
|
msg('done')
|
|
msg('done')
|
|
|
|
|
|
- _prevout_txs_dict = dict(zip(_prevout_txids,_prevout_txs))
|
|
|
|
|
|
+ _prevout_txs_dict = dict(zip(_prevout_txids, _prevout_txs))
|
|
|
|
|
|
for d in txdata:
|
|
for d in txdata:
|
|
- d['prevout_txs'] = [_prevout_txs_dict[txid] for txid in {i.txid for i in d['prevouts']} ]
|
|
|
|
|
|
+ d['prevout_txs'] = [_prevout_txs_dict[txid] for txid in {i.txid for i in d['prevouts']}]
|
|
|
|
|
|
if self.cfg.debug_tw:
|
|
if self.cfg.debug_tw:
|
|
do_json_dump(
|
|
do_json_dump(
|
|
@@ -378,4 +378,4 @@ class BitcoinTwTxHistory(TwTxHistory,BitcoinTwRPC):
|
|
idx = idx,
|
|
idx = idx,
|
|
unspent_info = unspent_info,
|
|
unspent_info = unspent_info,
|
|
mm_map = mm_map,
|
|
mm_map = mm_map,
|
|
- **d ) for idx,d in enumerate(txdata) )
|
|
|
|
|
|
+ **d) for idx, d in enumerate(txdata))
|