Exemplo n.º 1
0
    def render_GET(self, request):
        """ Get request /decode_tx/ that returns the tx decoded, if success

            Expects 'hex_tx' as GET parameter

            :rtype: string (json)
        """
        request.setHeader(b'content-type', b'application/json; charset=utf-8')
        set_cors(request, 'GET')

        parsed = parse_get_arguments(request.args, ARGS)
        if not parsed['success']:
            return get_missing_params_msg(parsed['missing'])

        try:
            tx_bytes = bytes.fromhex(parsed['args']['hex_tx'])
            tx = tx_or_block_from_bytes(tx_bytes)
            tx.storage = self.manager.tx_storage
            data = get_tx_extra_data(tx)
        except ValueError:
            data = {'success': False, 'message': 'Invalid hexadecimal data'}
        except struct.error:
            data = {'success': False, 'message': 'Could not decode transaction'}

        return json.dumps(data, indent=4).encode('utf-8')
Exemplo n.º 2
0
    def render_GET(self, request):
        """ Get request to /dashboard-tx/ that return a list of blocks and tx
            We expect two GET parameters: 'block' and 'tx'

            'block': int that indicates de quantity of blocks I should return
            'tx': int that indicates de quantity of tx I should return

            :rtype: string (json)
        """
        request.setHeader(b'content-type', b'application/json; charset=utf-8')
        set_cors(request, 'GET')

        parsed = parse_get_arguments(request.args, ARGS)
        if not parsed['success']:
            return get_missing_params_msg(parsed['missing'])

        # Get quantity for each
        try:
            block_count = int(parsed['args']['block'])
        except ValueError:
            return json.dumps({
                'success':
                False,
                'message':
                'Invalid parameter, cannot convert to int: block'
            }).encode('utf-8')

        try:
            tx_count = int(parsed['args']['tx'])
        except ValueError:
            return json.dumps({
                'success':
                False,
                'message':
                'Invalid parameter, cannot convert to int: tx'
            }).encode('utf-8')

        # Restrict counts
        block_count = min(block_count, settings.MAX_DASHBOARD_COUNT)
        tx_count = min(tx_count, settings.MAX_DASHBOARD_COUNT)

        transactions, _ = self.manager.tx_storage.get_newest_txs(
            count=tx_count)
        serialized_tx = [tx.to_json_extended() for tx in transactions]

        blocks, _ = self.manager.tx_storage.get_newest_blocks(
            count=block_count)
        serialized_blocks = [block.to_json_extended() for block in blocks]

        data = {
            'success': True,
            'transactions': serialized_tx,
            'blocks': serialized_blocks,
        }

        return json.dumps(data, indent=4).encode('utf-8')
Exemplo n.º 3
0
    def render_GET(self, request):
        """ Get request to /tips-histogram/ that return the number of tips between two timestamp
            We expect two GET parameters: 'begin' and 'end'

            'begin': int that indicates the beginning of the interval
            'end': int that indicates the end of the interval

            :rtype: string (json)
        """
        request.setHeader(b'content-type', b'application/json; charset=utf-8')
        set_cors(request, 'GET')

        parsed = parse_get_arguments(request.args, ARGS)
        if not parsed['success']:
            return json.dumps({
                'success':
                False,
                'message':
                'Missing parameter: {}'.format(parsed['missing'])
            }).encode('utf-8')

        args = parsed['args']

        # Get quantity for each
        try:
            begin = int(args['begin'])
        except ValueError:
            return json.dumps({
                'success':
                False,
                'message':
                'Invalid parameter, cannot convert to int: begin'
            }).encode('utf-8')

        try:
            end = int(args['end'])
        except ValueError:
            return json.dumps({
                'success':
                False,
                'message':
                'Invalid parameter, cannot convert to int: end'
            }).encode('utf-8')

        v = []
        for timestamp in range(begin, end + 1):
            tx_tips = self.manager.tx_storage.get_tx_tips(timestamp)
            v.append((timestamp, len(tx_tips)))

        return json.dumps({'success': True, 'tips': v}).encode('utf-8')
Exemplo n.º 4
0
    def render_GET(self, request: 'Request') -> bytes:
        """ Get request /block_at_height/ that returns a block at height in parameter

            'height': int, the height of block to get

            :rtype: string (json)
        """
        assert self.manager.tx_storage.indexes is not None

        request.setHeader(b'content-type', b'application/json; charset=utf-8')
        set_cors(request, 'GET')

        # Height parameter is required
        parsed = parse_get_arguments(request.args, ['height'])
        if not parsed['success']:
            return get_missing_params_msg(parsed['missing'])

        args = parsed['args']

        # Height parameter must be an integer
        try:
            height = int(args['height'])
        except ValueError:
            return json.dumps({
                'success':
                False,
                'message':
                'Invalid \'height\' parameter, expected an integer'
            }).encode('utf-8')

        # Get hash of the block with the height
        block_hash = self.manager.tx_storage.indexes.height.get(height)

        # If there is no block in the index with this height, block_hash will be None
        if block_hash is None:
            return json.dumps({
                'success':
                False,
                'message':
                'No block with height {}.'.format(height)
            }).encode('utf-8')

        block = self.manager.tx_storage.get_transaction(block_hash)

        data = {'success': True, 'block': block.to_json_extended()}
        return json.dumps(data, indent=4).encode('utf-8')
Exemplo n.º 5
0
    def render_GET(self, request: Request) -> bytes:
        """ GET request for /push_tx/
            Expects 'hex_tx' as args parameter that is the hex representation of the whole tx

            :rtype: string (json)

            This resource will be deprecated soon
        """
        request.setHeader(b'content-type', b'application/json; charset=utf-8')
        set_cors(request, 'GET')
        parsed = parse_get_arguments(request.args, ARGS)
        if not parsed['success']:
            data = {
                'success': False,
                'message': 'Missing hexadecimal data',
                'can_force': False
            }
            return json_dumpb(data)

        data = parsed['args']
        data['force'] = b'force' in request.args and request.args[b'force'][
            0].decode('utf-8') == 'true'

        return self.handle_push_tx(data)
Exemplo n.º 6
0
    def get_list_tx(self, request):
        """ Get parameter from request.args and return list of blocks/txs

            'type': 'block' or 'tx', to indicate if we should return a list of blocks or tx
            'count': int, to indicate the quantity of elements we should return
            'hash': string, the hash reference we are in the pagination
            'timestamp': int, the timestamp reference we are in the pagination
            'page': 'previous' or 'next', to indicate if the user wants after or before the hash reference
        """
        parsed = parse_get_arguments(request.args, GET_LIST_ARGS)
        if not parsed['success']:
            return get_missing_params_msg(parsed['missing'])

        args = parsed['args']
        error = None

        try:
            count = min(int(args['count']), settings.MAX_TX_COUNT)
        except ValueError:
            error = {'success': False, 'message': 'Invalid \'count\' parameter, expected an integer'}

        type_tx = args['type']
        if type_tx != 'tx' and type_tx != 'block':
            error = {'success': False, 'message': 'Invalid \'type\' parameter, expected \'block\' or \'tx\''}

        if error:
            return json.dumps(error).encode('utf-8')

        ref_hash = None
        page = ''
        if b'hash' in request.args:
            ref_hash = request.args[b'hash'][0].decode('utf-8')

            parsed = parse_get_arguments(request.args, ['timestamp', 'page'])
            if not parsed['success']:
                return get_missing_params_msg(parsed['missing'])

            try:
                ref_timestamp = int(parsed['args']['timestamp'])
            except ValueError:
                return json.dumps({
                    'success': False,
                    'message': 'Invalid \'timestamp\' parameter, expected an integer'
                }).encode('utf-8')

            page = parsed['args']['page']
            if page != 'previous' and page != 'next':
                return json.dumps({
                    'success': False,
                    'message': 'Invalid \'page\' parameter, expected \'previous\' or \'next\''
                }).encode('utf-8')

            if type_tx == 'block':
                if page == 'previous':
                    elements, has_more = self.manager.tx_storage.get_newer_blocks_after(
                        ref_timestamp, bytes.fromhex(ref_hash), count)
                else:
                    elements, has_more = self.manager.tx_storage.get_older_blocks_after(
                        ref_timestamp, bytes.fromhex(ref_hash), count)

            else:
                if page == 'previous':
                    elements, has_more = self.manager.tx_storage.get_newer_txs_after(
                        ref_timestamp, bytes.fromhex(ref_hash), count)
                else:
                    elements, has_more = self.manager.tx_storage.get_older_txs_after(
                        ref_timestamp, bytes.fromhex(ref_hash), count)
        else:
            if type_tx == 'block':
                elements, has_more = self.manager.tx_storage.get_newest_blocks(count=count)
            else:
                elements, has_more = self.manager.tx_storage.get_newest_txs(count=count)

        serialized = [element.to_json_extended() for element in elements]

        data = {'transactions': serialized, 'has_more': has_more}
        return json.dumps(data, indent=4).encode('utf-8')
Exemplo n.º 7
0
    def render_GET(self, request: Request) -> bytes:
        """ GET request for /thin_wallet/token_history/

            Expects as GET parameter of the queried token:
                - 'id': uid of token whose history is being requested
                - 'count': int, to indicate the quantity of elements we should return
                - 'hash': string, the hash reference we are in the pagination
                - 'timestamp': int, the timestamp reference we are in the pagination
                - 'page': 'previous' or 'next', to indicate if the user wants after or before the hash reference

            :rtype: string (json)
        """
        request.setHeader(b'content-type', b'application/json; charset=utf-8')
        set_cors(request, 'GET')

        if not self.manager.tx_storage.tokens_index:
            request.setResponseCode(503)
            return json.dumps({'success': False}).encode('utf-8')

        parsed = parse_get_arguments(request.args, ARGS)
        if not parsed['success']:
            return get_missing_params_msg(parsed['missing'])

        if b'id' not in request.args:
            return get_missing_params_msg('id')

        try:
            token_uid = bytes.fromhex(parsed['args']['id'])
        except (ValueError, AttributeError):
            return json.dumps({'success': False, 'message': 'Invalid token id'}).encode('utf-8')

        try:
            count = min(int(parsed['args']['count']), settings.MAX_TX_COUNT)
        except ValueError:
            return json.dumps({
                'success': False,
                'message': 'Invalid \'count\' parameter, expected an int'
            }).encode('utf-8')

        if b'hash' in request.args:
            parsed = parse_get_arguments(request.args, ['timestamp', 'page', 'hash'])
            if not parsed['success']:
                return get_missing_params_msg(parsed['missing'])

            try:
                hash_bytes = bytes.fromhex(parsed['args']['hash'])
            except ValueError:
                return json.dumps({
                    'success': False,
                    'message': 'Invalid \'hash\' parameter, could not decode hexadecimal'
                }).encode('utf-8')

            page = parsed['args']['page']
            if page != 'previous' and page != 'next':
                return json.dumps({
                    'success': False,
                    'message': 'Invalid \'page\' parameter, expected \'previous\' or \'next\''
                }).encode('utf-8')

            try:
                ref_timestamp = int(parsed['args']['timestamp'])
            except ValueError:
                return json.dumps({
                    'success': False,
                    'message': 'Invalid \'timestamp\' parameter, expected an int'
                }).encode('utf-8')

            if page == 'previous':
                elements, has_more = self.manager.tx_storage.tokens_index.get_newer_transactions(
                        token_uid, ref_timestamp, hash_bytes, count)
            else:
                elements, has_more = self.manager.tx_storage.tokens_index.get_older_transactions(
                        token_uid, ref_timestamp, hash_bytes, count)
        else:
            elements, has_more = self.manager.tx_storage.tokens_index.get_newest_transactions(token_uid, count)

        transactions = [self.manager.tx_storage.get_transaction(element) for element in elements]
        serialized = [tx.to_json_extended() for tx in transactions]

        data = {
            'success': True,
            'transactions': serialized,
            'has_more': has_more,
        }
        return json.dumps(data).encode('utf-8')