7 from .Account import Account
8 from .Transaction import Action, Transaction
9 from .UnspentOutputs import UnspentOutputs
10 from .connection import Connection
12 parser = argparse.ArgumentParser(description='Bytom merge utxo tool')
13 parser.add_argument('-o', '--url', default='http://127.0.0.1:9888', dest='url', help='API url to connect')
14 parser.add_argument('-a', '--account', default=None, dest='account_alias', help='account alias')
15 parser.add_argument('-p', '--pass', default=None, dest='password', help='account password')
16 parser.add_argument('-x', '--max', default=41250000000, type=int, dest='max_amount', help='range lower than max_amount')
17 parser.add_argument('-s', '--min', default=1, type=int, dest='min_amount', help='range higher than min_amount')
18 parser.add_argument('-l', '--list', action='store_true', dest='only_list', help='Show UTXO list without merge')
19 parser.add_argument('-m', '--merge', default=None, type=int, dest='merge_list', help='UTXO to merge')
20 parser.add_argument('-y', '--yes', action='store_true', default=None, dest='confirm', help='confirm transfer')
23 class BytomException(Exception):
27 class JSONRPCException(Exception):
31 def list_utxo(connection, account_alias, min_amount, max_amount):
33 data, ret = UnspentOutputs.list_UTXO(connection=Connection(connection))
34 block_height, ret_code = UnspentOutputs.get_block_height(connection=Connection(connection))
35 if ret == 1 and ret_code == 1:
37 # append mature utxo to set
38 if utxo['valid_height'] < block_height \
39 and utxo['account_alias'] == account_alias \
40 and utxo['asset_alias'] == 'BTM':
41 mature_utxos.append(utxo)
43 raise BytomException(data)
46 for utxo in mature_utxos:
47 if utxo['amount'] <= max_amount and utxo['amount'] >= min_amount:
53 def send_tx(connection, utxo_list, to_address, password):
57 asset_id = 'ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
59 for utxo in utxo_list:
60 actions.append(Action.unspent_output(output_id=utxo['id']))
61 amount += utxo['amount']
64 if amount > gas_amount:
65 amount = amount - gas_amount
67 print('\nAttention: The amount of all utxos is too little, less than tx gas.')
70 actions.append(Action.control_address(amount=amount, asset_id=asset_id, address=to_address))
74 transaction = Transaction.build_transaction(connection, actions)
76 signed_transaction = Transaction.sign_transaction(connection, password, transaction)
78 if signed_transaction['sign_complete']:
79 raw_transaction = signed_transaction['transaction']['raw_transaction']
80 result = Transaction.submit_transaction(connection, raw_transaction)
81 return result['tx_id']
83 raise BytomException('Sign not complete')
87 options = parser.parse_args()
88 utxolist = list_utxo(options.url, options.account_alias, options.min_amount, options.max_amount)
89 for i, utxo in enumerate(utxolist):
90 print('{:4}. {:13.8f} BTM {}{}'.format(i, utxo['amount'] / 1e8, utxo['id'], ' (mature)'))
93 print("total size of available utxos is {}".format(len(utxolist)))
98 merge_size = options.merge_list or input('Merge size of UTXOs (5, 13 or 20): ')
101 for i in range(merge_size if merge_size <= len(utxolist) else len(utxolist)):
102 utxo_mergelist.append(utxolist[i])
104 if len(utxo_mergelist) < 2:
105 print('Not Merge UTXOs, Exit...')
108 print('To merge {} UTXOs with {:13.8f} BTM'.format(len(utxo_mergelist),
109 sum(utxo['amount'] for utxo in utxo_mergelist) / 1e8))
111 if not options.account_alias:
112 options.account_alias = input('Transfer account alias: ')
114 if not options.password:
115 options.password = getpass.getpass('Bytom Account Password: ')
118 'One last disclaimer: the code we are about to go over is in no way intended to be used as an example of a robust solution. ')
119 print('You will transfer BTM to an address, please check this python code and DO IT later.')
121 if not (options.confirm or input('Confirm [y/N] ').lower() == 'y'):
122 print('Not Merge UTXOs, Exit...')
125 to_address = Account.find_address_by_alias(Connection(options.url), options.account_alias)
127 to_address = input('Transfer address: ')
129 print('tx_id:', send_tx(Connection(options.url), utxo_mergelist, to_address, options.password))
132 if __name__ == '__main__':