Example #1
0
def twentyone_balance(client, wallet):
    channel_client = channels.PaymentChannelClient(wallet)
    user_balances = _get_balances(client, wallet, channel_client)
    return user_balances.twentyone
Example #2
0
def _buy(config, resource, data, method, data_file, output_file,
         payment_method, max_price, info_only):
    # If resource is a URL string, then bypass seller search
    if URL_REGEXP.match(resource):
        target_url = resource
        seller = target_url
    elif resource in DEMOS:
        target_url = TWO1_MERCHANT_HOST + DEMOS[resource]["path"]
        data = json.dumps(data)
    else:
        raise NotImplementedError('Endpoint search is not implemented!')

    # Change default HTTP method from "GET" to "POST", if we have data
    if method == "GET" and (data or data_file):
        method = "POST"

    # Set default headers for making bitrequests with JSON-like data
    headers = {'Content-Type': 'application/json'}

    try:
        # Find the correct payment method
        if payment_method == 'offchain':
            bit_req = BitTransferRequests(config.machine_auth, config.username)
        elif payment_method == 'onchain':
            bit_req = OnChainRequests(config.wallet)
        else:
            raise Exception('Payment method does not exist.')

        # Make the request
        if info_only:
            res = bit_req.get_402_info(target_url)
        else:
            res = bit_req.request(
                method.lower(), target_url, max_price=max_price,
                data=data or data_file, headers=headers)
    except ResourcePriceGreaterThanMaxPriceError as e:
        config.log(UxString.Error.resource_price_greater_than_max_price.format(e))
        return
    except Exception as e:
        if 'Insufficient funds.' in str(e):
            config.log(UxString.Error.insufficient_funds_mine_more.format(
                DEFAULT_ONCHAIN_BUY_FEE
            ))
        else:
            config.log(str(e), fg="red")
        return

    # Output results to user
    if output_file:
        # Write response output file
        output_file.write(res.content)
    elif info_only:
        # Print headers that are related to 402 payment required
        for key, val in res.items():
            config.log('{}: {}'.format(key, val))
    elif resource in DEMOS:
        config.log(DEMOS[resource]["formatter"](res))
    else:
        # Write response to console
        config.log(res.text)

    # Write the amount paid out
    if not info_only:
        client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                                 config.machine_auth,
                                                 config.username)
        twentyone_balance, balance_c, pending_transactions, flushed_earnings = \
            _get_balances(config, client)
        config.log("You spent: %s Satoshis. Remaining 21.co balance: %s Satoshis." % (res.amount_paid, twentyone_balance))

    # Record the transaction if it was a payable request
    if hasattr(res, 'paid_amount'):
        config.log_purchase(s=seller,
                            r=resource,
                            p=res.paid_amount,
                            d=str(datetime.datetime.today()))
Example #3
0
def twentyone_balance(client, wallet):
    channel_client = channels.PaymentChannelClient(wallet)
    user_balances = _get_balances(client, wallet, channel_client)
    return user_balances.twentyone
Example #4
0
def _buy(config, resource, data, method, data_file, output_file,
         payment_method, max_price, info_only):
    # If resource is a URL string, then bypass seller search
    if URL_REGEXP.match(resource):
        target_url = resource
        seller = target_url
    elif resource in DEMOS:
        target_url = TWO1_MERCHANT_HOST + DEMOS[resource]["path"]
        data = json.dumps(data)
    else:
        raise NotImplementedError('Endpoint search is not implemented!')

    # Change default HTTP method from "GET" to "POST", if we have data
    if method == "GET" and (data or data_file):
        method = "POST"

    # Set default headers for making bitrequests with JSON-like data
    headers = {'Content-Type': 'application/json'}

    try:
        # Find the correct payment method
        if payment_method == 'offchain':
            bit_req = BitTransferRequests(config.machine_auth, config.username)
        elif payment_method == 'onchain':
            bit_req = OnChainRequests(config.wallet)
        elif payment_method == 'channel':
            bit_req = ChannelRequests(config.wallet)
            channel_list = bit_req._channelclient.list()
            if not channel_list:
                confirmed = click.confirm(UxString.buy_channel_warning.format(
                    bit_req.DEFAULT_DEPOSIT_AMOUNT,
                    PaymentChannelStateMachine.PAYMENT_TX_MIN_OUTPUT_AMOUNT), default=True)
                if not confirmed:
                    raise Exception(UxString.buy_channel_aborted)

        else:
            raise Exception('Payment method does not exist.')

        # Make the request
        if info_only:
            res = bit_req.get_402_info(target_url)
        else:
            res = bit_req.request(
                method.lower(), target_url, max_price=max_price,
                data=data or data_file, headers=headers)
    except ResourcePriceGreaterThanMaxPriceError as e:
        config.log(UxString.Error.resource_price_greater_than_max_price.format(e))
        return
    except Exception as e:
        f = get_fees()
        buy_fee = 2 * f['per_input'] + f['per_output']
        if 'Insufficient funds.' in str(e):
            config.log(UxString.Error.insufficient_funds_mine_more.format(
                buy_fee
            ))
        else:
            config.log(str(e), fg="red")
        return

    # Output results to user
    if output_file:
        # Write response output file
        output_file.write(res.content)
    elif info_only:
        # Print headers that are related to 402 payment required
        for key, val in res.items():
            config.log('{}: {}'.format(key, val))
    elif resource in DEMOS:
        config.log(DEMOS[resource]["formatter"](res))
    else:
        # Write response to console
        config.log(res.text)

    # Write the amount paid out if something was truly paid
    if not info_only and hasattr(res, 'amount_paid'):
        client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                                 config.machine_auth,
                                                 config.username)
        user_balances = _get_balances(config, client)
        if payment_method == 'offchain':
            balance_amount = user_balances.twentyone
            balance_type = '21.co'
        elif payment_method == 'onchain':
            balance_amount = user_balances.onchain
            balance_type = 'blockchain'
        elif payment_method == 'channel':
            balance_amount = user_balances.channels
            balance_type = 'payment channels'
        config.log("You spent: %s Satoshis. Remaining %s balance: %s Satoshis." % (
            res.amount_paid, balance_type, balance_amount))

    # Record the transaction if it was a payable request
    if hasattr(res, 'paid_amount'):
        config.log_purchase(s=seller,
                            r=resource,
                            p=res.paid_amount,
                            d=str(datetime.datetime.today()))
Example #5
0
File: buy.py Project: erikvold/two1
def _buy(config, resource, data, method, data_file, output_file,
         payment_method, max_price, info_only):
    """
    Buys bitcoin payable content over http

    Todo:
        reduce number of input args
        Exception is too general, raise a different exception when user cannot pay

    Args:
        config (Config): config object used for getting .two1 information
        resource (str): resource or content to purchase
        method (str): HTTP request method, defaults to GET
        data_file (str): name of the data file to send in HTTP body
        output_file (str): Output file name
        payment_method (str): Type of payment used in the purchase: offchain, onchain, channel
        max_price (int): Max price of resource
        info_only (bool): Flag which will only get info and not  purcahase the resource

    Raises:
        NotImplementedError: if endpoint or resource is not valid
        ResourcePriceGreaterThanMaxPriceError: If the resource price is greater than the max price
    """
    # If resource is a URL string, then bypass seller search
    if URL_REGEXP.match(resource):
        target_url = resource
        seller = target_url
    elif re.match(r'^(((\w*)(\/){0,1})(\w*)){0,2}(\/){0,1}$',
                  resource) and resource not in DEMOS:
        target_url = 'https://mkt.21.co/' + resource
        seller = target_url
    elif resource in DEMOS:
        target_url = TWO1_MERCHANT_HOST + DEMOS[resource]["path"]
        data = json.dumps(data)
    else:
        # If we can't figure out the resource type, attempt to use `http`
        target_url = 'http://' + resource

    # Change default HTTP method from "GET" to "POST", if we have data
    if method == "GET" and (data or data_file):
        method = "POST"

    # Set default headers for making bitrequests with JSON-like data
    headers = {'Content-Type': 'application/json'}

    try:
        # Find the correct payment method
        if payment_method == 'offchain':
            bit_req = BitTransferRequests(config.machine_auth, config.username)
        elif payment_method == 'onchain':
            bit_req = OnChainRequests(config.wallet)
        elif payment_method == 'channel':
            bit_req = ChannelRequests(config.wallet)
            channel_list = bit_req._channelclient.list()
            if not channel_list:
                confirmed = click.confirm(UxString.buy_channel_warning.format(
                    bit_req.DEFAULT_DEPOSIT_AMOUNT,
                    PaymentChannelStateMachine.PAYMENT_TX_MIN_OUTPUT_AMOUNT),
                                          default=True)
                if not confirmed:
                    raise Exception(UxString.buy_channel_aborted)

        else:
            raise Exception('Payment method does not exist.')

        # Make the request
        if info_only:
            res = bit_req.get_402_info(target_url)
        else:
            res = bit_req.request(method.lower(),
                                  target_url,
                                  max_price=max_price,
                                  data=data or data_file,
                                  headers=headers)
    except ResourcePriceGreaterThanMaxPriceError as e:
        config.log(
            UxString.Error.resource_price_greater_than_max_price.format(e))
        return
    except Exception as e:
        f = get_fees()
        buy_fee = 2 * f['per_input'] + f['per_output']
        if 'Insufficient funds.' in str(e):
            config.log(
                UxString.Error.insufficient_funds_mine_more.format(buy_fee))
        else:
            config.log(str(e), fg="red")
        return

    # Output results to user
    if output_file:
        # Write response output file
        output_file.write(res.content)
    elif info_only:
        # Print headers that are related to 402 payment required
        for key, val in res.items():
            config.log('{}: {}'.format(key, val))
    elif resource in DEMOS:
        config.log(DEMOS[resource]["formatter"](res))
    else:
        # Write response to console
        config.log(res.text)

    # Write the amount paid out if something was truly paid
    if not info_only and hasattr(res, 'amount_paid'):
        client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                                 config.machine_auth,
                                                 config.username)
        user_balances = _get_balances(config, client)
        if payment_method == 'offchain':
            balance_amount = user_balances.twentyone
            balance_type = '21.co'
        elif payment_method == 'onchain':
            balance_amount = user_balances.onchain
            balance_type = 'blockchain'
        elif payment_method == 'channel':
            balance_amount = user_balances.channels
            balance_type = 'payment channels'
        config.log(
            "You spent: %s Satoshis. Remaining %s balance: %s Satoshis." %
            (res.amount_paid, balance_type, balance_amount))

    # Record the transaction if it was a payable request
    if hasattr(res, 'paid_amount'):
        config.log_purchase(s=seller,
                            r=resource,
                            p=res.paid_amount,
                            d=str(datetime.datetime.today()))