Exemplo n.º 1
0
def _list_apps(config):
    """ Lists all apps that have been published to the 21 marketplace

    Args:
        config (Config): config object used for getting .two1 information.
    """
    click.secho(UxString.my_apps.format(config.username), fg="green")
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)
    current_page = 0
    total_pages = get_search_results(config, client, current_page)
    if total_pages < 1:
        return

    while 0 <= current_page < total_pages:
        try:
            prompt_resp = click.prompt(UxString.pagination, type=str)

            next_page = get_next_page(prompt_resp, current_page)

            if next_page == -1:
                model_id = prompt_resp
                display_app_info(config, client, model_id)
            elif next_page >= total_pages or next_page < 0:
                continue
            else:
                get_search_results(config, client, next_page)
                current_page = next_page

        except click.exceptions.Abort:
            return
Exemplo n.º 2
0
def _flush(config):
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)

    flush_earnings(config, client)

    config.log("")
Exemplo n.º 3
0
def _status(config, detail):
    """ Reports two1 stataus including balances, username, and mining hashrate

    Args:
        config (Config): config object used for getting .two1 information
        detail (bool): Lists all balance details in status report

    Returns:
        dict: a dictionary of 'account', 'mining', and 'wallet' items with formatted
            strings for each value
    """
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)

    status = {
        "account": status_account(config),
        "mining": status_mining(config, client),
        "wallet": status_wallet(config, client, detail)
    }

    config.log("")
    # status_endpoints(config)
    # status_bought_endpoints(config)

    return status
Exemplo n.º 4
0
def _join(config, network):
    """Perform the rest_client join"""
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)

    try:
        config.log(UxString.update_superuser)
        start_zerotier_command = ["sudo", "service", "zerotier-one", "start"]
        subprocess.check_output(start_zerotier_command)
        zt_device_address = zerotier.device_address()
        response = client.join(network, zt_device_address)
        if response.ok:
            join_command = [
                "sudo", "zerotier-cli", "join",
                response.json().get("networkid")
            ]
            subprocess.check_output(join_command)
            config.log(
                UxString.successful_join.format(
                    click.style(network, fg="magenta")))
    except ServerRequestError as e:
        if e.status_code == 401:
            config.log(UxString.invalid_network)
        else:
            raise e
    except subprocess.CalledProcessError as e:
        config.log(str(e))
Exemplo n.º 5
0
def start_cpu_mining(config):
    """Mine at the CPU.
    >>> from two1.commands.config import Config
    >>> config = Config()
    >>> start_cpu_mining(config)
    """

    client = rest_client.TwentyOneRestClient(cmd_config.TWO1_HOST,
                                             config.machine_auth,
                                             config.username)

    enonce1, enonce2_size, reward = set_payout_address(config, client)

    start_time = time.time()
    config.log(UxString.mining_start.format(config.username, reward))

    work = get_work(config, client)

    found_share = mine_work(work, enonce1=enonce1, enonce2_size=enonce2_size)

    paid_satoshis = save_work(client, found_share, config.username)

    end_time = time.time()
    duration = end_time - start_time

    config.log(UxString.mining_success.format(config.username, paid_satoshis,
                                              duration),
               fg="magenta")

    click.echo(UxString.mining_status)
    status.status_wallet(config, client)

    click.echo(
        UxString.mining_finish.format(click.style("21 status", bold=True),
                                      click.style("21 buy", bold=True)))
Exemplo n.º 6
0
def _inbox(config):
    """ Shows a list of notifications on a click pager

    Args:
        config (Config): config object used for getting .two1 information

    Returns:
        list: list of notifications in users inbox
    """
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)

    prints = []

    notifications, has_unreads = get_notifications(config, client)
    if len(notifications) > 0:
        prints.append(UxString.notification_intro)
        prints.extend(notifications)

    output = "\n".join(prints)
    config.echo_via_pager(output)

    if has_unreads:
        client.mark_notifications_read(config.username)

    return notifications
Exemplo n.º 7
0
def _log(config, debug):
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)

    response = client.get_earning_logs()

    logs = response["logs"]

    prints = [UxString.log_intro]

    if not debug:
        logs = filter_rollbacks(logs)

    for entry in logs:

        prints.append(get_headline(entry))

        # reason
        prints.append(get_description(entry))
        prints.append("\n")

        # transaction details
        if entry["amount"] < 0 and "paid_to" in entry and "txns" in entry:
            prints.append(get_txn_details(entry))
            prints.append("\n")

    if len(prints) == 1:
        prints.append(UxString.empty_logs)

    output = "\n".join(prints)
    config.echo_via_pager(output)

    return logs
Exemplo n.º 8
0
def _search(config, search_string):
    """ Searches the marketplace for apps by the given search_string

        Apps are then displayed in a pager in which the user can get more
        info on a selected app.

    Args:
        config (Config): config object used for getting .two1 information
        search_string (str): string used to search for apps
    """
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)
    if search_string is None:
        click.secho(UxString.list_all, fg="green")

    current_page = 0
    total_pages = get_search_results(client, search_string, current_page)
    if total_pages < 1:
        return

    while 0 <= current_page < total_pages:
        try:
            prompt_resp = click.prompt(UxString.pagination, type=str)
            next_page = get_next_page(prompt_resp, current_page)
            if next_page == -1:
                model_id = prompt_resp
                display_search_info(config, client, model_id)
            elif next_page >= total_pages or next_page < 0:
                continue
            else:
                get_search_results(client, search_string, next_page)
                current_page = next_page

        except click.exceptions.Abort:
            return
Exemplo n.º 9
0
def _rate(config, app_id, rating):
    """ Rate an app listed in the marketplace

    Args:
        config (Config): Config object used for user specific information
        app_id (str): Unique app id used to identify which app to rate
        rating (int): rating number (1-5)

    Raises:
        ServerRequestError: If any other server error occurs other than a 404
    """
    if rating < 1 or rating > 5:
        click.secho(UxString.bad_rating, fg="red")
        return

    client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                             config.machine_auth,
                                             config.username)
    try:
        client.rate_app(app_id, rating)
    except ServerRequestError as e:
        if e.status_code == 404:
            click.secho(UxString.rating_app_not_found.format(app_id))
            return
        raise e

    click.secho(UxString.rating_success.format(rating, app_id))
Exemplo n.º 10
0
def _log(config, debug):
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)

    prints = []

    logs = get_bc_logs(client, debug)
    prints.extend(logs)

    output = "\n".join(prints)
    config.echo_via_pager(output)

    return logs
Exemplo n.º 11
0
def _publish(config, manifest_path, marketplace, skip, overrides):
    """ Publishes application by uploading the manifest to the given marketplace

    Args:
        config (Config): config object used for getting .two1 information
        manifest_path (str): the path to the manifest file
        marketplace (str): the zerotier marketplace name
        skip (bool): skips strict checking of manifest file
        overrides (dict): Dictionary containing the key/value pairs will be overridden
        in the manifest.
    """
    try:
        manifest_json = check_app_manifest(manifest_path, overrides,
                                           marketplace)
        app_url = urlparse(manifest_json["host"])
        app_ip = app_url.path.split(":")[0]

        if not skip:
            address = get_zerotier_address(marketplace)

            if address != app_ip:
                if not click.confirm(
                        UxString.wrong_ip.format(app_ip, address, app_ip)):
                    click.secho(
                        UxString.switch_host.format(manifest_path, app_ip,
                                                    address))
                    return

    except ValueError:
        return
    except ValidationError as e:
        click.secho(UxString.bad_manifest.format(manifest_path, e.args[0],
                                                 UxString.publish_docs_url),
                    fg="red")
        return

    app_name = manifest_json["info"]["title"]
    app_endpoint = "{}://{}{}".format(manifest_json["schemes"][0],
                                      manifest_json["host"],
                                      manifest_json["basePath"])

    click.secho(
        UxString.publish_start.format(app_name, app_endpoint, marketplace))
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)
    payload = {"manifest": manifest_json, "marketplace": marketplace}
    response = client.publish(payload)
    if response.status_code == 201:
        click.secho(UxString.publish_success.format(app_name, marketplace))
Exemplo n.º 12
0
def _status(config, detail):
    client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth,
                                             config.username)

    status = {
        "account": status_account(config),
        "mining": status_mining(config, client),
        "wallet": status_wallet(config, client, detail)
    }

    config.log("")
    # status_endpoints(config)
    # status_bought_endpoints(config)

    return status
Exemplo n.º 13
0
    def _check_notifications(config, *args, **kwargs):

        res = func(config, *args, **kwargs)

        try:
            client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                                     config.machine_auth,
                                                     config.username)
            notifications = client.get_notifications(config.username)
            notification_json = notifications.json()
            urgent_notifications = notification_json["urgent_count"]
            if urgent_notifications > 0:
                click.secho(
                    UxString.unread_notifications.format(urgent_notifications))
        except:
            pass

        return res
Exemplo n.º 14
0
def start_cpu_mining(config):
    """ Mines bitcoin on the command line by using the CPU of the system

    CPU mining, or foreground mining, is when the pool sets the difficulty
    very low and the CPU finds a valid solution.

    Args:
        config (Config): config object used for getting .two1 information
    """

    client = rest_client.TwentyOneRestClient(cmd_config.TWO1_HOST,
                                             config.machine_auth,
                                             config.username)

    enonce1, enonce2_size, reward = set_payout_address(config, client)

    start_time = time.time()
    config.log(UxString.mining_start.format(config.username, reward))



    work = get_work(config, client)

    found_share = mine_work(work, enonce1=enonce1, enonce2_size=enonce2_size)

    paid_satoshis = save_work(client, found_share, config.username)

    end_time = time.time()
    duration = end_time - start_time

    config.log(
        UxString.mining_success.format(config.username, paid_satoshis, duration),
        fg="magenta")

    click.echo(UxString.mining_status)
    status.status_wallet(config, client)

    click.echo(UxString.mining_finish.format(
        click.style("21 status", bold=True), click.style("21 buy", bold=True)))
Exemplo n.º 15
0
def _join(config, network):
    """ Joins the given zerotier network

    Args:
        config (Config): config object used for getting .two1 information
        network (str): the name of the network being joined. Defaults to 21market

    Raises:
        ServerRequestError: if server returns an error code other than 401
    """
    client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                             config.machine_auth,
                                             config.username)

    try:
        config.log(UxString.update_superuser)
        user_platform = platform.system()
        if user_platform != "Darwin":
            start_zerotier_command = [
                "sudo", "service", "zerotier-one", "start"
            ]
            subprocess.check_output(start_zerotier_command)
        zt_device_address = zerotier.device_address()
        response = client.join(network, zt_device_address)
        if response.ok:
            join_command = [
                "sudo", "zerotier-cli", "join",
                response.json().get("networkid")
            ]
            subprocess.check_output(join_command)
            config.log(UxString.successful_join.format(click.style(network, fg="magenta")))
    except ServerRequestError as e:
        if e.status_code == 401:
            config.log(UxString.invalid_network)
        else:
            raise e
    except subprocess.CalledProcessError as e:
        config.log(str(e))
Exemplo n.º 16
0
def _delete_app(config, app_id):
    """ Deletes an app that has been published to the 21 marketplace

    Args:
        config (Config): config object used for getting .two1 information.
        app_id (str): a unique string that identifies the application.
    """
    if click.confirm(UxString.delete_confirmation.format(app_id)):
        client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                                 config.machine_auth,
                                                 config.username)
        try:
            resp = client.delete_app(config.username, app_id)
            resp_json = resp.json()
            deleted_title = resp_json["deleted_title"]
            click.secho(UxString.delete_success.format(app_id, deleted_title))
        except ServerRequestError as e:
            if e.status_code == 404:
                click.secho(UxString.delete_app_not_exist.format(app_id),
                            fg="red")
            elif e.status_code == 403:
                click.secho(UxString.delete_app_no_permissions.format(app_id),
                            fg="red")
Exemplo n.º 17
0
def _list(config):
    """ Lists all of the apps that the user has rated

    If no apps have been rated, then an empty formatted list is printed

    Args:
        config (Config): Config object used for user specific information

    Raises:
        ServerRequestError: If server error occurs other than a 404
    """
    click.secho(UxString.rating_list)

    client = rest_client.TwentyOneRestClient(TWO1_HOST,
                                             config.machine_auth,
                                             config.username)
    try:
        ratings = client.get_ratings()
        headers = ["id", "App title", "Creator", "Rating", "Rating Date"]
        ratings = ratings.json()["ratings"]
        rows = []
        for rating in ratings:
            rating_date = datetime.datetime.fromtimestamp(
                rating["rating_date"]).strftime("%Y-%m-%d %H:%M")
            rating_score = "{}/5".format(rating["rating"])
            rows.append([rating["app_id"], rating["app_title"], rating["app_creator"],
                         rating_score, rating_date])

        click.echo(tabulate(rows, headers, tablefmt="grid"))

    except ServerRequestError as e:
        if e.status_code == 404:
            click.secho(UxString.no_ratings)
            return
        else:
            raise e
Exemplo n.º 18
0
Arquivo: buy.py Projeto: 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()))
Exemplo n.º 19
0
from flask.ext.admin.contrib.sqla import ModelView
from flask.ext.login import LoginManager
from flask.ext.admin.contrib.fileadmin import FileAdmin

# 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.lib.server import rest_client
from two1.commands.config import Config
from two1.commands.config import TWO1_HOST

conf = Config()
host = TWO1_HOST
client = rest_client.TwentyOneRestClient(host, conf.machine_auth,
                                         conf.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(conf, client)

        if request.method == 'POST':
            print(request.form)
            if request.form['submit'] == 'Flush Earnings':
                flush_message = self.doFlush()
            else:
                if status_mining[
Exemplo n.º 20
0
import json

from flask import Flask
from flask import request

from two1.lib.server import rest_client
from two1.commands.config import TWO1_HOST
from two1.commands.config import Config
from two1.lib.wallet import Wallet
from two1.lib.bitserv.flask import Payment

app = Flask(__name__)
wallet = Wallet()
config = Config()
payment = Payment(app, wallet)
client = rest_client.TwentyOneRestClient(TWO1_HOST, config.machine_auth, config.username)

class Charity(object):
    name = ""
    address = ""

    # The class "constructor" - It's actually an initializer
    def __init__(self, name, address):
        self.name = name
        self.address = address

bitGive = Charity("Bit Give", "1PEoUKNxTZsc5rFSQvQjeTVwDE9vEDCRWm")
charities = [bitGive]

# endpoint to look up avaialable charities to donate to
@app.route('/charities', methods=['GET'])