implement statuses endpoint

This commit is contained in:
diminator 2017-01-06 15:55:07 +01:00
parent f9ed5690a7
commit 7124adcd34
No known key found for this signature in database
GPG Key ID: C3D8590E6D0D439A
5 changed files with 145 additions and 48 deletions

View File

@ -1,6 +1,10 @@
""" API routes definition """
from flask_restful import Api
from bigchaindb.web.views import info, transactions as tx, unspents
from bigchaindb.web.views import (
info,
statuses,
transactions as tx, unspents,
)
def add_routes(app):
@ -17,8 +21,8 @@ def r(*args, **kwargs):
ROUTES_API_V1 = [
r('statuses/', statuses.StatusApi),
r('transactions/<string:tx_id>', tx.TransactionApi),
r('transactions/<string:tx_id>/status', tx.TransactionStatusApi),
r('transactions', tx.TransactionListApi),
r('unspents/', unspents.UnspentListApi),
]

View File

@ -0,0 +1,45 @@
"""This module provides the blueprint for some basic API endpoints.
For more information please refer to the documentation on ReadTheDocs:
- https://docs.bigchaindb.com/projects/server/en/latest/drivers-clients/
http-client-server-api.html
"""
from flask import current_app
from flask_restful import Resource, reqparse
from bigchaindb.web.views.base import make_error
class StatusApi(Resource):
def get(self):
"""API endpoint to get details about the status of a transaction or a block.
Return:
A ``dict`` in the format ``{'status': <status>}``, where
``<status>`` is one of "valid", "invalid", "undecided", "backlog".
"""
parser = reqparse.RequestParser()
parser.add_argument('tx_id', type=str)
parser.add_argument('block_id', type=str)
args = parser.parse_args(strict=True)
if sum(arg is not None for arg in args.values()) != 1:
return make_error(400, "Provide exactly one query parameter. Choices are: block_id, tx_id")
pool = current_app.config['bigchain_pool']
status = None
with pool() as bigchain:
if args['tx_id']:
status = bigchain.get_status(args['tx_id'])
elif args['block_id']:
block = bigchain.get_block(block_id=args['block_id'])
if not block:
return make_error(404)
status = bigchain.block_election_status(block['id'], block['block']['voters'])
if not status:
return make_error(404)
return {'status': status}

View File

@ -46,29 +46,6 @@ class TransactionApi(Resource):
return tx.to_dict()
class TransactionStatusApi(Resource):
def get(self, tx_id):
"""API endpoint to get details about the status of a transaction.
Args:
tx_id (str): the id of the transaction.
Return:
A ``dict`` in the format ``{'status': <status>}``, where
``<status>`` is one of "valid", "invalid", "undecided", "backlog".
"""
pool = current_app.config['bigchain_pool']
with pool() as bigchain:
status = bigchain.get_status(tx_id)
if not status:
return make_error(404)
return {'status': status}
class TransactionListApi(Resource):
def post(self):
"""API endpoint to push transactions to the Federation.

View File

@ -0,0 +1,94 @@
import pytest
from bigchaindb.models import Transaction
STATUSES_ENDPOINT = '/api/v1/statuses'
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_transaction_status_endpoint(b, client, user_pk):
input_tx = b.get_owned_ids(user_pk).pop()
tx, status = b.get_transaction(input_tx.txid, include_status=True)
res = client.get(STATUSES_ENDPOINT + "?tx_id=" + input_tx.txid)
assert status == res.json['status']
assert res.status_code == 200
@pytest.mark.bdb
def test_get_transaction_status_endpoint_returns_404_if_not_found(client):
res = client.get(STATUSES_ENDPOINT + "?tx_id=123")
assert res.status_code == 404
@pytest.mark.bdb
def test_get_block_status_endpoint_undecided(b, client):
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
block = b.create_block([tx])
b.write_block(block)
status = b.block_election_status(block.id, block.voters)
res = client.get(STATUSES_ENDPOINT + "?block_id=" + block.id)
assert status == res.json['status']
assert res.status_code == 200
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_block_status_endpoint_valid(b, client):
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
block = b.create_block([tx])
b.write_block(block)
# vote the block valid
vote = b.vote(block.id, b.get_last_voted_block().id, True)
b.write_vote(vote)
status = b.block_election_status(block.id, block.voters)
res = client.get(STATUSES_ENDPOINT + "?block_id=" + block.id)
assert status == res.json['status']
assert res.status_code == 200
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_block_status_endpoint_invalid(b, client):
tx = Transaction.create([b.me], [([b.me], 1)])
tx = tx.sign([b.me_private])
block = b.create_block([tx])
b.write_block(block)
# vote the block valid
vote = b.vote(block.id, b.get_last_voted_block().id, False)
b.write_vote(vote)
status = b.block_election_status(block.id, block.voters)
res = client.get(STATUSES_ENDPOINT + "?block_id=" + block.id)
assert status == res.json['status']
assert res.status_code == 200
@pytest.mark.bdb
def test_get_block_status_endpoint_returns_404_if_not_found(client):
res = client.get(STATUSES_ENDPOINT + "?block_id=123")
assert res.status_code == 404
@pytest.mark.bdb
def test_get_status_endpoint_returns_400_bad_query_params(client):
res = client.get(STATUSES_ENDPOINT)
assert res.status_code == 400
res = client.get(STATUSES_ENDPOINT + "?ts_id=123")
assert res.status_code == 400
res = client.get(STATUSES_ENDPOINT + "?tx_id=123&block_id=123")
assert res.status_code == 400

View File

@ -159,26 +159,3 @@ def test_post_invalid_transfer_transaction_returns_400(b, client, user_pk, user_
res = client.post(TX_ENDPOINT, data=json.dumps(transfer_tx.to_dict()))
assert res.status_code == 400
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_transaction_status_endpoint(b, client, user_pk):
input_tx = b.get_owned_ids(user_pk).pop()
tx, status = b.get_transaction(input_tx.txid, include_status=True)
res = client.get(TX_ENDPOINT + input_tx.txid + "/status")
assert status == res.json['status']
assert res.status_code == 200
res = client.get(TX_ENDPOINT + input_tx.txid + "/status/")
assert status == res.json['status']
assert res.status_code == 200
@pytest.mark.bdb
@pytest.mark.usefixtures('inputs')
def test_get_transaction_status_returns_404_if_not_found(client):
res = client.get(TX_ENDPOINT + '123' + "/status")
assert res.status_code == 404
res = client.get(TX_ENDPOINT + '123' + "/status/")
assert res.status_code == 404