Ejemplo n.º 1
0
    async def sanity_check(self):

        async with self.pool.acquire() as con:
            rows = await con.fetch(
                "SELECT * FROM transactions WHERE (last_status = 'unconfirmed' OR last_status IS NULL) "
                "AND created < (now() AT TIME ZONE 'utc') - interval '5 minutes'"
            )
        for row in rows:
            # check if the transaction is still in the network
            tx = await self.eth.eth_getTransactionByHash(
                row['transaction_hash'])
            if tx is None:
                # the transaction no longer exists on the network
                await self.send_transaction_notifications({
                    'hash':
                    row['transaction_hash'],
                    'to':
                    row['to_address'],
                    'from':
                    row['from_address'],
                    'blockNumber':
                    None,
                    'value':
                    row['value'],
                    'nonce':
                    row['nonce'],
                    'gas':
                    row['estimated_gas_cost'],
                    'gasPrice':
                    '0x1',
                    'error':
                    True
                })
            else:
                # check if the transactions has actually been confirmed
                if tx['blockNumber'] is not None:
                    await self.send_transaction_notifications(tx)
                else:
                    # update the nonce if it doesn't match what is in the database
                    # (NOTE: this shouldn't really be the case ever, this is mainly
                    # for checking on tx's from before the nonce was stored)
                    if parse_int(tx['nonce']) != row['nonce']:
                        log.info(
                            "Fixing stored nonce value for tx: {} (old: {}, new: {})"
                            .format(tx['hash'], row['nonce'],
                                    parse_int(tx['nonce'])))
                        async with self.pool.acquire() as con:
                            await con.execute(
                                "UPDATE transactions SET nonce = $1 WHERE transaction_hash = $2",
                                parse_int(tx['nonce']),
                                row['transaction_hash'])
                    # log that there is an error
                    log.error(
                        "Found long standing unconfirmed transaction: {}".
                        format(tx['hash']))
    async def test_get_balance(self):

        addr = '0x39bf9e501e61440b4b268d7b2e9aa2458dd201bb'
        val = 761751855997712

        await self.faucet(addr, val)

        resp = await self.fetch('/balance/{}'.format(addr))

        self.assertEqual(resp.code, 200)

        data = json_decode(resp.body)
        self.assertEqual(parse_int(data['confirmed_balance']), val)
        self.assertEqual(parse_int(data['unconfirmed_balance']), val)
    async def test_get_balance_with_unconfirmed_txs(self):

        addr = '0x39bf9e501e61440b4b268d7b2e9aa2458dd201bb'
        val = 761751855997712

        await self.faucet(addr, val)

        async with self.pool.acquire() as con:
            await con.execute("INSERT INTO transactions VALUES ('0x2f321aa116146a9bc62b61c76508295f708f42d56340c9e613ebfc27e33f240c', $1, $2, 0, $3)",
                              FAUCET_ADDRESS, addr, val)

        resp = await self.fetch('/balance/{}'.format(addr))

        self.assertEqual(resp.code, 200)

        data = json_decode(resp.body)
        self.assertEqual(parse_int(data['confirmed_balance']), val)
        self.assertEqual(parse_int(data['unconfirmed_balance']), val * 2)
Ejemplo n.º 4
0
async def get_reports(request, conf, current_user):
    page = parse_int(request.args.get('page', None)) or 1
    if page < 1:
        page = 1
    limit = 10
    offset = (page - 1) * limit

    sql = ("SELECT * FROM reports "
           "ORDER BY report_id DESC "
           "OFFSET $1 LIMIT $2")
    args = [offset, limit]
    count_sql = ("SELECT COUNT(*) FROM reports")
    count_args = []
    async with conf.db.id.acquire() as con:
        rows = await con.fetch(sql, *args)
        count = await con.fetchrow(count_sql, *count_args)

    reports = []
    for row in rows:
        async with conf.db.id.acquire() as con:
            reporter = await con.fetchrow(
                "SELECT * FROM users WHERE token_id = $1",
                row['reporter_token_id'])
            reportee = await con.fetchrow(
                "SELECT * FROM users WHERE token_id = $1",
                row['reportee_token_id'])

        reporter = fix_avatar_for_user(conf.urls.id, dict(reporter))
        reportee = fix_avatar_for_user(conf.urls.id, dict(reportee))
        reports.append({
            'reporter': reporter,
            'reportee': reportee,
            'details': row['details'],
            'date': row['date']
        })

    total_pages = (count['count'] // limit) + (0 if count['count'] %
                                               limit == 0 else 1)

    def get_qargs(page=page, as_list=False, as_dict=False):
        qargs = {'page': page}
        if as_dict:
            return qargs
        if as_list:
            return qargs.items()
        return urlencode(qargs)

    return html(await env.get_template("reports.html").render_async(
        reports=reports,
        current_user=current_user,
        environment=conf.name,
        page="reports",
        total=count['count'],
        total_pages=total_pages,
        current_page=page,
        get_qargs=get_qargs))
Ejemplo n.º 5
0
async def get_txs(request, conf, user):
    page = parse_int(request.args.get('page', None)) or 1
    if page < 1:
        page = 1
    limit = 10
    offset = (page - 1) * limit
    where_clause = ''
    filters = [
        f for f in request.args.getlist('filter', [])
        if f in ['confirmed', 'unconfirmed', 'error']
    ]
    if filters:
        where_clause = "WHERE " + " OR ".join("status = '{}'".format(f)
                                              for f in filters)
        if 'unconfirmed' in filters:
            where_clause += " OR status IS NULL"
    async with conf.db.eth.acquire() as con:
        rows = await con.fetch(
            "SELECT * FROM transactions {} ORDER BY created DESC OFFSET $1 LIMIT $2"
            .format(where_clause), offset, limit)
        count = await con.fetchrow(
            "SELECT COUNT(*) FROM transactions {}".format(where_clause))
    txs = []
    for row in rows:
        tx = dict(row)
        tx['from_user'] = await get_token_user_from_payment_address(
            conf, tx['from_address'])
        tx['to_user'] = await get_token_user_from_payment_address(
            conf, tx['to_address'])
        txs.append(tx)

    total_pages = (count['count'] // limit) + (0 if count['count'] %
                                               limit == 0 else 1)

    def get_qargs(page=page, filters=filters, as_list=False, as_dict=False):
        qargs = {'page': page}
        if filters:
            qargs['filter'] = filters
        if as_dict:
            return qargs
        if as_list:
            return qargs.items()
        return urlencode(qargs, True)

    return html(await env.get_template("txs.html").render_async(
        txs=txs,
        current_user=user,
        environment=conf.name,
        page="txs",
        total=count['count'],
        total_pages=total_pages,
        current_page=page,
        active_filters=filters,
        get_qargs=get_qargs))
Ejemplo n.º 6
0
def to_eth(wei, points=18):
    wei = str(parse_int(wei))
    pad = 18 - len(wei)
    if pad < 0:
        eth = wei[:abs(pad)] + "." + wei[abs(pad):abs(pad) + points]
    else:
        eth = "0." + wei.zfill(18)[:points]
    while eth.endswith("0"):
        eth = eth[:-1]
    if eth.endswith("."):
        eth += "0"
    return eth
Ejemplo n.º 7
0
async def check_account_nonces(conf, dryrun=False):
    async with conf.db.id.acquire() as con:
        users = await con.fetch("SELECT token_id, payment_address FROM users")

    last_percent = -1
    async with conf.db.eth.acquire() as con:
        tr = con.transaction()
        await tr.start()
        for i, user in enumerate(users):
            percent = int((i / len(users)) * 100)
            if percent != last_percent:
                print("Progress: {}/{} ({}%)".format(i, len(users), percent))
                last_percent = percent
            from_address = user['payment_address']
            resp = await app.http.post(
                conf.urls.node,
                headers={'Content-Type': 'application/json'},
                data=json.dumps({
                    "jsonrpc": "2.0",
                    "id": random.randint(0, 1000000),
                    "method": "eth_getTransactionCount",
                    "params": [from_address]
                }).encode('utf-8'))
            if resp.status == 200:
                data = await resp.json()
                if 'result' in data and data['result'] is not None:
                    nonce = parse_int(data['result'])

                    res = await con.execute(
                        "UPDATE transactions SET last_status = 'error' WHERE from_address = $1 AND nonce >= $2 AND last_status != 'error'",
                        from_address, nonce)
                    if res != "UPDATE 0":
                        print("{}|{}: {}".format(user['token_id'],
                                                 from_address, res))

        if dryrun:
            await tr.rollback()
        else:
            await tr.commit()
Ejemplo n.º 8
0
    async def post(self):

        if 'reputation' not in self.application.config or 'id' not in self.application.config['reputation']:
            raise HTTPError(404)

        try:
            address = self.verify_request()
        except JSONHTTPError:
            raise HTTPError(404)

        if address != self.application.config['reputation']['id']:
            raise HTTPError(404)

        if not all(x in self.json for x in ['address', 'score', 'count']):
            raise JSONHTTPError(400, body={'errors': [{'id': 'bad_arguments', 'message': 'Bad Arguments'}]})

        token_id = self.json['address']
        if not validate_address(token_id):
            raise JSONHTTPError(400, body={'errors': [{'id': 'invalid_address', 'message': 'Invalid Address'}]})

        count = self.json['count']
        count = parse_int(count)
        if count is None:
            raise JSONHTTPError(400, body={'errors': [{'id': 'invalid_count', 'message': 'Invalid Count'}]})

        score = self.json['score']
        if isinstance(score, str) and validate_decimal_string(score):
            score = Decimal(score)
        if not isinstance(score, (int, float, Decimal)):
            raise JSONHTTPError(400, body={'errors': [{'id': 'invalid_score', 'message': 'Invalid Score'}]})

        async with self.db:
            await self.db.execute("UPDATE apps SET reputation_score = $1, review_count = $2 WHERE token_id = $3",
                                  score, count, token_id)
            await self.db.commit()

        self.set_status(204)
Ejemplo n.º 9
0
    def test_parse_float_string(self):

        self.assertEqual(parse_int("12345.567678"), 12345)
Ejemplo n.º 10
0
    async def create_transaction_skeleton(self,
                                          *,
                                          to_address,
                                          from_address,
                                          value=0,
                                          nonce=None,
                                          gas=None,
                                          gas_price=None,
                                          data=None):

        if not validate_address(from_address):
            raise JsonRPCInvalidParamsError(data={
                'id': 'invalid_from_address',
                'message': 'Invalid From Address'
            })

        if not validate_address(to_address):
            raise JsonRPCInvalidParamsError(data={
                'id': 'invalid_to_address',
                'message': 'Invalid To Address'
            })

        if value:
            value = parse_int(value)
            if value is None:
                raise JsonRPCInvalidParamsError(data={
                    'id': 'invalid_value',
                    'message': 'Invalid Value'
                })

        # check optional arguments

        if nonce is None:
            # check cache for nonce
            nonce = self.redis.get("nonce:{}".format(from_address))
            if nonce:
                nonce = int(nonce)
            # get the network's value too
            nw_nonce = await self.eth.eth_getTransactionCount(from_address)
            if nonce is None or nw_nonce > nonce:
                # if not cached, or the cached value is lower than
                # the network value, use the network value!
                nonce = nw_nonce
        else:
            nonce = parse_int(nonce)
            if nonce is None:
                raise JsonRPCInvalidParamsError(data={
                    'id': 'invalid_nonce',
                    'message': 'Invalid Nonce'
                })

        if data is not None:
            if isinstance(data, int):
                data = hex(data)
            if isinstance(data, str):
                try:
                    data = data_decoder(data)
                except binascii.Error:
                    pass
            if not isinstance(data, bytes):
                raise JsonRPCInvalidParamsError(data={
                    'id': 'invalid_data',
                    'message': 'Invalid Data field'
                })
        else:
            data = b''

        if gas is None:
            # if there is data the default startgas value wont be enough
            if data:
                gas = await self.eth.eth_estimateGas(from_address,
                                                     to_address,
                                                     nonce=nonce,
                                                     data=data)
            else:
                gas = DEFAULT_STARTGAS
        else:
            gas = parse_int(gas)
            if gas is None:
                raise JsonRPCInvalidParamsError(data={
                    'id': 'invalid_gas',
                    'message': 'Invalid Gas'
                })

        if gas_price is None:
            gas_price = DEFAULT_GASPRICE
        else:
            gas_price = parse_int(gas_price)
            if gas_price is None:
                raise JsonRPCInvalidParamsError(data={
                    'id': 'invalid_gas_price',
                    'message': 'Invalid Gas Price'
                })

        tx = create_transaction(nonce=nonce,
                                gasprice=gas_price,
                                startgas=gas,
                                to=to_address,
                                value=value,
                                data=data)

        transaction = encode_transaction(tx)

        return transaction
Ejemplo n.º 11
0
    def test_parse_int_string(self):

        self.assertEqual(parse_int("12345"), 12345)
Ejemplo n.º 12
0
    def test_parse_unicode(self):

        self.assertEqual(parse_int(u'12345'), 12345)
Ejemplo n.º 13
0
    def test_parse_bytes(self):

        self.assertEqual(parse_int(b"12345"), 12345)
Ejemplo n.º 14
0
    def test_parse_misc(self):

        self.assertEqual(parse_int({}), None)
Ejemplo n.º 15
0
    def test_parse_none(self):

        self.assertEqual(parse_int(None), None)
Ejemplo n.º 16
0
    def do_POST(self):

        # TODO: figure out why read is blocking here
        data = self.rfile.read(len(self.rfile.peek()))
        data = data.decode('utf-8')
        data = json.loads(data)

        if self.path == "/v1/tx/skel":

            gas_price = parse_int(
                data['gas_price']) if 'gas_price' in data else DEFAULT_GASPRICE
            gas = parse_int(data['gas']) if 'gas' in data else DEFAULT_STARTGAS
            nonce = parse_int(data['nonce']) if 'nonce' in data else 0

            if 'value' not in data or 'from' not in data or 'to' not in data:
                self.write_data(
                    400, {
                        'errors': [{
                            'id': 'bad_arguments',
                            'message': 'Bad Arguments'
                        }]
                    })
                return
            value = parse_int(data['value'])
            to_address = data['to']
            from_address = data['from']

            if not validate_address(to_address):
                self.write_data(
                    400, {
                        'errors': [{
                            'id': 'invalid_to_address',
                            'message': 'Invalid To Address'
                        }]
                    })
                return
            if not validate_address(from_address):
                self.write_data(
                    400, {
                        'errors': [{
                            'id': 'invalid_from_address',
                            'message': 'Invalid From Address'
                        }]
                    })
                return

            tx = create_transaction(nonce=nonce,
                                    gasprice=gas_price,
                                    startgas=gas,
                                    to=to_address,
                                    value=value)

            transaction = encode_transaction(tx)

            self.write_data(
                200, {
                    "tx_data": {
                        "nonce": hex(nonce),
                        "from": from_address,
                        "to": to_address,
                        "value": hex(value),
                        "startGas": hex(gas),
                        "gasPrice": hex(gas_price)
                    },
                    "tx": transaction
                })

        elif self.path == "/v1/tx":

            tx = decode_transaction(data['tx'])

            if 'signature' in data:

                sig = data_decoder(data['signature'])

                add_signature_to_transaction(tx, sig)

            self.write_data(200, {"tx_hash": data_encoder(tx.hash)})

        else:

            self.write_data(404)
Ejemplo n.º 17
0
    async def send_transaction_notifications(self, transaction):

        to_address = transaction['to']
        from_address = transaction['from']

        token_ids = []
        overwritten_tx_hash = None
        overwritten_tx_hash_to_address = None
        overwritten_tx_token_ids = []
        sender_token_id = None
        async with self.pool.acquire() as con:
            # find if we have a record of this tx by checking the from address and nonce
            db_txs = await con.fetch(
                "SELECT * FROM transactions WHERE "
                "from_address = $1 AND nonce = $2", from_address,
                parse_int(transaction['nonce']))
            if len(db_txs) > 1:
                # see if one has the same hash
                db_tx = await con.fetchrow(
                    "SELECT * FROM transactions WHERE "
                    "from_address = $1 AND nonce = $2 AND transaction_hash = $3 AND (last_status != $4 OR last_status IS NULL)",
                    from_address, parse_int(transaction['nonce']),
                    transaction['hash'], 'error')
                if db_tx is None:
                    # find if there are any that aren't marked as error
                    no_error = await con.fetch(
                        "SELECT * FROM transactions WHERE "
                        "from_address = $1 AND nonce = $2 AND transaction_hash != $3 AND (last_status != $4 OR last_status IS NULL)",
                        from_address, parse_int(transaction['nonce']),
                        transaction['hash'], 'error')
                    if len(no_error) == 1:
                        db_tx = no_error[0]
                    elif len(no_error) != 0:
                        log.warning(
                            "Multiple transactions from '{}' exist with nonce '{}' in unknown state"
                        )

            elif len(db_txs) == 1:
                db_tx = db_txs[0]
            else:
                db_tx = None

            to_ids = await con.fetch(
                "SELECT token_id FROM notification_registrations WHERE eth_address = $1",
                to_address)
            to_ids = [row['token_id'] for row in to_ids]
            token_ids.extend(to_ids)

            from_ids = await con.fetch(
                "SELECT token_id FROM notification_registrations WHERE eth_address = $1",
                from_address)
            from_ids = [row['token_id'] for row in from_ids]
            token_ids.extend(from_ids)

            # check if we have this transaction saved in the database with
            # a specific token_id for the sender
            if db_tx:
                sender_token_id = db_tx['sender_token_id']
                # make sure the tx hash we have already matches this
                if transaction['hash'] != db_tx['transaction_hash']:
                    # only worry about this if it wasn't set as an error already
                    if db_tx['last_status'] != 'error':
                        log.warning("found overwritten transaction!")
                        log.warning("tx from: {}".format(from_address))
                        log.warning("nonce: {}".format(
                            parse_int(transaction['nonce'])))
                        log.warning("old tx hash: {}".format(
                            db_tx['transaction_hash']))
                        log.warning("new tx hash: {}".format(
                            transaction['hash']))
                        log.warning("old tx status: {}".format(
                            db_tx['last_status']))

                        # if not we have an overwrite
                        overwritten_tx_hash = db_tx['transaction_hash']
                        overwritten_tx_hash_to_address = db_tx['to_address']
                        if to_address != overwritten_tx_hash_to_address:
                            old_to_ids = await con.fetch(
                                "SELECT token_id FROM notification_registrations WHERE eth_address = $1",
                                db_tx['to_address'])
                            old_to_ids = [
                                row['token_id'] for row in old_to_ids
                            ]
                            overwritten_tx_token_ids.extend(old_to_ids)
                        else:
                            overwritten_tx_token_ids.extend(to_ids)
                        overwritten_tx_token_ids.extend(from_ids)
                        await con.execute(
                            "UPDATE transactions SET error = 1, last_status = 'error' WHERE transaction_hash = $1",
                            db_tx['transaction_hash'])
                    # reset db_tx so we store the new tx later on
                    db_tx = None
                else:
                    new_status = 'error' if 'error' in transaction else (
                        'confirmed' if transaction['blockNumber'] is not None
                        else 'unconfirmed')
                    # check last_status to see if we need to send this as a pn or not
                    # and update the status
                    if db_tx['last_status'] == new_status:
                        # we've already sent a notification for this state
                        # so there's no need to send another
                        return
                    log.info("setting {} status on transaction: {}".format(
                        new_status, transaction['hash']))
                    await con.execute(
                        "UPDATE transactions SET {}"
                        "last_status = $1 "
                        "WHERE transaction_hash = $2".format(
                            "confirmed = (now() AT TIME ZONE 'utc'), "
                            if new_status == 'confirmed' else ''), new_status,
                        transaction['hash'])

            # if there are interested parties in the new tx, add it to the database
            if db_tx is None and (token_ids or any(
                    addr in self.callbacks
                    for addr in [to_address, from_address])):
                log.info("storing info about new interesting transaction")
                log.warning("tx from: {}".format(from_address))
                log.warning("nonce: {}".format(transaction['nonce']))
                log.warning("new tx hash: {}".format(transaction['hash']))

                # this could potentially be an overwrite of an overwrite putting the original
                # transaction back in as a non-error, in this case the last_status value is
                # simply updated from the original tx
                await con.execute(
                    "INSERT INTO transactions "
                    "(transaction_hash, from_address, to_address, nonce, value, estimated_gas_cost, sender_token_id, last_status) "
                    "VALUES ($1, $2, $3, $4, $5, $6, $7, $8) "
                    "ON CONFLICT (transaction_hash) DO UPDATE "
                    "SET last_status = EXCLUDED.last_status",
                    transaction['hash'], from_address, to_address,
                    parse_int(transaction['nonce']),
                    str(parse_int(transaction['value'])),
                    str(
                        parse_int(transaction['gas']) *
                        parse_int(transaction['gasPrice'])), sender_token_id,
                    'confirmed' if transaction['blockNumber'] is not None else
                    'unconfirmed')

        # if the tx was overwritten, send the tx cancel message first
        if overwritten_tx_hash:
            await self.send_notifications(
                [overwritten_tx_hash_to_address, from_address],
                overwritten_tx_token_ids, {
                    'hash': overwritten_tx_hash,
                    'to': overwritten_tx_hash_to_address,
                    'from': from_address,
                    'blockNumber': None,
                    'value': None,
                    'error': 'overwritten'
                }, sender_token_id)

        await self.send_notifications([to_address, from_address], token_ids,
                                      transaction, sender_token_id)
Ejemplo n.º 18
0
    def get_balance(self, address, **kwargs):

        resp = self._fetch("/v1/balance/{}".format(address), "GET", **kwargs)
        return parse_int(resp["confirmed_balance"]), parse_int(resp["unconfirmed_balance"])
Ejemplo n.º 19
0
    def test_parse_int_no_leading_zeros_string(self):

        self.assertEqual(parse_int("0123"), None)
Ejemplo n.º 20
0
    def test_parse_zero_int_string(self):

        self.assertEqual(parse_int("0"), 0)
Ejemplo n.º 21
0
    def test_parse_negative_int_string(self):

        self.assertEqual(parse_int("-12345"), -12345)
Ejemplo n.º 22
0
async def update_categories(request, conf, current_user):

    category_name = request.form.get('category', None)
    category_tag = request.form.get('tag', None)
    category_id = request.form.get('id', None)
    should_remove = request.form.get('remove', None)
    language = 'en'

    error = None

    if should_remove is not None:

        if category_id is None:
            error = "Missing category id"
        else:
            category_id = parse_int(category_id)

            async with conf.db.id.acquire() as con:
                await con.fetchval(
                    "DELETE FROM categories WHERE category_id = $1",
                    category_id)

    elif category_tag is None or category_name is None:
        error = "Missing name and tag"

    else:

        # force tags to be lowercase
        category_tag = category_tag.lower()

        if category_id is None:
            try:
                async with conf.db.id.acquire() as con:
                    category_id = await con.fetchval(
                        "INSERT INTO categories (tag) VALUES ($1) RETURNING category_id",
                        category_tag)
            except UniqueViolationError:
                error = "Tag already exists"

        # check again because we only update if the category_id was supplied by the user
        # or the insert statement above succeeded.
        if category_id is not None:

            category_id = parse_int(category_id)

            async with conf.db.id.acquire() as con:
                await con.execute(
                    "INSERT INTO category_names (category_id, name, language) VALUES ($1, $2, $3) "
                    "ON CONFLICT (category_id, language) DO UPDATE SET name = EXCLUDED.name",
                    category_id, category_name, language)

    get_sql = (
        "SELECT * FROM categories "
        "JOIN category_names ON categories.category_id = category_names.category_id AND category_names.language = $1"
        "ORDER BY categories.tag ASC ")

    async with conf.db.id.acquire() as con:
        rows = await con.fetch(get_sql, language)

    return html(await env.get_template("categories.html").render_async(
        categories=rows,
        error=error,
        current_user=current_user,
        environment=conf.name,
        page="categories"))
Ejemplo n.º 23
0
    def test_parse_hex_string(self):

        self.assertEqual(parse_int("0x12345"), 74565)
Ejemplo n.º 24
0
async def liveordev(request, conf, user):

    # get statistics

    async with conf.db.eth.acquire() as con:
        tx24h = await con.fetchrow(
            "SELECT COUNT(*) FROM transactions WHERE created > (now() AT TIME ZONE 'utc') - interval '24 hours'"
        )
        tx7d = await con.fetchrow(
            "SELECT COUNT(*) FROM transactions WHERE created > (now() AT TIME ZONE 'utc') - interval '7 days'"
        )
        tx1m = await con.fetchrow(
            "SELECT COUNT(*) FROM transactions WHERE created > (now() AT TIME ZONE 'utc') - interval '1 month'"
        )
        txtotal = await con.fetchrow("SELECT COUNT(*) FROM transactions")
        last_block = await con.fetchrow("SELECT * FROM last_blocknumber")

    async with conf.db.id.acquire() as con:
        u24h = await con.fetchrow(
            "SELECT COUNT(*) FROM users WHERE created > (now() AT TIME ZONE 'utc') - interval '24 hours'"
        )
        u7d = await con.fetchrow(
            "SELECT COUNT(*) FROM users WHERE created > (now() AT TIME ZONE 'utc') - interval '7 days'"
        )
        u1m = await con.fetchrow(
            "SELECT COUNT(*) FROM users WHERE created > (now() AT TIME ZONE 'utc') - interval '1 month'"
        )
        utotal = await con.fetchrow("SELECT COUNT(*) FROM users")

    users = {
        'day': u24h['count'],
        'week': u7d['count'],
        'month': u1m['count'],
        'total': utotal['count']
    }
    txs = {
        'day': tx24h['count'],
        'week': tx7d['count'],
        'month': tx1m['count'],
        'total': txtotal['count']
    }

    status = {}
    block = {'db': last_block['blocknumber']}
    # check service status
    # eth
    try:
        resp = await app.http.get('{}/v1/balance/0x{}'.format(
            conf.urls.eth, '0' * 40),
                                  timeout=SERVICE_CHECK_TIMEOUT)
        if resp.status == 200:
            status['eth'] = "OK"
        else:
            status['eth'] = "Error: {}".format(resp.status)
    except asyncio.TimeoutError:
        status['eth'] = "Error: timeout"
    # id
    try:
        resp = await app.http.get('{}/v1/user/0x{}'.format(
            conf.urls.id, '0' * 40),
                                  timeout=SERVICE_CHECK_TIMEOUT)
        if resp.status == 404:
            status['id'] = "OK"
        else:
            status['id'] = "Error: {}".format(resp.status)
    except asyncio.TimeoutError:
        status['id'] = "Error: timeout"
    # dir
    try:
        resp = await app.http.get('{}/v1/apps/'.format(conf.urls.dir),
                                  timeout=SERVICE_CHECK_TIMEOUT)
        if resp.status == 200:
            status['dir'] = "OK"
        else:
            status['dir'] = "Error: {}".format(resp.status)
    except asyncio.TimeoutError:
        status['dir'] = "Error: timeout"
    # rep
    try:
        resp = await app.http.get('{}/v1/timestamp'.format(conf.urls.rep),
                                  timeout=SERVICE_CHECK_TIMEOUT)
        if resp.status == 200:
            status['rep'] = "OK"
        else:
            status['rep'] = "Error: {}".format(resp.status)
    except asyncio.TimeoutError:
        status['rep'] = "Error: timeout"
    # node
    try:
        resp = await app.http.post(
            conf.urls.node,
            headers={'Content-Type': 'application/json'},
            data=json.dumps({
                "jsonrpc": "2.0",
                "id": random.randint(0, 1000000),
                "method": "eth_blockNumber",
                "params": []
            }).encode('utf-8'))
        if resp.status == 200:
            data = await resp.json()
            if 'result' in data:
                if data['result'] is not None:
                    status['node'] = "OK"
                    block['node'] = parse_int(data['result'])
            elif 'error' in data:
                status['node'] = data['error']
        else:
            status['node'] = "Error: {}".format(resp.status)
    except asyncio.TimeoutError:
        status['node'] = "Error: timeout"

    return html(await env.get_template("index.html").render_async(
        current_user=user,
        environment=conf.name,
        page="home",
        txs=txs,
        users=users,
        status=status,
        block=block))
Ejemplo n.º 25
0
    def test_parse_float(self):

        self.assertEqual(parse_int(12345.45675), 12345)
Ejemplo n.º 26
0
async def get_apps(request, conf, current_user):
    page = parse_int(request.args.get('page', None)) or 1
    if page < 1:
        page = 1
    limit = 10
    offset = (page - 1) * limit
    order_by = request.args.get('order_by', None)
    search_query = request.args.get('query', None)
    filter_by = request.args.get('filter', None)
    order = ('created', 'DESC')
    if order_by:
        if order_by in sortable_apps_columns:
            if order_by[0] == '-':
                order = (order_by[1:], 'ASC'
                         if order_by[1:] in negative_apps_columns else 'DESC')
            else:
                order = (order_by, 'DESC'
                         if order_by in negative_apps_columns else 'ASC')

    if search_query:
        # strip punctuation
        query = ''.join(
            [c for c in search_query if c not in string.punctuation])
        # split words and add in partial matching flags
        query = '|'.join(
            ['{}:*'.format(word) for word in query.split(' ') if word])
        args = [offset, limit, query]
        if order_by:
            query_order = "ORDER BY {} {}".format(*order)
        else:
            # default order by rank
            query_order = "ORDER BY TS_RANK_CD(t1.tsv, TO_TSQUERY($3)) DESC, name, username"
        sql = ("SELECT * FROM "
               "(SELECT * FROM users, TO_TSQUERY($3) AS q "
               "WHERE (tsv @@ q) AND is_app = true) AS t1 "
               "{} "
               "OFFSET $1 LIMIT $2".format(query_order))
        count_args = [query]
        count_sql = ("SELECT COUNT(*) FROM users, TO_TSQUERY($1) AS q "
                     "WHERE (tsv @@ q) AND is_app = true")
        async with conf.db.id.acquire() as con:
            rows = await con.fetch(sql, *args)
            count = await con.fetchrow(count_sql, *count_args)
    else:
        async with conf.db.id.acquire() as con:
            rows = await con.fetch(
                "SELECT * FROM users WHERE is_app = true ORDER BY {} {} NULLS LAST OFFSET $1 LIMIT $2"
                .format(*order), offset, limit)
            count = await con.fetchrow(
                "SELECT COUNT(*) FROM users WHERE is_app = true")

    apps = []
    for row in rows:
        app = fix_avatar_for_user(conf.urls.id, dict(row))
        apps.append(app)

    total_pages = (count['count'] // limit) + (0 if count['count'] %
                                               limit == 0 else 1)

    def get_qargs(page=page,
                  order_by=order_by,
                  query=search_query,
                  filter=filter_by,
                  as_list=False,
                  as_dict=False):
        qargs = {'page': page}
        if order_by:
            if order_by[0] == '+':
                order_by = order_by[1:]
            elif order_by[0] != '-':
                # toggle sort order
                print(order, order_by)
                if order[0] == order_by and order[1] == (
                        'ASC'
                        if order_by in negative_user_columns else 'DESC'):
                    order_by = '-{}'.format(order_by)
            qargs['order_by'] = order_by
        if query:
            qargs['query'] = query
        if filter:
            qargs['filter'] = filter
        if as_dict:
            return qargs
        if as_list:
            return qargs.items()
        return urlencode(qargs)

    return html(await env.get_template("apps.html").render_async(
        apps=apps,
        current_user=current_user,
        environment=conf.name,
        page="apps",
        total=count['count'],
        total_pages=total_pages,
        current_page=page,
        get_qargs=get_qargs))
Ejemplo n.º 27
0
    def test_parse_decimal(self):

        self.assertEqual(parse_int(Decimal("12345.6787")), 12345)