Skip to content

Instantly share code, notes, and snippets.

@dexX7
Created April 25, 2014 01:36
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dexX7/11275285 to your computer and use it in GitHub Desktop.
Save dexX7/11275285 to your computer and use it in GitHub Desktop.
Display transactions which send Bitcoin to a specific address
We can make this file beautiful and searchable if this error is corrected: No commas found in this CSV file in line 0.
blocktime;blockheight;position;txid;vout;amount;sender
1398115251;297047;94;70ddc412ccae8c8c1659e71597f3971240b0e03d195799ed83235e2f52a3cf25;0;0.007;13KQXZwHFk3DCqDZG45qqaJzn6uuJPGAZS
1398155998;297117;1;b8ef7515dd6d29243f544766876934216e302e78732f44df9e5fef4cbc0739bc;1;15;186y2sHKTzmTaAvbM543Vqw9zw9dtaneiN
1398155998;297117;18;a165174f5876eb43bf5ef0c6961d99420979fc7919eda9863dea9745ae33fac9;0;118;1DjAmmS6iSg5Xe6wYz37CAMAdvGTQoijiK
1398155998;297117;24;e489cad48a8473f496bbcb17a503118a682804a90a11a06304e9b004d8b66310;0;6.3;1EB6Nm4JmS7mbeJ8Yv7bycbMDvgpWq9uvN
1398155998;297117;36;cf54e2b39f28e2cf12bce49db8de81c32584ab5aab00a14f39f5580eccf65409;0;1;1KJwKxZ4U8PnaoGgGBTBZZ4GkM3ACyL3oq
...
Full data:
http://www.bitwatch.co/msc/1KHfLixa2idRnZXMUfEisBati1vpywaH6E.csv
[{
"sender": "13KQXZwHFk3DCqDZG45qqaJzn6uuJPGAZS",
"vout": 0,
"txid": "70ddc412ccae8c8c1659e71597f3971240b0e03d195799ed83235e2f52a3cf25",
"blocktime": 1398115251,
"amount": 0.007,
"blockheight": 297047,
"position": 94
}, {
"sender": "186y2sHKTzmTaAvbM543Vqw9zw9dtaneiN",
"vout": 1,
"txid": "b8ef7515dd6d29243f544766876934216e302e78732f44df9e5fef4cbc0739bc",
"blocktime": 1398155998,
"amount": 15,
"blockheight": 297117,
"position": 1
}, {
"sender": "1DjAmmS6iSg5Xe6wYz37CAMAdvGTQoijiK",
"vout": 0,
"txid": "a165174f5876eb43bf5ef0c6961d99420979fc7919eda9863dea9745ae33fac9",
"blocktime": 1398155998,
"amount": 118,
"blockheight": 297117,
"position": 18
}, {...
}]
Full data:
http://www.bitwatch.co/msc/1KHfLixa2idRnZXMUfEisBati1vpywaH6E.json
#!/usr/bin/python
import hashlib
import json
import requests
import sys
from bitcoinrpc.authproxy import AuthServiceProxy
from decimal import Decimal
######################################################
#
# this tool can be used to fetch all relevant
# transaction data related to a specific address,
# e.g. show bitcoin nominated maidsafecoin sales
#
# a valid rpc connection to bitcoind is required
#
# rpc options:
# - rpc username and password needs to be set
#
# user options:
# - define the address to look up
# - set output mode: csv or json
# - use rpc call "listtransactions" or
# http://api.bitwatch.co/listtransactions to
# fetch transaction data
#
##
# rpc connection options - action required
##
RPC_USERNAME = 'rpcusername'
RPC_PASSWORD = 'rpcpassword'
RPC_CONNECT = '127.0.0.1'
RPC_PORT = 8332
##
# user options - action required
##
OPT_ADDRESS = '1KHfLixa2idRnZXMUfEisBati1vpywaH6E'
OPT_OUTPUT = 'CSV' # 'JSON'
OPT_MODE = 'API' # 'RPC'
#
######################################################
##
# rpc connection related
##
rpc_client = AuthServiceProxy('http://%s:%s@%s:%s' \
% (RPC_USERNAME, RPC_PASSWORD, RPC_CONNECT, RPC_PORT))
def check_rpc_connection():
try:
test = rpc_client.getinfo()
return True
except:
return False
def get_raw_transaction(txid):
try:
txinfo = rpc_client.getrawtransaction(txid, 1)
return txinfo
except Exception:
print 'could not get raw transaction for '+txid
return None
def get_received_transactions_rpc(address):
received = []
try:
received = rpc_client.listreceivedbyaddress()
except Exception:
print 'could not get received transactions'
return []
for tx_block in received:
if 'address' in tx_block \
and 'txids' in tx_block \
and tx_block['address'] == address:
for txid in tx_block['txids']:
tx = get_raw_transaction(txid)
if tx <> None:
received.append(tx)
return received
##
# web api related
##
def get_all_transactions(address, count = 99999):
response = requests.get('http://api.bitwatch.co/listtransactions/' \
+address+'?verbose=1&count='+str(count)).json()
if 'status' in response and response['status'] == 200:
return response['result']
else:
return []
##
# convert public key to public key hash
##
__b58chars = '123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz'
__b58base = len(__b58chars)
def base58_encode(v):
v = v.decode('hex')
long_value = 0L
for (i, c) in enumerate(v[::-1]):
long_value += (256**i) * ord(c)
result = ''
while long_value >= __b58base:
div, mod = divmod(long_value, __b58base)
result = __b58chars[mod] + result
long_value = div
result = __b58chars[long_value] + result
nPad = 0
for c in v:
if c == '\0':
nPad += 1
else:
break
return (__b58chars[0] * nPad) + result
def get_sha256(string):
return hashlib.sha256(string.decode('hex')).hexdigest()
def get_hash160(string):
h = hashlib.new('ripemd160')
h.update(string.decode('hex'))
return h.hexdigest()
def hash_160_to_bc_address(h160):
vh160 = '00' + h160
h3 = get_sha256(get_sha256(vh160))
checksum = h3[0:8]
addr = vh160 + checksum
b58 = base58_encode(addr)
return b58
def get_pubkeyhash(pubkey):
sha = get_sha256(pubkey)
hash160 = get_hash160(sha)
b58 = hash_160_to_bc_address(hash160)
return b58
##
# core transaction processing
##
def get_transactions_to(tx, address):
outputs = []
amount = 0.0
if 'txid' in tx \
and 'vout' in tx:
for vout in tx['vout']:
if 'value' in vout \
and 'scriptPubKey' in vout \
and 'type' in vout['scriptPubKey'] \
and 'addresses' in vout['scriptPubKey'] \
and vout['scriptPubKey']['type'] == 'pubkeyhash' \
and address in vout['scriptPubKey']['addresses']:
spend = { 'txid': tx['txid'], \
'vout': vout['n'], \
'amount': vout['value'] }
if 'blocktime' in tx:
spend['blocktime'] = tx['blocktime']
if 'blockheight' in tx:
spend['blockheight'] = tx['blockheight']
if 'position' in tx:
spend['position'] = tx['position']
outputs.append(spend)
if len(outputs) > 0:
sender = get_input(tx)
for output in outputs:
output['sender'] = sender
return outputs
def extract_input_pubkey(vin):
if 'scriptSig' in vin \
and 'asm' in vin['scriptSig']:
asm = vin['scriptSig']['asm'].split(' ')
if len(asm) == 2 and asm[0].startswith('304'):
return asm[1]
return None
def extract_highest_input(tx):
pubkey = None
if 'vin' in tx:
for vin in tx['vin']:
pk = extract_input_pubkey(vin)
if pk <> None:
if pubkey is None:
pubkey = pk
if pk <> pubkey:
return None
if pubkey is None:
return None
return get_pubkeyhash(pubkey)
def fetch_output(txid, n):
tx = get_raw_transaction(txid)
if 'vout' in tx \
and len(tx['vout']) >= n:
return tx['vout'][n]
return None
def fetch_input_amount(vin):
if 'txid' in vin \
and 'vout' in vin:
prev_output = fetch_output(vin['txid'], vin['vout'])
if prev_output <> None \
and 'value' in prev_output:
return prev_output['value']
return Decimal()
def get_input(tx):
pubkeyhash = extract_highest_input(tx)
if pubkeyhash <> None:
return pubkeyhash
pubkeys = {}
highest_pubkey = None
highest_amount = Decimal()
if 'vin' in tx:
for vin in tx['vin']:
pk = extract_input_pubkey(vin)
if pk is None:
continue
if not pubkeys.has_key(pk):
pubkeys[pk] = Decimal()
amount = fetch_input_amount(vin)
pubkeys[pk] += amount
if pubkeys[pk] > highest_amount:
highest_amount = pubkeys[pk]
highest_pubkey = pk
if highest_pubkey <> None:
pubkeyhash = get_pubkeyhash(highest_pubkey)
return pubkeyhash
def get_relevant_transactions(address):
if OPT_MODE == 'RPC':
txs = get_received_transactions_rpc(address)
else:
txs = get_all_transactions(address)
all_outputs = []
for tx in txs:
all_outputs += get_transactions_to(tx, address)
return all_outputs
##
# output related
##
def get_relevant_transactions_csv(address):
all_outputs = get_relevant_transactions(address)
for output in all_outputs:
line = ''
if 'blocktime' in output:
line += str(output['blocktime']) + ';'
if 'blockheight' in output:
line += str(output['blockheight']) + ';'
if 'position' in output:
line += str(output['position']) + ';'
if 'txid' in output:
line += str(output['txid']) + ';'
if 'vout' in output:
line += str(output['vout']) + ';'
if 'amount' in output:
line += str(output['amount']) + ';'
if 'sender' in output:
line += str(output['sender'])
print line
def get_relevant_transactions_json(address):
all_outputs = get_relevant_transactions(address)
print json.dumps(all_outputs)
##
# start program
##
if __name__ == '__main__':
if not check_rpc_connection():
print 'rpc connection to bitcoind can not be established'
exit()
if OPT_OUTPUT == 'JSON':
get_relevant_transactions_json(OPT_ADDRESS)
else:
get_relevant_transactions_csv(OPT_ADDRESS)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment