Example #1
0
 def __init__(self, wallet, username=None):
     """Initialize the bittransfer with wallet and username."""
     from two1.server.machine_auth_wallet import MachineAuthWallet
     super().__init__()
     if isinstance(wallet, MachineAuthWallet):
         self.wallet = wallet
     else:
         self.wallet = MachineAuthWallet(wallet)
     if username is None:
         self.username = config.Config().username
     else:
         self.username = username
Example #2
0
def mock_machine_auth(mock_wallet):
    """ Fixture that injects a MachineAuthWallet using a MockWallet

    Returns:
        MockTwo1Wallet: an initialized mock two1 wallet
    """
    return MachineAuthWallet(mock_wallet)
Example #3
0
def machine_auth_wallet(wallet):
    """ Fixture which injects a MachineAuthWallet

    Returns:
        MachineAuthWallet: machine auth wallet
    """
    return MachineAuthWallet(wallet)
Example #4
0
def mock_config(mock_wallet):
    """ Fixture that injects a MockConfig

    Returns:
        MockConfig: an mock config object initialized with a mock wallet
    """
    _mock_config = mock_objects.MockConfig()
    _mock_config.machine_auth = MachineAuthWallet(mock_wallet)
    return _mock_config
Example #5
0
 def __init__(self, wallet, username=None, client=None):
     """Initialize the bittransfer with wallet and username."""
     from two1.server.machine_auth_wallet import MachineAuthWallet
     from two1.server import rest_client
     super().__init__()
     if isinstance(wallet, MachineAuthWallet):
         self.wallet = wallet
     else:
         self.wallet = MachineAuthWallet(wallet)
     if username is None:
         self.username = config.Config().username
     else:
         self.username = username
     if client is None:
         self.client = rest_client.TwentyOneRestClient(
             two1.TWO1_HOST, self.wallet, self.username)
     else:
         self.client = client
Example #6
0
 def __init__(self, wallet, username=None):
     """Initialize the bittransfer with wallet and username."""
     from two1.server.machine_auth_wallet import MachineAuthWallet
     super().__init__()
     if isinstance(wallet, MachineAuthWallet):
         self.wallet = wallet
     else:
         self.wallet = MachineAuthWallet(wallet)
     if username is None:
         self.username = config.Config().username
     else:
         self.username = username
Example #7
0
def mock_rest_client(monkeypatch, mock_config, mock_wallet):
    """ Fixture that injects a MockTwentyOneRestClient

    Returns:
        MockTwentyOneRestClient: an mock rest client initialized with a mock config and mock wallet
    """
    machine_auth = MachineAuthWallet(mock_wallet)
    _mock_rest_client = mock_objects.MockTwentyOneRestClient(
        None, machine_auth, mock_config.username)
    for func_name in mock_objects.MockTwentyOneRestClient.DEFAULT_VALUES.keys(
    ):
        monkeypatch.setattr(server.rest_client.TwentyOneRestClient, func_name,
                            getattr(_mock_rest_client, func_name))
    return _mock_rest_client
Example #8
0
def patch_rest_client(monkeypatch, mock_config, mock_wallet):
    """ Fixture that injects a MockTwentyOneRestClient that monkeypathces the regular TwentyOneRestClient

    Returns:
        MockTwentyOneRestClient: a mock rest client object
    """
    machine_auth = MachineAuthWallet(mock_wallet)
    _patch_rest_client = mock_objects.MockTwentyOneRestClient(
        None, machine_auth, mock_config.username)
    for mock_function in mock_objects.MockTwentyOneRestClient.DEFAULT_VALUES.keys(
    ):
        monkeypatch.setattr(server.rest_client.TwentyOneRestClient,
                            mock_function,
                            getattr(_patch_rest_client, mock_function))
    return _patch_rest_client
Example #9
0
 def __init__(self, wallet, username=None, client=None):
     """Initialize the bittransfer with wallet and username."""
     from two1.server.machine_auth_wallet import MachineAuthWallet
     from two1.server import rest_client
     super().__init__()
     if isinstance(wallet, MachineAuthWallet):
         self.wallet = wallet
     else:
         self.wallet = MachineAuthWallet(wallet)
     if username is None:
         self.username = config.Config().username
     else:
         self.username = username
     if client is None:
         self.client = rest_client.TwentyOneRestClient(
             two1.TWO1_HOST, self.wallet, self.username)
     else:
         self.client = client
Example #10
0
def request(*args, payment_method=None, **kwargs):
    """Instantiate, or use a cached BitRequests object, and make a request."""
    global _requests
    global _current_method
    global _current_wallet
    payment_method = payment_method or _current_method

    if not _current_wallet:
        from two1.wallet import Wallet
        _current_wallet = Wallet()

    if payment_method not in _requests:
        if payment_method == OFF_CHAIN:
            from two1.server.machine_auth_wallet import MachineAuthWallet
            _requests[_current_method] = BitTransferRequests(
                MachineAuthWallet(_current_wallet))
        elif payment_method == ON_CHAIN:
            _requests[_current_method] = OnChainRequests(_current_wallet)
        elif payment_method == CHANNEL:
            _requests[_current_method] = ChannelRequests(_current_wallet)
        else:
            raise ValueError('That method is not supported.')

    return _requests[payment_method].request(*args, **kwargs)
Example #11
0
class BitTransferRequests(BitRequests):

    """BitRequests for making bit-transfer payments."""

    HTTP_BITCOIN_PRICE = 'price'
    HTTP_BITCOIN_ADDRESS = 'bitcoin-address'
    HTTP_BITCOIN_USERNAME = '******'

    def __init__(self, wallet, username=None, client=None):
        """Initialize the bittransfer with wallet and username."""
        from two1.server.machine_auth_wallet import MachineAuthWallet
        from two1.server import rest_client
        super().__init__()
        if isinstance(wallet, MachineAuthWallet):
            self.wallet = wallet
        else:
            self.wallet = MachineAuthWallet(wallet)
        if username is None:
            self.username = config.Config().username
        else:
            self.username = username
        if client is None:
            self.client = rest_client.TwentyOneRestClient(
                two1.TWO1_HOST, self.wallet, self.username)
        else:
            self.client = client

    def make_402_payment(self, response, max_price):
        """Make a bit-transfer payment to the payment-handling service."""
        # Retrieve payment headers
        headers = response.headers
        price = headers.get(BitTransferRequests.HTTP_BITCOIN_PRICE)
        payee_address = headers.get(BitTransferRequests.HTTP_BITCOIN_ADDRESS)
        payee_username = headers.get(BitTransferRequests.HTTP_BITCOIN_USERNAME)

        # Verify that the payment method is supported
        if price is None or payee_address is None or payee_username is None:
            raise UnsupportedPaymentMethodError(
                'Resource does not support that payment method.')

        # Convert string headers into correct data types
        price = int(price)

        # verify that we have the money to purchase the resource
        buffer_balance = self.client.get_earnings()["total_earnings"]
        if price > buffer_balance:
            insuff_funds_err = 'Resource price ({}) exceeds buffer balance ({}).'
            raise InsufficientBalanceError(insuff_funds_err.format(price, buffer_balance))

        # Verify resource cost against our budget
        if max_price and price > max_price:
            max_price_err = 'Resource price ({}) exceeds max price ({}).'
            raise ResourcePriceGreaterThanMaxPriceError(max_price_err.format(price, max_price))

        # Get the signing public key
        pubkey = self.wallet.get_public_key()
        compressed_pubkey = codecs.encode(pubkey.compressed_bytes, 'base64').decode()

        # Create and sign BitTranfer
        bittransfer = json.dumps({
            'payer': self.username,
            'payer_pubkey': compressed_pubkey,
            'payee_address': payee_address,
            'payee_username': payee_username,
            'amount': price,
            'timestamp': time.time(),
            'description': response.url
        })
        if not isinstance(bittransfer, str):
            raise TypeError("Serialized bittransfer must be a string")
        signature = self.wallet.sign_message(bittransfer)
        logger.debug('[BitTransferRequests] Signature: {}'.format(signature))
        logger.debug('[BitTransferRequests] BitTransfer: {}'.format(bittransfer))
        return {
            'Bitcoin-Transfer': bittransfer,
            'Authorization': signature
        }

    def get_402_info(self, url):
        """Get bit-transfer payment information about the resource."""
        headers = requests.get(url).headers
        price = headers.get(BitTransferRequests.HTTP_BITCOIN_PRICE, 0)
        payee_address = headers.get(BitTransferRequests.HTTP_BITCOIN_ADDRESS)
        payee_username = headers.get(BitTransferRequests.HTTP_BITCOIN_USERNAME)
        return {BitTransferRequests.HTTP_BITCOIN_PRICE: int(price),
                BitTransferRequests.HTTP_BITCOIN_ADDRESS: payee_address,
                BitTransferRequests.HTTP_BITCOIN_USERNAME: payee_username}
Example #12
0
class BitTransferRequests(BitRequests):

    """BitRequests for making bit-transfer payments."""

    HTTP_BITCOIN_PRICE = 'price'
    HTTP_BITCOIN_ADDRESS = 'bitcoin-address'
    HTTP_BITCOIN_USERNAME = '******'

    def __init__(self, wallet, username=None, client=None):
        """Initialize the bittransfer with wallet and username."""
        from two1.server.machine_auth_wallet import MachineAuthWallet
        from two1.server import rest_client
        super().__init__()
        if isinstance(wallet, MachineAuthWallet):
            self.wallet = wallet
        else:
            self.wallet = MachineAuthWallet(wallet)
        if username is None:
            self.username = config.Config().username
        else:
            self.username = username
        if client is None:
            self.client = rest_client.TwentyOneRestClient(
                two1.TWO1_HOST, self.wallet, self.username)
        else:
            self.client = client

    def make_402_payment(self, response, max_price):
        """Make a bit-transfer payment to the payment-handling service."""
        # Retrieve payment headers
        headers = response.headers
        price = headers.get(BitTransferRequests.HTTP_BITCOIN_PRICE)
        payee_address = headers.get(BitTransferRequests.HTTP_BITCOIN_ADDRESS)
        payee_username = headers.get(BitTransferRequests.HTTP_BITCOIN_USERNAME)

        # Verify that the payment method is supported
        if price is None or payee_address is None or payee_username is None:
            raise UnsupportedPaymentMethodError(
                'Resource does not support that payment method.')

        # Convert string headers into correct data types
        price = int(price)

        # verify that we have the money to purchase the resource
        buffer_balance = self.client.get_earnings()["total_earnings"]
        if price > buffer_balance:
            insuff_funds_err = 'Resource price ({}) exceeds buffer balance ({}).'
            raise InsufficientBalanceError(insuff_funds_err.format(price, buffer_balance))

        # Verify resource cost against our budget
        if max_price and price > max_price:
            max_price_err = 'Resource price ({}) exceeds max price ({}).'
            raise ResourcePriceGreaterThanMaxPriceError(max_price_err.format(price, max_price))

        # Get the signing public key
        pubkey = self.wallet.get_public_key()
        compressed_pubkey = codecs.encode(pubkey.compressed_bytes, 'base64').decode()

        # Create and sign BitTranfer
        bittransfer = json.dumps({
            'payer': self.username,
            'payer_pubkey': compressed_pubkey,
            'payee_address': payee_address,
            'payee_username': payee_username,
            'amount': price,
            'timestamp': time.time(),
            'description': response.url
        })
        if not isinstance(bittransfer, str):
            raise TypeError("Serialized bittransfer must be a string")
        signature = self.wallet.sign_message(bittransfer)
        logger.debug('[BitTransferRequests] Signature: {}'.format(signature))
        logger.debug('[BitTransferRequests] BitTransfer: {}'.format(bittransfer))
        return {
            'Bitcoin-Transfer': bittransfer,
            'Authorization': signature
        }

    def get_402_info(self, url):
        """Get bit-transfer payment information about the resource."""
        headers = requests.get(url).headers
        price = headers.get(BitTransferRequests.HTTP_BITCOIN_PRICE, 0)
        payee_address = headers.get(BitTransferRequests.HTTP_BITCOIN_ADDRESS)
        payee_username = headers.get(BitTransferRequests.HTTP_BITCOIN_USERNAME)
        return {BitTransferRequests.HTTP_BITCOIN_PRICE: int(price),
                BitTransferRequests.HTTP_BITCOIN_ADDRESS: payee_address,
                BitTransferRequests.HTTP_BITCOIN_USERNAME: payee_username}
Example #13
0
# Setup the dashboard
from two1.commands import status
from two1.commands import log
from two1.commands import flush
from two1.commands import mine
from two1.wallet import Wallet
from two1.server.machine_auth_wallet import MachineAuthWallet
from two1.server import rest_client
from two1.commands.config import Config
from two1 import TWO1_HOST

wallet = Wallet()
host = TWO1_HOST
conf = Config()
username = Config().username
client = rest_client.TwentyOneRestClient(host, MachineAuthWallet(wallet),
                                         username)
admin = Admin(app, name='Admin', template_mode='bootstrap3')


class DashboardView(BaseView):
    @expose('/', methods=('GET', 'POST'))
    def dashboard(self):
        flush_message = ""
        status_mining = status.status_mining(client)

        if request.method == 'POST':
            print(request.form)
            if request.form['submit'] == 'Flush Earnings':
                flush_message = self.doFlush()
            else:
Example #14
0
    def buy(config, resource, data, method, data_file, output_file,
            payment_method, max_price, info_only):
        """Buy from any machine payable endpoint

           Note: The two1lib _buy function does not support simply returning an object,
                 until then, include a local copy here
        """
        # 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_WWW_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(MachineAuthWallet(wallet),
                                              username)
            elif payment_method == 'onchain':
                bit_req = OnChainRequests(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:
            response = res.json()
            # Clean up names
            for index, elem in enumerate(response):
                if elem['name'] is None:
                    response[index]['name'] = 'Please name me'
                elif len(elem['name']) == 0:
                    response[index]['name'] = 'Please name me'
                else:
                    response[index]['name'] = response[index]['name'].title()
                print(elem['description'])
                if elem['description'] is None:
                    try:
                        response[index]['description'] = elem['owner'].title(
                        ) + ' is a bad endpoint operator and forgot to place a description'
                    except:
                        response[index][
                            'description'] = 'Anonymous is a bad endpoint operator and forgot to place a description'
                # Any description greater than 66 characters causes the text to overflow, this enforces a limit
                elif len(elem['description']) > 63:
                    response[index]['description'] = response[index][
                        'description'][:63] + '...'

            # Write response to console
            return response

        # 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,
                                                     MachineAuthWallet(wallet),
                                                     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'

        # 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()))