The problem was explained by jdogresorg.
they have basically disabled the armory offline functionality on the counterwallet servers so save time/space/money take your pick!
There is a way to do the tx manually
bitcoin core and counterparty-lib required
# see https://github.com/CounterpartyXCP/counterparty-lib#installation
from counterpartylib.lib import util
from counterpartylib.lib import config
from counterpartylib.lib.backend import addrindex
config.BACKEND_URL = 'http://littleskunk:MySuperSecretPassword@localhost:8332'
config.REQUESTS_TIMEOUT = 30
config.RPC = 'http://littleskunk:MySuperSecretPassword@localhost:8334'
config.BACKEND_SSL_NO_VERIFY = False
def counterparty_api(method, params):
return util.api(method, params)
def bitcoin_api(method, params):
return addrindex.rpc(method, params)
def lowFeeHighDust():
# insert your fee per KB here. 1 KB = 1000 byte.
# use http://bitcoinfees.21.co/ to select one
# if you can wait one week take a look at https://jochen-hoenicke.de/queue/1w.html
# a very low fee has to wait for the next weekend
FEE_PER_KB = 1000
# default min relay fee. Has no effect on bitcoin core conf and is only used for dust calculation.
MIN_RELAY_FEE = 1000
# replace this with the coins you would like to send
asset = 'SJCX'
# list all bitcoin core addresses
wallet = bitcoin_api('listaddressgroupings', [])
# loop through all addresses
for group in wallet:
for address in group:
# get the balance for the asset
balance = counterparty_api('get_balances',
{"filters": [
{"field": "address", "op": "==", "value": address[0]},
{"field": "asset", "op": "==", "value": asset}
],"filterop": "and"})
# add the BTC balance to the result
balance.append({'quantity': int(address[1] * 100000000), 'address': address[0], 'asset': 'BTC'})
#print(balance)
# is there BTC and some assets on that address?
if balance and len(balance) > 1 and balance[0]['quantity'] > 0 and balance[len(balance) - 1]['quantity'] > 0:
# insert your destination address here
# or keep this destination and send me a donation :)
# destination = '1BRrpnXVRTH4Nh6ugQfQ5PcrqAvGCr8QH8'
destination = '1BRrpnXVRTH4Nh6ugQfQ5PcrqAvGCr8QH8'
validateaddress = bitcoin_api('validateaddress', [address[0]])
assert validateaddress['ismine']
pubkey = validateaddress['pubkey']
# create the dummy counterparty transaction for fee and dust calculation. Send all coins to the destination address.
# disable_utxo_locks to be able to overwrite the dummy transaction later.
# start with a fee of only 1 and use everything else as dust. That will give us the maximum transaction size.
unsigned_tx = counterparty_api('create_send',
{'source': address[0],
'destination': destination,
'asset': asset,
'quantity': balance[0]['quantity'],
'pubkey': pubkey,
'fee': 1,
'regular_dust_size': balance[len(balance) - 1]['quantity'] - 1,
'disable_utxo_locks': True,
'allow_unconfirmed_inputs': True})
# lets get the transaction size to calculate the fee
bitcoin_api('walletpassphrase', ['MySuperSecretPassword', 60])
signed_tx = bitcoin_api('signrawtransaction', [unsigned_tx])['hex']
tx_info = bitcoin_api('decoderawtransaction', [signed_tx])
# use round to get as close as possible to the target fee per KB
# use int + 1 to get a minimum fee per KB
# FEE = int(tx_info['size'] * FEE_PER_KB / 1000) + 1
FEE = round(tx_info['size'] * FEE_PER_KB / 1000)
# lets increase the dust size to send all BTC and SJCX in one transaction
# dust size = btc balance - fee
regular_dust_size = balance[len(balance) - 1]['quantity'] - FEE
# Now we can start to create the final transaction
unsigned_tx = counterparty_api('create_send',
{'source': address[0],
'destination': destination,
'asset': asset,
'quantity': balance[0]['quantity'],
'pubkey': pubkey,
'fee': FEE,
'regular_dust_size': regular_dust_size,
'disable_utxo_locks': True,
'allow_unconfirmed_inputs': True})
# unlock the bitcoin core wallet and sign the transaction
bitcoin_api('walletpassphrase', ['MySuperSecretPassword', 60])
signed_tx = bitcoin_api('signrawtransaction', [unsigned_tx])['hex']
# the fee is to low for bitcoin core. Increase the priority or bitcoin core will refuse to relay it
tx_info = bitcoin_api('decoderawtransaction', [signed_tx])
bitcoin_api('prioritisetransaction', [tx_info['txid'], 0.0, 10000000])
# print out the final transaction
tx_info = counterparty_api('get_tx_info', {'tx_hex': unsigned_tx})
print(tx_info)
# point of no return publish the transaction and print out the txid
# as long as you don't execute this you can play with the script
# tx_hash = bitcoin_api('sendrawtransaction', [signed_tx])
# print('txid: ' + tx_hash)
def lowFeeLowDust():
# insert your fee per KB here. 1 KB = 1000 byte.
# use http://bitcoinfees.21.co/ to select one
# if you can wait one week take a look at https://jochen-hoenicke.de/queue/1w.html
# a very low fee has to wait for the next weekend
FEE_PER_KB = 1000
# default min relay fee. Has no effect on bitcoin core conf and is only used for dust calculation.
MIN_RELAY_FEE = 1000
# replace this with the coins you would like to send
asset = 'SJCX'
# list all bitcoin core addresses
wallet = bitcoin_api('listaddressgroupings', [])
# loop through all addresses
for group in wallet:
for address in group:
# get the balance for the asset
balance = counterparty_api('get_balances',
{"filters": [
{"field": "address", "op": "==", "value": address[0]},
{"field": "asset", "op": "==", "value": asset}
],"filterop": "and"})
# add the BTC balance to the result
balance.append({'quantity': int(address[1] * 100000000), 'address': address[0], 'asset': 'BTC'})
#print(balance)
# is there BTC and some assets on that address?
if balance and len(balance) > 1 and balance[0]['quantity'] > 0 and balance[len(balance) - 1]['quantity'] > 0:
# insert your destination address here
# or keep this destination and send me a donation :)
# destination = '1BRrpnXVRTH4Nh6ugQfQ5PcrqAvGCr8QH8'
destination = '1BRrpnXVRTH4Nh6ugQfQ5PcrqAvGCr8QH8'
validateaddress = bitcoin_api('validateaddress', [address[0]])
assert validateaddress['ismine']
pubkey = validateaddress['pubkey']
# create the dummy counterparty transaction for fee and dust calculation. Send all coins to the destination address.
# disable_utxo_locks to be able to overwrite the dummy transaction later.
# start with a fee and dust of only 1. That will give us the transaction size.
unsigned_tx = counterparty_api('create_send',
{'source': address[0],
'destination': destination,
'asset': asset,
'quantity': balance[0]['quantity'],
'pubkey': pubkey,
'fee': 1,
'regular_dust_size': 1,
'disable_utxo_locks': True,
'allow_unconfirmed_inputs': True})
# lets get the transaction size to calculate the fee
bitcoin_api('walletpassphrase', ['MySuperSecretPassword', 60])
signed_tx = bitcoin_api('signrawtransaction', [unsigned_tx])['hex']
tx_info = bitcoin_api('decoderawtransaction', [signed_tx])
# use round to get as close as possible to the target fee per KB
# use int + 1 to get a minimum fee per KB
# FEE = int(tx_info['size'] * FEE_PER_KB / 1000) + 1
FEE = round(tx_info['size'] * FEE_PER_KB / 1000)
# minimum dust size is 3 times min relay fee (default relay fee is 1 per Byte)
# minimum dust size should be per KB as well but counterparty is using a fixed dust size for some reason
# lets calculate the correct dust size
regular_dust_size = int(tx_info['size'] * 3 * MIN_RELAY_FEE / 1000) + 1
# Now we can start to create the final transaction
unsigned_tx = counterparty_api('create_send',
{'source': address[0],
'destination': destination,
'asset': asset,
'quantity': balance[0]['quantity'],
'pubkey': pubkey,
'fee': FEE,
'regular_dust_size': regular_dust_size,
'disable_utxo_locks': True,
'allow_unconfirmed_inputs': True})
# unlock the bitcoin core wallet and sign the transaction
bitcoin_api('walletpassphrase', ['MySuperSecretPassword', 60])
signed_tx = bitcoin_api('signrawtransaction', [unsigned_tx])['hex']
# the fee is to low for bitcoin core. Increase the priority or bitcoin core will refuse to relay it
tx_info = bitcoin_api('decoderawtransaction', [signed_tx])
bitcoin_api('prioritisetransaction', [tx_info['txid'], 0.0, 10000000])
# print out the final transaction
tx_info = counterparty_api('get_tx_info', {'tx_hex': unsigned_tx})
print(tx_info)
# point of no return publish the transaction and print out the txid
# as long as you don't execute this you can play with the script
# tx_hash = bitcoin_api('sendrawtransaction', [signed_tx])
# print('txid: ' + tx_hash)
print("Start")
lowFeeHighDust()
print("End")
To be honest it would be nice if the counterwallet server operators could just re-enable this feature as it is obvious some of us used this feature for long term storage / security and just when you want to use it…it’s gone!!
I do not have the time to build a server just to move some coins. I will either have to pay someone to do this for me or deal with it if the coins become worth the effort involved to spare the time.
I hope someone can find an easy solution to this before my coins loose their value…