class Asset(click.ParamType): name = 'asset' def convert(self, value, param, ctx): assert 'asset_tag' not in ctx.params['details']['addressees'][-1] ctx.params['details']['addressees'][-1]['asset_tag'] = value return value # Add asset parameter to sendtoaddress but also check for unsafe usage @green.command() @click.argument('address', type=Address(), expose_value=False) @click.argument('asset', type=Asset(), expose_value=False) @click.argument('amount', type=Amount(precision=8), expose_value=False) @click.option('--subaccount', default=0, expose_value=False, callback=details_json) @with_login @print_result def sendtoaddress(session, details): assets = set([a['asset_tag'] for a in details['addressees']]) precision_risk = _get_network( )['mainnet'] and 'send_all' not in details and assets != {'btc'} if precision_risk and not context.expert: # Disable sendtoaddress for non btc assets with amounts on mainnet # The interface is considered unsafe due to the ambiguity of the amount field. For btc the # amount passed to sendtoaddress is interpreted as btc (satoshi x10^8), however assets may # have different 'precision' specified and it's not currently clear how best to handle that.
@click.pass_context def outputs(ctx, session, show_all, show_change): """Show and modify transaction outputs. With no subcommand shows a summary of the current transaction outputs.""" if ctx.invoked_subcommand: return tx = _load_tx(allow_errors=True) for output in tx['transaction_outputs']: _print_tx_output(options, output) @outputs.command() @click.argument('address', type=Address(), expose_value=False) @click.argument('amount', type=Amount(), expose_value=False) @with_login def add(session, details): """Add a transaction output.""" with Tx(allow_errors=True) as tx: tx.setdefault('addressees', []) send_all = details.get('send_all', False) if send_all: if tx['addressees']: raise click.ClickException( "Cannot add send-all output with other outputs present. " "First remove other outputs with `tx outputs clear`.") tx['send_all'] = True tx['addressees'].extend(details['addressees']) @outputs.command()
@click.option('--count', type=int, default=30, expose_value=False, callback=details_json) @with_login @print_result @gdk_resolve def gettransactions(session, details): return gdk.get_transactions(session.session_obj, json.dumps(details)) @green.command() @click.option('--addressee', '-a', type=(Address(), Amount()), expose_value=False, multiple=True) @click.option('--subaccount', default=0, expose_value=False, callback=details_json) @click.option('--fee-rate', '-f', type=int, expose_value=False, callback=details_json) @with_login @print_result def createtransaction(session, details): """Create an outgoing transaction"""
def getunspentoutputs(session, details): """Get unspent outputs""" return gdk.get_unspent_outputs(session.session_obj, json.dumps(details)) @green.command() @click.option('--subaccount', type=int, default=0, expose_value=False, callback=details_json) @click.option('--first', type=int, default=0, expose_value=False, callback=details_json) @click.option('--count', type=int, default=30, expose_value=False, callback=details_json) @with_login @print_result @gdk_resolve def gettransactions(session, details): return gdk.get_transactions(session.session_obj, json.dumps(details)) @green.command() @click.option('--addressee', '-a', type=(Address(), Amount()), expose_value=False, multiple=True) @click.option('--subaccount', default=0, expose_value=False, callback=details_json) @click.option('--fee-rate', '-f', type=int, expose_value=False, callback=details_json) @with_login @print_result def createtransaction(session, details): """Create an outgoing transaction""" return _gdk_resolve(gdk.create_transaction(session.session_obj, json.dumps(details))) @green.command() @click.argument('details', type=click.File('rb')) @with_login @print_result @gdk_resolve def signtransaction(session, details): """Sign a transaction