Example #1
0
def main():
    if os.name == 'nt':
        from counterpartylib.lib import util_windows
        #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging
        util_windows.fix_win32_unicode()

    # Post installation tasks
    generate_config_files()

    # Parse command-line arguments.
    parser = argparse.ArgumentParser(
        prog=APP_NAME,
        description='Counterparty CLI for counterparty-server',
        add_help=False)
    parser.add_argument('-h',
                        '--help',
                        dest='help',
                        action='store_true',
                        help='show this help message and exit')
    parser.add_argument('-V',
                        '--version',
                        action='version',
                        version="{} v{}; {} v{}".format(
                            APP_NAME, APP_VERSION, 'counterparty-lib',
                            config.VERSION_STRING))
    parser.add_argument('--config-file',
                        help='the location of the configuration file')

    parser = add_config_arguments(parser, CONFIG_ARGS, 'client.conf')

    subparsers = parser.add_subparsers(dest='action',
                                       help='the action to be taken')

    parser_send = subparsers.add_parser(
        'send', help='create and broadcast a *send* message')
    parser_send.add_argument('--source',
                             required=True,
                             help='the source address')
    parser_send.add_argument('--destination',
                             required=True,
                             help='the destination address')
    parser_send.add_argument('--quantity',
                             required=True,
                             help='the quantity of ASSET to send')
    parser_send.add_argument(
        '--asset',
        required=True,
        help='the ASSET of which you would like to send QUANTITY')
    parser_send.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_order = subparsers.add_parser(
        'order', help='create and broadcast an *order* message')
    parser_order.add_argument('--source',
                              required=True,
                              help='the source address')
    parser_order.add_argument(
        '--get-quantity',
        required=True,
        help='the quantity of GET_ASSET that you would like to receive')
    parser_order.add_argument('--get-asset',
                              required=True,
                              help='the asset that you would like to buy')
    parser_order.add_argument(
        '--give-quantity',
        required=True,
        help='the quantity of GIVE_ASSET that you are willing to give')
    parser_order.add_argument('--give-asset',
                              required=True,
                              help='the asset that you would like to sell')
    parser_order.add_argument(
        '--expiration',
        type=int,
        required=True,
        help='the number of blocks for which the order should be valid')
    parser_order.add_argument(
        '--fee-fraction-required',
        default=config.DEFAULT_FEE_FRACTION_REQUIRED,
        help=
        'the miners’ fee required for an order to match this one, as a fraction of the {} to be bought'
        .format(config.BTC))
    parser_order_fees = parser_order.add_mutually_exclusive_group()
    parser_order_fees.add_argument(
        '--fee-fraction-provided',
        default=config.DEFAULT_FEE_FRACTION_PROVIDED,
        help='the miners’ fee provided, as a fraction of the {} to be sold'.
        format(config.BTC))
    parser_order_fees.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_btcpay = subparsers.add_parser(
        '{}pay'.format(config.BTC).lower(),
        help=
        'create and broadcast a *{}pay* message, to settle an Order Match for which you owe {}'
        .format(config.BTC, config.BTC))
    parser_btcpay.add_argument('--source',
                               required=True,
                               help='the source address')
    parser_btcpay.add_argument(
        '--order-match-id',
        required=True,
        help=
        'the concatenation of the hashes of the two transactions which compose the order match'
    )
    parser_btcpay.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_issuance = subparsers.add_parser(
        'issuance',
        help=
        'issue a new asset, issue more of an existing asset or transfer the ownership of an asset'
    )
    parser_issuance.add_argument('--source',
                                 required=True,
                                 help='the source address')
    parser_issuance.add_argument(
        '--transfer-destination',
        help='for transfer of ownership of asset issuance rights')
    parser_issuance.add_argument('--quantity',
                                 default=0,
                                 help='the quantity of ASSET to be issued')
    parser_issuance.add_argument(
        '--asset',
        required=True,
        help='the name of the asset to be issued (if it’s available)')
    parser_issuance.add_argument(
        '--divisible',
        action='store_true',
        help=
        'whether or not the asset is divisible (must agree with previous issuances)'
    )
    parser_issuance.add_argument(
        '--description',
        type=str,
        required=True,
        help=
        'a description of the asset (set to ‘LOCK’ to lock against further issuances with non‐zero quantitys)'
    )
    parser_issuance.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_broadcast = subparsers.add_parser(
        'broadcast',
        help='broadcast textual and numerical information to the network')
    parser_broadcast.add_argument('--source',
                                  required=True,
                                  help='the source address')
    parser_broadcast.add_argument(
        '--text',
        type=str,
        required=True,
        help='the textual part of the broadcast (set to ‘LOCK’ to lock feed)')
    parser_broadcast.add_argument('--value',
                                  type=float,
                                  default=-1,
                                  help='numerical value of the broadcast')
    parser_broadcast.add_argument(
        '--fee-fraction',
        default=0,
        help='the fraction of bets on this feed that go to its operator')
    parser_broadcast.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_bet = subparsers.add_parser(
        'bet', help='offer to make a bet on the value of a feed')
    parser_bet.add_argument('--source',
                            required=True,
                            help='the source address')
    parser_bet.add_argument(
        '--feed-address',
        required=True,
        help='the address which publishes the feed to bet on')
    parser_bet.add_argument('--bet-type',
                            choices=list(BET_TYPE_NAME.values()),
                            required=True,
                            help='choices: {}'.format(
                                list(BET_TYPE_NAME.values())))
    parser_bet.add_argument(
        '--deadline',
        required=True,
        help='the date and time at which the bet should be decided/settled')
    parser_bet.add_argument('--wager',
                            required=True,
                            help='the quantity of XCP to wager')
    parser_bet.add_argument(
        '--counterwager',
        required=True,
        help=
        'the minimum quantity of XCP to be wagered by the user to bet against you, if he were to accept the whole thing'
    )
    parser_bet.add_argument('--target-value',
                            default=0.0,
                            help='target value for Equal/NotEqual bet')
    parser_bet.add_argument('--leverage',
                            type=int,
                            default=5040,
                            help='leverage, as a fraction of 5040')
    parser_bet.add_argument(
        '--expiration',
        type=int,
        required=True,
        help='the number of blocks for which the bet should be valid')
    parser_bet.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_dividend = subparsers.add_parser(
        'dividend',
        help=
        'pay dividends to the holders of an asset (in proportion to their stake in it)'
    )
    parser_dividend.add_argument('--source',
                                 required=True,
                                 help='the source address')
    parser_dividend.add_argument(
        '--quantity-per-unit',
        required=True,
        help='the quantity of XCP to be paid per whole unit held of ASSET')
    parser_dividend.add_argument('--asset',
                                 required=True,
                                 help='the asset to which pay dividends')
    parser_dividend.add_argument('--dividend-asset',
                                 required=True,
                                 help='asset in which to pay the dividends')
    parser_dividend.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_burn = subparsers.add_parser(
        'burn',
        help='destroy {} to earn XCP, during an initial period of time')
    parser_burn.add_argument('--source',
                             required=True,
                             help='the source address')
    parser_burn.add_argument('--quantity',
                             required=True,
                             help='quantity of {} to be burned'.format(
                                 config.BTC))
    parser_burn.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_cancel = subparsers.add_parser(
        'cancel', help='cancel an open order or bet you created')
    parser_cancel.add_argument('--source',
                               required=True,
                               help='the source address')
    parser_cancel.add_argument('--offer-hash',
                               required=True,
                               help='the transaction hash of the order or bet')
    parser_cancel.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_rps = subparsers.add_parser(
        'rps', help='open a rock-paper-scissors like game')
    parser_rps.add_argument('--source',
                            required=True,
                            help='the source address')
    parser_rps.add_argument('--wager',
                            required=True,
                            help='the quantity of XCP to wager')
    parser_rps.add_argument('--move',
                            type=int,
                            required=True,
                            help='the selected move')
    parser_rps.add_argument(
        '--possible-moves',
        type=int,
        required=True,
        help='the number of possible moves (odd number greater or equal than 3)'
    )
    parser_rps.add_argument(
        '--expiration',
        type=int,
        required=True,
        help='the number of blocks for which the bet should be valid')
    parser_rps.add_argument('--fee',
                            help='the exact BTC fee to be paid to miners')

    parser_rpsresolve = subparsers.add_parser(
        'rpsresolve', help='resolve a rock-paper-scissors like game')
    parser_rpsresolve.add_argument('--source',
                                   required=True,
                                   help='the source address')
    parser_rpsresolve.add_argument(
        '--random',
        type=str,
        required=True,
        help='the random number used in the corresponding rps transaction')
    parser_rpsresolve.add_argument(
        '--move',
        type=int,
        required=True,
        help='the selected move in the corresponding rps transaction')
    parser_rpsresolve.add_argument(
        '--rps-match-id',
        required=True,
        help=
        'the concatenation of the hashes of the two transactions which compose the rps match'
    )
    parser_rpsresolve.add_argument(
        '--fee', help='the exact BTC fee to be paid to miners')

    parser_publish = subparsers.add_parser(
        'publish', help='publish contract code in the blockchain')
    parser_publish.add_argument('--source',
                                required=True,
                                help='the source address')
    parser_publish.add_argument('--gasprice',
                                required=True,
                                type=int,
                                help='the price of gas')
    parser_publish.add_argument(
        '--startgas',
        required=True,
        type=int,
        help=
        'the maximum quantity of {} to be used to pay for the execution (satoshis)'
        .format(config.XCP))
    parser_publish.add_argument(
        '--endowment',
        required=True,
        type=int,
        help='quantity of {} to be transfered to the contract (satoshis)'.
        format(config.XCP))
    parser_publish.add_argument(
        '--code-hex',
        required=True,
        type=str,
        help='the hex‐encoded contract (returned by `serpent compile`)')
    parser_publish.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_execute = subparsers.add_parser(
        'execute', help='execute contract code in the blockchain')
    parser_execute.add_argument('--source',
                                required=True,
                                help='the source address')
    parser_execute.add_argument(
        '--contract-id',
        required=True,
        help='the contract ID of the contract to be executed')
    parser_execute.add_argument('--gasprice',
                                required=True,
                                type=int,
                                help='the price of gas')
    parser_execute.add_argument(
        '--startgas',
        required=True,
        type=int,
        help=
        'the maximum quantity of {} to be used to pay for the execution (satoshis)'
        .format(config.XCP))
    parser_execute.add_argument(
        '--value',
        required=True,
        type=int,
        help='quantity of {} to be transfered to the contract (satoshis)'.
        format(config.XCP))
    parser_execute.add_argument(
        '--payload-hex',
        required=True,
        type=str,
        help=
        'data to be provided to the contract (returned by `serpent encode_datalist`)'
    )
    parser_execute.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_destroy = subparsers.add_parser(
        'destroy', help='destroy a quantity of a Counterparty asset')
    parser_destroy.add_argument('--source',
                                required=True,
                                help='the source address')
    parser_destroy.add_argument(
        '--asset',
        required=True,
        help='the ASSET of which you would like to destroy QUANTITY')
    parser_destroy.add_argument('--quantity',
                                required=True,
                                help='the quantity of ASSET to destroy')
    parser_destroy.add_argument('--tag', default='', help='tag')
    parser_destroy.add_argument(
        '--fee',
        help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_address = subparsers.add_parser(
        'balances',
        help='display the balances of a {} address'.format(config.XCP_NAME))
    parser_address.add_argument('address',
                                help='the address you are interested in')

    parser_asset = subparsers.add_parser(
        'asset',
        help='display the basic properties of a {} asset'.format(
            config.XCP_NAME))
    parser_asset.add_argument('asset', help='the asset you are interested in')

    parser_wallet = subparsers.add_parser(
        'wallet',
        help=
        'list the addresses in your backend wallet along with their balances in all {} assets'
        .format(config.XCP_NAME))

    parser_pending = subparsers.add_parser(
        'pending',
        help='list pending order matches awaiting {}payment from you'.format(
            config.BTC))

    parser_getrows = subparsers.add_parser(
        'getrows', help='get rows from a Counterparty table')
    parser_getrows.add_argument('--table', required=True, help='table name')
    parser_getrows.add_argument('--filter',
                                nargs=3,
                                action='append',
                                help='filters to get specific rows')
    parser_getrows.add_argument('--filter-op',
                                choices=['AND', 'OR'],
                                help='operator uses to combine filters',
                                default='AND')
    parser_getrows.add_argument('--order-by',
                                help='field used to order results')
    parser_getrows.add_argument('--order-dir',
                                choices=['ASC', 'DESC'],
                                help='direction used to order results')
    parser_getrows.add_argument(
        '--start-block',
        help='return only rows with block_index greater than start-block')
    parser_getrows.add_argument(
        '--end-block',
        help='return only rows with block_index lower than end-block')
    parser_getrows.add_argument(
        '--status', help='return only rows with the specified status')
    parser_getrows.add_argument('--limit',
                                help='number of rows to return',
                                default=100)
    parser_getrows.add_argument('--offset',
                                help='number of rows to skip',
                                default=0)

    parser_getrunninginfo = subparsers.add_parser(
        'getinfo', help='get the current state of the server')

    args = parser.parse_args()

    # Logging
    log.set_up(logger, verbose=args.verbose)
    logger.propagate = False

    logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME))

    # Help message
    if args.help:
        parser.print_help()
        sys.exit()

    # Configuration
    clientapi.initialize(
        testnet=args.testnet,
        testcoin=args.testcoin,
        counterparty_rpc_connect=args.counterparty_rpc_connect,
        counterparty_rpc_port=args.counterparty_rpc_port,
        counterparty_rpc_user=args.counterparty_rpc_user,
        counterparty_rpc_password=args.counterparty_rpc_password,
        counterparty_rpc_ssl=args.counterparty_rpc_ssl,
        counterparty_rpc_ssl_verify=args.counterparty_rpc_ssl_verify,
        wallet_name=args.wallet_name,
        wallet_connect=args.wallet_connect,
        wallet_port=args.wallet_port,
        wallet_user=args.wallet_user,
        wallet_password=args.wallet_password,
        wallet_ssl=args.wallet_ssl,
        wallet_ssl_verify=args.wallet_ssl_verify,
        requests_timeout=args.requests_timeout)

    # MESSAGE CREATION
    if args.action in list(messages.MESSAGE_PARAMS.keys()):
        unsigned_hex = messages.compose(args.action, args)
        logger.info('Transaction (unsigned): {}'.format(unsigned_hex))
        if not args.unsigned:
            if script.is_multisig(args.source):
                logger.info(
                    'Multi‐signature transactions are signed and broadcasted manually.'
                )

            elif input('Sign and broadcast? (y/N) ') == 'y':

                if wallet.is_mine(args.source):
                    if wallet.is_locked():
                        passphrase = getpass.getpass(
                            'Enter your wallet passhrase: ')
                        logger.info('Unlocking wallet for 60 (more) seconds.')
                        wallet.unlock(passphrase)
                    signed_tx_hex = wallet.sign_raw_transaction(unsigned_hex)
                else:
                    private_key_wif = input(
                        'Source address not in wallet. Please enter the private key in WIF format for {}:'
                        .format(args.source))
                    if not private_key_wif:
                        raise TransactionError('invalid private key')
                    signed_tx_hex = wallet.sign_raw_transaction(
                        unsigned_hex, private_key_wif=private_key_wif)

                logger.info('Transaction (signed): {}'.format(signed_tx_hex))
                tx_hash = wallet.send_raw_transaction(signed_tx_hex)
                logger.info(
                    'Hash of transaction (broadcasted): {}'.format(tx_hash))

    # VIEWING
    elif args.action in [
            'balances', 'asset', 'wallet', 'pending', 'getinfo', 'getrows'
    ]:
        view = console.get_view(args.action, args)
        print_method = getattr(console, 'print_{}'.format(args.action), None)
        if args.json_output or print_method is None:
            util.json_print(view)
        else:
            print_method(view)

    else:
        parser.print_help()
def main():
    if os.name == 'nt':
        from counterpartylib.lib import util_windows
        #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging
        util_windows.fix_win32_unicode()

    # Post installation tasks
    generate_config_files()

    # Parse command-line arguments.
    parser = argparse.ArgumentParser(prog=APP_NAME, description='Server for the {} protocol'.format(config.XCP_NAME), add_help=False)
    parser.add_argument('-h', '--help', dest='help', action='store_true', help='show this help message and exit')
    parser.add_argument('-V', '--version', action='version', version="{} v{}; {} v{}".format(APP_NAME, APP_VERSION, 'counterparty-lib', config.VERSION_STRING))
    parser.add_argument('--config-file', help='the path to the configuration file')

    parser = add_config_arguments(parser, CONFIG_ARGS, 'server.conf')

    subparsers = parser.add_subparsers(dest='action', help='the action to be taken')

    parser_server = subparsers.add_parser('start', help='run the server')

    parser_reparse = subparsers.add_parser('reparse', help='reparse all transactions in the database')
   
    parser_rollback = subparsers.add_parser('rollback', help='rollback database')
    parser_rollback.add_argument('block_index', type=int, help='the index of the last known good block')
    
    parser_kickstart = subparsers.add_parser('kickstart', help='rapidly build database by reading from Bitcoin Core blockchain')
    parser_kickstart.add_argument('--bitcoind-dir', help='Bitcoin Core data directory')

    parser_bootstrap = subparsers.add_parser('bootstrap', help='bootstrap database with hosted snapshot')

    args = parser.parse_args()

    log.set_up(logger, verbose=args.verbose)
    
    logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME))

    # Help message
    if args.help:
        parser.print_help()
        sys.exit()

    # Bootstrapping
    if args.action == 'bootstrap':
        bootstrap(testnet=args.testnet)
        sys.exit()

    # Configuration
    if args.action in ['reparse', 'rollback', 'kickstart', 'start']:
        try:
            db = server.initialise(database_file=args.database_file,
                                log_file=args.log_file, api_log_file=args.api_log_file,
                                testnet=args.testnet, testcoin=args.testcoin,
                                backend_name=args.backend_name,
                                backend_connect=args.backend_connect,
                                backend_port=args.backend_port,
                                backend_user=args.backend_user,
                                backend_password=args.backend_password,
                                backend_ssl=args.backend_ssl,
                                backend_ssl_no_verify=args.backend_ssl_no_verify,
                                backend_poll_interval=args.backend_poll_interval,
                                rpc_host=args.rpc_host, rpc_port=args.rpc_port, rpc_user=args.rpc_user,
                                rpc_password=args.rpc_password, rpc_no_allow_cors=args.rpc_no_allow_cors,
                                requests_timeout=args.requests_timeout,
                                rpc_batch_size=args.rpc_batch_size,
                                check_asset_conservation=not args.no_check_asset_conservation,
                                force=args.force, verbose=args.verbose)
                                #,broadcast_tx_mainnet=args.broadcast_tx_mainnet)
        except TypeError as e:
            if 'unexpected keyword argument' in str(e):
                raise VersionError('Unsupported Server Parameter. CLI/Library Version Incompatibility.')
            else:
                raise e

    # PARSING
    if args.action == 'reparse':
        server.reparse(db)

    elif args.action == 'rollback':
        server.reparse(db, block_index=args.block_index)

    elif args.action == 'kickstart':
        server.kickstart(db, bitcoind_dir=args.bitcoind_dir)

    elif args.action == 'start':
        server.start_all(db)

    else:
        parser.print_help()
Example #3
0
def main():
    if os.name == 'nt':
        from counterpartylib.lib import util_windows
        #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging
        util_windows.fix_win32_unicode()

    # Post installation tasks
    generate_config_files()

    # Parse command-line arguments.
    parser = argparse.ArgumentParser(prog=APP_NAME, description='Counterparty CLI for counterparty-server', add_help=False)
    parser.add_argument('-h', '--help', dest='help', action='store_true', help='show this help message and exit')
    parser.add_argument('-V', '--version', action='version', version="{} v{}; {} v{}".format(APP_NAME, APP_VERSION, 'counterparty-lib', config.VERSION_STRING))
    parser.add_argument('--config-file', help='the location of the configuration file')

    parser = add_config_arguments(parser, CONFIG_ARGS, 'client.conf')

    subparsers = parser.add_subparsers(dest='action', help='the action to be taken')

    parser_send = subparsers.add_parser('send', help='create and broadcast a *send* message')
    parser_send.add_argument('--source', required=True, help='the source address')
    parser_send.add_argument('--destination', required=True, help='the destination address')
    parser_send.add_argument('--quantity', required=True, help='the quantity of ASSET to send')
    parser_send.add_argument('--asset', required=True, help='the ASSET of which you would like to send QUANTITY')
    parser_send.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_order = subparsers.add_parser('order', help='create and broadcast an *order* message')
    parser_order.add_argument('--source', required=True, help='the source address')
    parser_order.add_argument('--get-quantity', required=True, help='the quantity of GET_ASSET that you would like to receive')
    parser_order.add_argument('--get-asset', required=True, help='the asset that you would like to buy')
    parser_order.add_argument('--give-quantity', required=True, help='the quantity of GIVE_ASSET that you are willing to give')
    parser_order.add_argument('--give-asset', required=True, help='the asset that you would like to sell')
    parser_order.add_argument('--expiration', type=int, required=True, help='the number of blocks for which the order should be valid')
    parser_order.add_argument('--fee-fraction-required', default=config.DEFAULT_FEE_FRACTION_REQUIRED, help='the miners’ fee required for an order to match this one, as a fraction of the {} to be bought'.format(config.BTC))
    parser_order_fees = parser_order.add_mutually_exclusive_group()
    parser_order_fees.add_argument('--fee-fraction-provided', default=config.DEFAULT_FEE_FRACTION_PROVIDED, help='the miners’ fee provided, as a fraction of the {} to be sold'.format(config.BTC))
    parser_order_fees.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_btcpay = subparsers.add_parser('{}pay'.format(config.BTC).lower(), help='create and broadcast a *{}pay* message, to settle an Order Match for which you owe {}'.format(config.BTC, config.BTC))
    parser_btcpay.add_argument('--source', required=True, help='the source address')
    parser_btcpay.add_argument('--order-match-id', required=True, help='the concatenation of the hashes of the two transactions which compose the order match')
    parser_btcpay.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_issuance = subparsers.add_parser('issuance', help='issue a new asset, issue more of an existing asset or transfer the ownership of an asset')
    parser_issuance.add_argument('--source', required=True, help='the source address')
    parser_issuance.add_argument('--transfer-destination', help='for transfer of ownership of asset issuance rights')
    parser_issuance.add_argument('--quantity', default=0, help='the quantity of ASSET to be issued')
    parser_issuance.add_argument('--asset', required=True, help='the name of the asset to be issued (if it’s available)')
    parser_issuance.add_argument('--divisible', action='store_true', help='whether or not the asset is divisible (must agree with previous issuances)')
    parser_issuance.add_argument('--description', type=str, required=True, help='a description of the asset (set to ‘LOCK’ to lock against further issuances with non‐zero quantitys)')
    parser_issuance.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_broadcast = subparsers.add_parser('broadcast', help='broadcast textual and numerical information to the network')
    parser_broadcast.add_argument('--source', required=True, help='the source address')
    parser_broadcast.add_argument('--text', type=str, required=True, help='the textual part of the broadcast (set to ‘LOCK’ to lock feed)')
    parser_broadcast.add_argument('--value', type=float, default=-1, help='numerical value of the broadcast')
    parser_broadcast.add_argument('--fee-fraction', default=0, help='the fraction of bets on this feed that go to its operator')
    parser_broadcast.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_bet = subparsers.add_parser('bet', help='offer to make a bet on the value of a feed')
    parser_bet.add_argument('--source', required=True, help='the source address')
    parser_bet.add_argument('--feed-address', required=True, help='the address which publishes the feed to bet on')
    parser_bet.add_argument('--bet-type', choices=list(BET_TYPE_NAME.values()), required=True, help='choices: {}'.format(list(BET_TYPE_NAME.values())))
    parser_bet.add_argument('--deadline', required=True, help='the date and time at which the bet should be decided/settled')
    parser_bet.add_argument('--wager', required=True, help='the quantity of XCP to wager')
    parser_bet.add_argument('--counterwager', required=True, help='the minimum quantity of XCP to be wagered by the user to bet against you, if he were to accept the whole thing')
    parser_bet.add_argument('--target-value', default=0.0, help='target value for Equal/NotEqual bet')
    parser_bet.add_argument('--leverage', type=int, default=5040, help='leverage, as a fraction of 5040')
    parser_bet.add_argument('--expiration', type=int, required=True, help='the number of blocks for which the bet should be valid')
    parser_bet.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_dividend = subparsers.add_parser('dividend', help='pay dividends to the holders of an asset (in proportion to their stake in it)')
    parser_dividend.add_argument('--source', required=True, help='the source address')
    parser_dividend.add_argument('--quantity-per-unit', required=True, help='the quantity of XCP to be paid per whole unit held of ASSET')
    parser_dividend.add_argument('--asset', required=True, help='the asset to which pay dividends')
    parser_dividend.add_argument('--dividend-asset', required=True, help='asset in which to pay the dividends')
    parser_dividend.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_burn = subparsers.add_parser('burn', help='destroy {} to earn XCP, during an initial period of time')
    parser_burn.add_argument('--source', required=True, help='the source address')
    parser_burn.add_argument('--quantity', required=True, help='quantity of {} to be burned'.format(config.BTC))
    parser_burn.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_cancel = subparsers.add_parser('cancel', help='cancel an open order or bet you created')
    parser_cancel.add_argument('--source', required=True, help='the source address')
    parser_cancel.add_argument('--offer-hash', required=True, help='the transaction hash of the order or bet')
    parser_cancel.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_rps = subparsers.add_parser('rps', help='open a rock-paper-scissors like game')
    parser_rps.add_argument('--source', required=True, help='the source address')
    parser_rps.add_argument('--wager', required=True, help='the quantity of XCP to wager')
    parser_rps.add_argument('--move', type=int, required=True, help='the selected move')
    parser_rps.add_argument('--possible-moves', type=int, required=True, help='the number of possible moves (odd number greater or equal than 3)')
    parser_rps.add_argument('--expiration', type=int, required=True, help='the number of blocks for which the bet should be valid')
    parser_rps.add_argument('--fee', help='the exact BTC fee to be paid to miners')

    parser_rpsresolve = subparsers.add_parser('rpsresolve', help='resolve a rock-paper-scissors like game')
    parser_rpsresolve.add_argument('--source', required=True, help='the source address')
    parser_rpsresolve.add_argument('--random', type=str, required=True, help='the random number used in the corresponding rps transaction')
    parser_rpsresolve.add_argument('--move', type=int, required=True, help='the selected move in the corresponding rps transaction')
    parser_rpsresolve.add_argument('--rps-match-id', required=True, help='the concatenation of the hashes of the two transactions which compose the rps match')
    parser_rpsresolve.add_argument('--fee', help='the exact BTC fee to be paid to miners')

    parser_publish = subparsers.add_parser('publish', help='publish contract code in the blockchain')
    parser_publish.add_argument('--source', required=True, help='the source address')
    parser_publish.add_argument('--gasprice', required=True, type=int, help='the price of gas')
    parser_publish.add_argument('--startgas', required=True, type=int, help='the maximum quantity of {} to be used to pay for the execution (satoshis)'.format(config.XCP))
    parser_publish.add_argument('--endowment', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'.format(config.XCP))
    parser_publish.add_argument('--code-hex', required=True, type=str, help='the hex‐encoded contract (returned by `serpent compile`)')
    parser_publish.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_execute = subparsers.add_parser('execute', help='execute contract code in the blockchain')
    parser_execute.add_argument('--source', required=True, help='the source address')
    parser_execute.add_argument('--contract-id', required=True, help='the contract ID of the contract to be executed')
    parser_execute.add_argument('--gasprice', required=True, type=int, help='the price of gas')
    parser_execute.add_argument('--startgas', required=True, type=int, help='the maximum quantity of {} to be used to pay for the execution (satoshis)'.format(config.XCP))
    parser_execute.add_argument('--value', required=True, type=int, help='quantity of {} to be transfered to the contract (satoshis)'.format(config.XCP))
    parser_execute.add_argument('--payload-hex', required=True, type=str, help='data to be provided to the contract (returned by `serpent encode_datalist`)')
    parser_execute.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_destroy = subparsers.add_parser('destroy', help='destroy a quantity of a Counterparty asset')
    parser_destroy.add_argument('--source', required=True, help='the source address')
    parser_destroy.add_argument('--asset', required=True, help='the ASSET of which you would like to destroy QUANTITY')
    parser_destroy.add_argument('--quantity', required=True, help='the quantity of ASSET to destroy')
    parser_destroy.add_argument('--tag', default='', help='tag')
    parser_destroy.add_argument('--fee', help='the exact {} fee to be paid to miners'.format(config.BTC))

    parser_address = subparsers.add_parser('balances', help='display the balances of a {} address'.format(config.XCP_NAME))
    parser_address.add_argument('address', help='the address you are interested in')

    parser_asset = subparsers.add_parser('asset', help='display the basic properties of a {} asset'.format(config.XCP_NAME))
    parser_asset.add_argument('asset', help='the asset you are interested in')

    parser_wallet = subparsers.add_parser('wallet', help='list the addresses in your backend wallet along with their balances in all {} assets'.format(config.XCP_NAME))

    parser_pending = subparsers.add_parser('pending', help='list pending order matches awaiting {}payment from you'.format(config.BTC))

    parser_getrows = subparsers.add_parser('getrows', help='get rows from a Counterparty table')
    parser_getrows.add_argument('--table', required=True, help='table name')
    parser_getrows.add_argument('--filter', nargs=3, action='append', help='filters to get specific rows')
    parser_getrows.add_argument('--filter-op', choices=['AND', 'OR'], help='operator uses to combine filters', default='AND')
    parser_getrows.add_argument('--order-by', help='field used to order results')
    parser_getrows.add_argument('--order-dir', choices=['ASC', 'DESC'], help='direction used to order results')
    parser_getrows.add_argument('--start-block', help='return only rows with block_index greater than start-block')
    parser_getrows.add_argument('--end-block', help='return only rows with block_index lower than end-block')
    parser_getrows.add_argument('--status', help='return only rows with the specified status')
    parser_getrows.add_argument('--limit', help='number of rows to return', default=100)
    parser_getrows.add_argument('--offset', help='number of rows to skip', default=0)

    parser_getrunninginfo = subparsers.add_parser('getinfo', help='get the current state of the server')

    args = parser.parse_args()

    # Logging
    log.set_up(logger, verbose=args.verbose)
    logger.propagate = False

    logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME))

    # Help message
    if args.help:
        parser.print_help()
        sys.exit()

    # Configuration
    clientapi.initialize(testnet=args.testnet, testcoin=args.testcoin,
                        counterparty_rpc_connect=args.counterparty_rpc_connect, counterparty_rpc_port=args.counterparty_rpc_port,
                        counterparty_rpc_user=args.counterparty_rpc_user, counterparty_rpc_password=args.counterparty_rpc_password,
                        counterparty_rpc_ssl=args.counterparty_rpc_ssl, counterparty_rpc_ssl_verify=args.counterparty_rpc_ssl_verify,
                        wallet_name=args.wallet_name, wallet_connect=args.wallet_connect, wallet_port=args.wallet_port, 
                        wallet_user=args.wallet_user, wallet_password=args.wallet_password,
                        wallet_ssl=args.wallet_ssl, wallet_ssl_verify=args.wallet_ssl_verify,
                        requests_timeout=args.requests_timeout)

    # MESSAGE CREATION
    if args.action in list(messages.MESSAGE_PARAMS.keys()):
        unsigned_hex = messages.compose(args.action, args)
        logger.info('Transaction (unsigned): {}'.format(unsigned_hex))
        if not args.unsigned:
            if script.is_multisig(args.source):
                logger.info('Multi‐signature transactions are signed and broadcasted manually.')
            
            elif input('Sign and broadcast? (y/N) ') == 'y':

                if wallet.is_mine(args.source):
                    if wallet.is_locked():
                        passphrase = getpass.getpass('Enter your wallet passhrase: ')
                        logger.info('Unlocking wallet for 60 (more) seconds.')
                        wallet.unlock(passphrase)
                    signed_tx_hex = wallet.sign_raw_transaction(unsigned_hex)
                else:
                    private_key_wif = input('Source address not in wallet. Please enter the private key in WIF format for {}:'.format(args.source))
                    if not private_key_wif:
                        raise TransactionError('invalid private key')
                    signed_tx_hex = wallet.sign_raw_transaction(unsigned_hex, private_key_wif=private_key_wif)

                logger.info('Transaction (signed): {}'.format(signed_tx_hex))
                tx_hash = wallet.send_raw_transaction(signed_tx_hex)
                logger.info('Hash of transaction (broadcasted): {}'.format(tx_hash))


    # VIEWING
    elif args.action in ['balances', 'asset', 'wallet', 'pending', 'getinfo', 'getrows']:
        view = console.get_view(args.action, args)
        print_method = getattr(console, 'print_{}'.format(args.action), None)
        if args.json_output or print_method is None:
            util.json_print(view)
        else:
            print_method(view)

    else:
        parser.print_help()
Example #4
0
def main():
    if os.name == 'nt':
        from counterpartylib.lib import util_windows
        #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging
        util_windows.fix_win32_unicode()

    # Post installation tasks
    generate_config_files()

    # Parse command-line arguments.
    parser = argparse.ArgumentParser(
        prog=APP_NAME,
        description='Server for the {} protocol'.format(config.XCP_NAME),
        add_help=False)
    parser.add_argument('-h',
                        '--help',
                        dest='help',
                        action='store_true',
                        help='show this help message and exit')
    parser.add_argument('-V',
                        '--version',
                        action='version',
                        version="{} v{}; {} v{}".format(
                            APP_NAME, APP_VERSION, 'counterparty-lib',
                            config.VERSION_STRING))
    parser.add_argument('--config-file',
                        help='the path to the configuration file')

    add_config_arguments(parser, CONFIG_ARGS, 'server.conf')

    subparsers = parser.add_subparsers(dest='action',
                                       help='the action to be taken')

    parser_server = subparsers.add_parser('start', help='run the server')

    parser_reparse = subparsers.add_parser(
        'reparse', help='reparse all transactions in the database')

    parser_rollback = subparsers.add_parser('rollback',
                                            help='rollback database')
    parser_rollback.add_argument('block_index',
                                 type=int,
                                 help='the index of the last known good block')

    parser_kickstart = subparsers.add_parser(
        'kickstart',
        help='rapidly build database by reading from Bitcoin Core blockchain')
    parser_kickstart.add_argument('--bitcoind-dir',
                                  help='Bitcoin Core data directory')

    parser_bootstrap = subparsers.add_parser(
        'bootstrap', help='bootstrap database with hosted snapshot')
    parser_bootstrap.add_argument('-q',
                                  '--quiet',
                                  dest='quiet',
                                  action='store_true',
                                  help='suppress progress bar')

    args = parser.parse_args()

    log.set_up(log.ROOT_LOGGER,
               verbose=args.verbose,
               console_logfilter=os.environ.get('COUNTERPARTY_LOGGING', None))

    logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME))

    # Help message
    if args.help:
        parser.print_help()
        sys.exit()

    # Bootstrapping
    if args.action == 'bootstrap':
        bootstrap(testnet=args.testnet, quiet=args.quiet)
        sys.exit()

    def init_with_catch(fn, init_args):
        try:
            return fn(**init_args)
        except TypeError as e:
            if 'unexpected keyword argument' in str(e):
                raise VersionError(
                    'Unsupported Server Parameter. CLI/Library Version Incompatibility.'
                )
            else:
                raise e

    # Configuration
    COMMANDS_WITH_DB = ['reparse', 'rollback', 'kickstart', 'start']
    COMMANDS_WITH_CONFIG = ['debug_config']
    if args.action in COMMANDS_WITH_DB or args.action in COMMANDS_WITH_CONFIG:
        init_args = dict(
            database_file=args.database_file,
            log_file=args.log_file,
            api_log_file=args.api_log_file,
            testnet=args.testnet,
            testcoin=args.testcoin,
            backend_name=args.backend_name,
            backend_connect=args.backend_connect,
            backend_port=args.backend_port,
            backend_user=args.backend_user,
            backend_password=args.backend_password,
            backend_ssl=args.backend_ssl,
            backend_ssl_no_verify=args.backend_ssl_no_verify,
            backend_poll_interval=args.backend_poll_interval,
            rpc_host=args.rpc_host,
            rpc_port=args.rpc_port,
            rpc_user=args.rpc_user,
            rpc_password=args.rpc_password,
            rpc_no_allow_cors=args.rpc_no_allow_cors,
            requests_timeout=args.requests_timeout,
            rpc_batch_size=args.rpc_batch_size,
            check_asset_conservation=not args.no_check_asset_conservation,
            force=args.force,
            verbose=args.verbose,
            console_logfilter=os.environ.get('COUNTERPARTY_LOGGING', None),
            p2sh_dust_return_pubkey=args.p2sh_dust_return_pubkey,
            utxo_locks_max_addresses=args.utxo_locks_max_addresses,
            utxo_locks_max_age=args.utxo_locks_max_age)
        #,broadcast_tx_mainnet=args.broadcast_tx_mainnet)

    if args.action in COMMANDS_WITH_DB:
        db = init_with_catch(server.initialise, init_args)

    elif args.action in COMMANDS_WITH_CONFIG:
        init_with_catch(server.initialise_config, init_args)

    # PARSING
    if args.action == 'reparse':
        server.reparse(db)

    elif args.action == 'rollback':
        server.reparse(db, block_index=args.block_index)

    elif args.action == 'kickstart':
        server.kickstart(db, bitcoind_dir=args.bitcoind_dir)

    elif args.action == 'start':
        server.start_all(db)

    elif args.action == 'debug_config':
        server.debug_config()

    else:
        parser.print_help()
Example #5
0
    def initialize(self, openDialog=False):
        configdir = appdirs.user_config_dir(appauthor=config.XCP_NAME,
                                            appname=config.APP_NAME,
                                            roaming=True)
        configfile = os.path.join(configdir, 'client.conf')
        config_exists = os.path.exists(configfile)

        if not config_exists:
            generate_config_file(configfile, client.CONFIG_ARGS)

        # Parse command-line arguments.
        parser = argparse.ArgumentParser(
            prog=APP_NAME,
            description=tr('Counterparty CLI for counterparty-server'),
            add_help=False,
            conflict_handler='resolve')
        parser.add_argument('-h',
                            '--help',
                            dest='help',
                            action='store_true',
                            help=tr('show this help message and exit'))
        parser.add_argument('-V',
                            '--version',
                            action='version',
                            version="{} v{}".format(APP_NAME, APP_VERSION))
        parser.add_argument(
            '--config-file',
            help=tr(
                'the location of the counterparty-client configuration file'))

        self.args = parser.parse_known_args()[0]

        if not config_exists or openDialog:
            is_splash_visible = False
            if self.splash:
                is_splash_visible = self.splash.isVisible()
                if is_splash_visible:
                    self.splash.hide()
            configfile = getattr(self.args, 'config_file', None) or configfile
            configUI = ConfigDialog(configfile, newconfig=not config_exists)
            result = configUI.exec()
            if is_splash_visible:
                self.splash.show()

        if openDialog and result == 0:
            return False

        parser = add_config_arguments(parser,
                                      CONFIG_ARGS,
                                      'client.conf',
                                      config_file_arg_name='config_file')

        self.args = parser.parse_args()

        dargs = vars(self.args)
        for argName in dargs:
            print('{}: {}'.format(argName.upper(), dargs[argName]))
            setattr(self, argName.upper(), dargs[argName])

        # Help message
        if self.args.help:
            parser.print_help()
            sys.exit()

        # Logging
        logdir = appdirs.user_log_dir(appauthor=config.XCP_NAME,
                                      appname=config.APP_NAME)
        if not os.path.exists(logdir):
            os.makedirs(logdir, mode=0o755)
        self.LOG_FILE = os.path.join(logdir, 'counterpartygui.log')
        log.set_up(logger, verbose=self.args.verbose, logfile=self.LOG_FILE)

        return True
Example #6
0
def main():
    if os.name == 'nt':
        from counterpartylib.lib import util_windows
        #patch up cmd.exe's "challenged" (i.e. broken/non-existent) UTF-8 logging
        util_windows.fix_win32_unicode()

    # Post installation tasks
    generate_config_files()

    # Parse command-line arguments.
    parser = argparse.ArgumentParser(
        prog=APP_NAME,
        description='Server for the {} protocol'.format(config.XCP_NAME),
        add_help=False)
    parser.add_argument('-h',
                        '--help',
                        dest='help',
                        action='store_true',
                        help='show this help message and exit')
    parser.add_argument('-V',
                        '--version',
                        action='version',
                        version="{} v{}; {} v{}".format(
                            APP_NAME, APP_VERSION, 'counterparty-lib',
                            config.VERSION_STRING))
    parser.add_argument('--config-file',
                        help='the path to the configuration file')

    parser = add_config_arguments(parser, CONFIG_ARGS, 'server.conf')

    subparsers = parser.add_subparsers(dest='action',
                                       help='the action to be taken')

    parser_server = subparsers.add_parser('start', help='run the server')

    parser_reparse = subparsers.add_parser(
        'reparse', help='reparse all transactions in the database')

    parser_rollback = subparsers.add_parser('rollback',
                                            help='rollback database')
    parser_rollback.add_argument('block_index',
                                 type=int,
                                 help='the index of the last known good block')

    parser_kickstart = subparsers.add_parser(
        'kickstart',
        help='rapidly build database by reading from Bitcoin Core blockchain')
    parser_kickstart.add_argument('--bitcoind-dir',
                                  help='Bitcoin Core data directory')

    parser_bootstrap = subparsers.add_parser(
        'bootstrap', help='bootstrap database with hosted snapshot')

    args = parser.parse_args()

    log.set_up(logger, verbose=args.verbose)

    logger.info('Running v{} of {}.'.format(APP_VERSION, APP_NAME))

    # Help message
    if args.help:
        parser.print_help()
        sys.exit()

    # Bootstrapping
    if args.action == 'bootstrap':
        bootstrap(testnet=args.testnet)
        sys.exit()

    # Configuration
    if args.action in ['reparse', 'rollback', 'kickstart', 'start']:
        try:
            db = server.initialise(
                database_file=args.database_file,
                log_file=args.log_file,
                api_log_file=args.api_log_file,
                testnet=args.testnet,
                testcoin=args.testcoin,
                backend_name=args.backend_name,
                backend_connect=args.backend_connect,
                backend_port=args.backend_port,
                backend_user=args.backend_user,
                backend_password=args.backend_password,
                backend_ssl=args.backend_ssl,
                backend_ssl_no_verify=args.backend_ssl_no_verify,
                backend_poll_interval=args.backend_poll_interval,
                rpc_host=args.rpc_host,
                rpc_port=args.rpc_port,
                rpc_user=args.rpc_user,
                rpc_password=args.rpc_password,
                rpc_no_allow_cors=args.rpc_no_allow_cors,
                force=args.force,
                verbose=args.verbose)
            #,broadcast_tx_mainnet=args.broadcast_tx_mainnet)
        except TypeError as e:
            if 'unexpected keyword argument' in str(e):
                raise VersionError(
                    'Unsupported Server Parameter. CLI/Library Version Incompatibility.'
                )
            else:
                raise e

    # PARSING
    if args.action == 'reparse':
        server.reparse(db)

    elif args.action == 'rollback':
        server.reparse(db, block_index=args.block_index)

    elif args.action == 'kickstart':
        server.kickstart(db, bitcoind_dir=args.bitcoind_dir)

    elif args.action == 'start':
        server.start_all(db)

    else:
        parser.print_help()