Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
A script to help using ymgve's bitcoin_fork_claimer script
#!/usr/bin/env python
# This script is meant to be used with bitcoin_fork_claimer: https://github.com/ymgve/bitcoin_fork_claimer
# The outputs of this script are the inputs to that script.
# Python 2.x is required
import urllib2
import json
import sys
import collections
# Insert your BTC addresses, one per line
addresses = """
15ZvPgCkTrkKsUzw8PaianK6W7sZQhTMK1
1HTmbaeSZn7faPjxcSeEHJoxgBGMxJYYem
"""
# Forks to check. No need to touch, unless you want to add or remove a fork
fork_list = {
"CLAM": { "name": "Clam", "block": 300377 },
"BCH": { "name": "BCash", "block": 478559 },
"BCD": { "name": "Bitcoin Diamond", "block": 495866 },
"SBTC": { "name": "Super Bitcoin", "block": 498888 },
"BTG": { "name": "Bitcoin Gold", "block": 491407 },
"B2X": { "name": "Segwit2x", "block": 501451 },
"BCX": { "name": "BitcoinX", "block": 498888 },
"BTP": { "name": "BitcoinPay", "block": 499345},
"BTF": { "name": "Bitcoin Faith", "block": 500000 },
"BPA": { "name": "Bitcoin Pizza", "block": 501888},
"BTH": { "name": "Bitcoin Hot", "block": 498848 },
"BTN": { "name": "Bitcoin New", "block": 501000 },
"BTW": { "name": "Bitcoin World", "block": 499777 },
"BTV": { "name": "Bitcoin Vote", "block": 505050 },
"BTT": { "name": "Bitcoin Top", "block": 501118 },
"WBTC": { "name": "World Bitcoin", "block": 503888 },
"BTSQ": { "name": "Bitcoin Community", "block": 506066 },
"BICC": { "name": "BitClassic Coin", "block": 498888 },
"UBTC": { "name": "United Bitcoin", "block": 498777 },
"BTCP": { "name": "Bitcoin Private", "block": 511346 },
"LBTC": { "name": "Lightning Bitcoin", "block": 499999 },
"GOD": { "name": "Bitcoin God", "block": 501226 }
}
desired_forks = {}
def main():
addr_list = addresses.strip().split("\n")
addr_list = [addr.strip() for addr in addr_list]
global desired_forks
desired_forks = get_desired_forks()
if len(desired_forks) == 0:
print "Retrieving all forks..."
print
desired_forks = fork_list
# Add balance entry per fork
for coincode, coindata in desired_forks.viewitems():
coindata["balances"] = {}
for addr in addr_list:
coindata["balances"][addr] = 0
for addr in addr_list:
a = urllib2.urlopen("https://blockchain.info/rawaddr/" + addr).read()
txs = json.loads(a)["txs"]
for coincode, coindata in desired_forks.viewitems():
valid = process_txs(addr, txs, coindata)
for value in valid:
if not coindata.has_key("commands"):
coindata["commands"] = []
coindata["commands"].append(" python claimer.py " + coincode + " " + " ".join(value) + " " + coincode + "_ADDR")
coindata["total_value"] = sum(coindata["balances"].values())
if not "-balance" in sys.argv:
print_commands()
print_balances()
def process_txs(addr, txs, coin):
txs_before_fork = [tx for tx in txs if tx.has_key("block_height") and tx["block_height"] <= coin["block"]]
valid_txs = txs_before_fork[:]
valid = []
# Remove spent transactions
for txid in valid_txs[:]:
for tx in txs_before_fork:
tx_from_mining = tx["vin_sz"] == 1 and not tx["inputs"][0].has_key("prev_out")
if tx_from_mining:
continue
for input_tx in tx["inputs"]:
if input_tx["prev_out"]["tx_index"] == txid["tx_index"] and input_tx["prev_out"]["addr"] == addr:
try:
valid_txs.remove(txid)
except ValueError:
pass # Was probably removed before. Skipping.
for tx in valid_txs:
for tx_out in tx["out"]:
if addr == tx_out["addr"]:
coin["balances"][addr] += tx_out["value"]
valid.append([tx["hash"], "PRIV_KEY_OF_" + addr, addr])
break
return valid
def print_commands():
for coincode, coindata in desired_forks.viewitems():
if coindata.has_key("commands"):
print coindata["name"] + " (" + coincode + ")"
print "\n".join(coindata["commands"])
print
def print_balances():
decimals = 100000000.0
for coincode, coindata in desired_forks.viewitems():
if coindata["total_value"] > 0:
print
coin_fmt = (coindata["name"] + " (" + coincode + ")").ljust(50, " ")
total_fmt = format((coindata["total_value"] / decimals), ".8f")
print coin_fmt + total_fmt.rjust(15, " ") + " BTC"
ordered_addresses = collections.OrderedDict(sorted(coindata["balances"].items(), reverse=True, key=lambda t: t[1]))
for addr, balance in ordered_addresses.viewitems():
if balance > 0:
addr_fmt = addr.ljust(50, " ")
balance_fmt = format((balance / decimals), ".8f")
print addr_fmt + balance_fmt.rjust(15, " ") + " BTC "
def get_cli_args():
if len(sys.argv) == 1:
print "You can also specify which forks you want. Example: python " + sys.argv[0] + " btv bcx"
return None
return [arg.upper() for arg in sys.argv[1:]]
def get_desired_forks():
cli_args = get_cli_args()
if cli_args is None:
return {}
return { k : v for k, v in fork_list.iteritems() if k in cli_args }
main()
@emanuelelaface

This comment has been minimized.

Copy link

emanuelelaface commented Feb 4, 2018

Hi, I did a little change in order to be easier to adapt to the needs of the user. In practice I specify the addresses and the private keys in a comma separated value text file as well as the fork_list adding also the address to send.
I load then the two files with

with open('keys') as f:
    lines = f.read().splitlines()
wallet={}
for line in lines:
    addr, key = line.split(',')
    wallet[addr]=key

with open('fork_list') as f:
    lines = f.read().splitlines()
fork_list={}
for line in lines:
    if line[0] != '#':
        coin, name, block, address = line.split('#')[0].split(',')
        fork_list[coin]={'name': name, 'block': int(block), 'address': address}

and I call the address of the fork as

coindata["commands"].append("python claimer.py " + coincode + " " + " ".join(value) + " " + fork_list[coincode]['address'])

and the private key as

valid.append([tx["hash"], wallet[addr], addr])

Maybe you can add this as an option in your code.

@serevan

This comment has been minimized.

Copy link

serevan commented Mar 22, 2018

Hi, it doesn't work with p2wpkh-p2sh, p2sh private keys

@host2gate

This comment has been minimized.

Copy link

host2gate commented May 16, 2018

claimer.py is not accepting bch addr.
I added BCH fork details to your script.

Getting below error when trying with a BCH dest address

Candidate transaction, index 1 with 107889 Satoshis (0.00107889 BTC)
Traceback (most recent call last):
File "C:\Sundar\BTC\bitcoin_fork_claimer-master\claimer.py", line 1356, in
rawaddr = b58decode(destaddr)
File "C:\Sundar\BTC\bitcoin_fork_claimer-master\claimer.py", line 68, in b58decode
n = n * 58 + b58ab.index(c)
ValueError: substring not found

@P0u1us

This comment has been minimized.

Copy link

P0u1us commented Aug 16, 2018

Hi, very much appreciate the tool, in combination with fork_claimer excellent,
EXCEPT... it is worthy to mention that blockchain API limits the number of TXIDs to 50 !!! and thus the tool does not further show older/remaining TXIDs;
I needed to manually modify and add "?offset=50/100/etc to get all TXIDs ;
just needed to mention this ;-)

@woeisme

This comment has been minimized.

Copy link

woeisme commented Nov 18, 2019

Can you add support for CLAMS?

@ottosch

This comment has been minimized.

Copy link
Owner Author

ottosch commented Nov 20, 2019

Can you add support for CLAMS?

Done.

To all others that commented before, I'm sorry but I didn't see your messages. This is the first time I received an e-mail about someone saying something here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.