Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Http api 1.0 rc changes #39

Merged
merged 15 commits into from
Jun 21, 2017
86 changes: 44 additions & 42 deletions src/connection/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,18 +7,17 @@ export default class Connection {
this.headers = headers
}

getApiUrls(endpoints) {
// TODO: Use camel case
return {
'blocks': `${this.path}blocks`,
'blocks_detail': `${this.path}blocks/%(blockId)s`,
'outputs': `${this.path}outputs`,
'statuses': `${this.path}statuses`,
'transactions': `${this.path}transactions`,
'transactions_detail': `${this.path}transactions/%(txId)s`,
'search_assets': `${this.path}assets`,
'votes': `${this.path}votes`
}[endpoints]
getApiUrls(endpoint) {
return this.path + {
'blocks': 'blocks',
'blocksDetail': 'blocks/%(blockId)s',
'outputs': 'outputs',
'statuses': 'statuses',
'transactions': 'transactions',
'transactionsDetail': 'transactions/%(transactionId)s',
'assets': 'assets',
'votes': 'votes'
}[endpoint]
}

_req(path, options = {}) {
Expand All @@ -32,7 +31,7 @@ export default class Connection {
* @param blockId
*/
getBlock(blockId) {
return this._req(this.getApiUrls('blocks_detail'), {
return this._req(this.getApiUrls('blocksDetail'), {
urlTemplateSpec: {
blockId
}
Expand All @@ -41,79 +40,84 @@ export default class Connection {

/**
* @public
* @param tx_id
* @param transactionId
*/
getStatus(tx_id) { // eslint-disable-line camelcase
getStatus(transactionId) {
return this._req(this.getApiUrls('statuses'), {
query: {
tx_id
transaction_id: transactionId
}
})
}

/**
* @public
* @param txId
* @param transactionId
*/
getTransaction(txId) {
return this._req(this.getApiUrls('transactions_detail'), {
getTransaction(transactionId) {
return this._req(this.getApiUrls('transactionsDetail'), {
urlTemplateSpec: {
txId
transactionId
}
})
}

/**
* @public
* @param tx_id
* @param transactionId
* @param status
*/
listBlocks({ tx_id, status }) {
listBlocks(transactionId, status) {
return this._req(this.getApiUrls('blocks'), {
query: {
tx_id,
transaction_id: transactionId,
status
}
})
}

/**
* @public
* @param public_key
* @param unspent
* @param publicKey
* @param spent
* @param onlyJsonResponse
*/
listOutputs({ public_key, unspent }, onlyJsonResponse = true) {
listOutputs(publicKey, spent, onlyJsonResponse = true) {
const query = {
public_key: publicKey
}
// NOTE: If `spent` is not defined, it must not be included in the
// query parameters.
if (spent !== undefined) {
query.spent = spent.toString()
}
return this._req(this.getApiUrls('outputs'), {
query: {
public_key,
unspent
}
query
}, onlyJsonResponse)
}

/**
* @public
* @param asset_id
* @param assetId
* @param operation
*/
listTransactions({ asset_id, operation }) {
listTransactions(assetId, operation) {
return this._req(this.getApiUrls('transactions'), {
query: {
asset_id,
asset_id: assetId,
operation
}
})
}

/**
* @public
* @param block_id
* @param blockId
*/
listVotes(block_id) { // eslint-disable-line camelcase
listVotes(blockId) {
return this._req(this.getApiUrls('votes'), {
query: {
block_id
block_id: blockId
}
})
}
Expand All @@ -128,12 +132,10 @@ export default class Connection {
const timer = setInterval(() => {
this.getStatus(txId)
.then((res) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove extra parenthesis 💅

console.log('Fetched transaction status:', res) // eslint-disable-line no-console
if (res.status === 'valid') {
clearInterval(timer)
this.getTransaction(txId)
.then((res_) => {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove extra parenthesis 💅

console.log('Fetched transaction:', res_) // eslint-disable-line no-console
resolve(res_)
})
}
Expand Down Expand Up @@ -162,12 +164,12 @@ export default class Connection {
/**
* @public
*
* @param transaction
* @param search
*/
searchAssets(query) {
return this.req(this.getApiUrls('search_assets'), {
searchAssets(search) {
return this._req(this.getApiUrls('assets'), {
query: {
text_search: query
search
}
})
}
Expand Down
3 changes: 2 additions & 1 deletion src/transaction/serializeTransactionIntoCanonicalString.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ import clone from 'clone'
* @return {string} a canonically serialized Transaction
*/
export default function serializeTransactionIntoCanonicalString(transaction) {
// BigchainDB signs fulfillments by serializing transactions into a "canonical" format where
// BigchainDB signs fulfillments by serializing transactions into a
// "canonical" format where
const tx = clone(transaction)
// TODO: set fulfillments to null
// Sort the keys
Expand Down
208 changes: 208 additions & 0 deletions test/connection/test_connection.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,208 @@
import test from 'ava'
import sinon from 'sinon'

import * as request from '../../src/request' // eslint-disable-line
import { Connection } from '../../src'

const API_PATH = 'http://localhost:9984/api/v1/'
const conn = new Connection(API_PATH)


test('generate API URLS', t => {
const endpoints = {
'blocks': 'blocks',
'blocksDetail': 'blocks/%(blockId)s',
'outputs': 'outputs',
'statuses': 'statuses',
'transactions': 'transactions',
'transactionsDetail': 'transactions/%(transactionId)s',
'assets': 'assets',
}
Object.keys(endpoints).forEach(endpointName => {
const url = conn.getApiUrls(endpointName)
const expected = API_PATH + endpoints[endpointName]
t.is(url, expected)
})
})


test('Request with custom headers', t => {
const testConn = new Connection(API_PATH, { hello: 'world' })
const expectedOptions = {
headers: {
hello: 'world',
custom: 'headers'
}
}

// request is read only, cannot be mocked?
sinon.spy(request, 'default')
testConn._req(API_PATH, { headers: { custom: 'headers' } })

t.truthy(request.default.calledWith(API_PATH, expectedOptions))
request.default.restore()
})


test('Get block for a block id', t => {
const expectedPath = 'path'
const blockId = 'abc'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.getBlock(blockId)
t.truthy(conn._req.calledWith(
expectedPath,
{ urlTemplateSpec: { blockId } }
))
})


test('Get status for a transaction id', t => {
const expectedPath = 'path'
const transactionId = 'abc'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.getStatus(transactionId)
t.truthy(conn._req.calledWith(
expectedPath,
{ query: { transaction_id: transactionId } }
))
})


test('Get transaction for a transaction id', t => {
const expectedPath = 'path'
const transactionId = 'abc'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.getTransaction(transactionId)
t.truthy(conn._req.calledWith(
expectedPath,
{ urlTemplateSpec: { transactionId } }
))
})


test('Get list of blocks for a transaction id', t => {
const expectedPath = 'path'
const transactionId = 'abc'
const status = 'status'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.listBlocks(transactionId, status)
t.truthy(conn._req.calledWith(
expectedPath,
{
query: {
transaction_id: transactionId,
status
}
}
))
})


test('Get list of transactions for an asset id', t => {
const expectedPath = 'path'
const assetId = 'abc'
const operation = 'operation'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.listTransactions(assetId, operation)
t.truthy(conn._req.calledWith(
expectedPath,
{
query: {
asset_id: assetId,
operation
}
}
))
})


test('Get outputs for a public key and no spent flag', t => {
const expectedPath = 'path'
const publicKey = 'publicKey'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.listOutputs(publicKey)
t.truthy(conn._req.calledWith(
expectedPath,
{ query: { public_key: publicKey } }
))
})


test('Get outputs for a public key and spent=false', t => {
const expectedPath = 'path'
const publicKey = 'publicKey'
const spent = false

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.listOutputs(publicKey, spent)
t.truthy(conn._req.calledWith(
expectedPath,
{ query: { public_key: publicKey, spent: 'false' } }
))
})


test('Get outputs for a public key and spent=true', t => {
const expectedPath = 'path'
const publicKey = 'publicKey'
const spent = true

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.listOutputs(publicKey, spent)
t.truthy(conn._req.calledWith(
expectedPath,
{ query: { public_key: publicKey, spent: 'true' } }
))
})


test('Get votes for a block id', t => {
const expectedPath = 'path'
const blockId = 'abc'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.listVotes(blockId)
t.truthy(conn._req.calledWith(
expectedPath,
{ query: { block_id: blockId } }
))
})


test('Get asset for text', t => {
const expectedPath = 'path'
const search = 'abc'

conn._req = sinon.spy()
conn.getApiUrls = sinon.stub().returns(expectedPath)

conn.searchAssets(search)
t.truthy(conn._req.calledWith(
expectedPath,
{ query: { search } }
))
})
Loading