mirror of
https://github.com/bigchaindb/js-bigchaindb-driver.git
synced 2024-11-22 17:50:09 +01:00
Merge pull request #39 from bigchaindb/http-api-1.0-rc-changes
Http api 1.0 rc changes
This commit is contained in:
commit
b8d73b23e7
@ -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 = {}) {
|
||||
@ -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
|
||||
}
|
||||
@ -41,37 +40,37 @@ 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
|
||||
}
|
||||
})
|
||||
@ -79,28 +78,33 @@ export default class Connection {
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
})
|
||||
@ -108,12 +112,12 @@ export default class Connection {
|
||||
|
||||
/**
|
||||
* @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
|
||||
}
|
||||
})
|
||||
}
|
||||
@ -128,12 +132,10 @@ export default class Connection {
|
||||
const timer = setInterval(() => {
|
||||
this.getStatus(txId)
|
||||
.then((res) => {
|
||||
console.log('Fetched transaction status:', res) // eslint-disable-line no-console
|
||||
if (res.status === 'valid') {
|
||||
clearInterval(timer)
|
||||
this.getTransaction(txId)
|
||||
.then((res_) => {
|
||||
console.log('Fetched transaction:', res_) // eslint-disable-line no-console
|
||||
resolve(res_)
|
||||
})
|
||||
}
|
||||
@ -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
|
||||
}
|
||||
})
|
||||
}
|
||||
|
@ -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
|
||||
|
208
test/connection/test_connection.js
Normal file
208
test/connection/test_connection.js
Normal file
@ -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 } }
|
||||
))
|
||||
})
|
32
test/constants.js
Normal file
32
test/constants.js
Normal file
@ -0,0 +1,32 @@
|
||||
import test from 'ava'
|
||||
import { Transaction, Ed25519Keypair } from '../src'
|
||||
// TODO: Find out if ava has something like conftest, if so put this there.
|
||||
|
||||
// NOTE: It's safer to cast `Math.random()` to a string, to avoid differences
|
||||
// in "float interpretation" between languages (e.g. JavaScript and Python)
|
||||
export function asset() { return { message: `${Math.random()}` } }
|
||||
export const metaData = { message: 'metaDataMessage' }
|
||||
|
||||
export const alice = new Ed25519Keypair()
|
||||
export const aliceCondition = Transaction.makeEd25519Condition(alice.publicKey)
|
||||
export const aliceOutput = Transaction.makeOutput(aliceCondition)
|
||||
export const createTx = Transaction.makeCreateTransaction(
|
||||
asset,
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
export const transferTx = Transaction.makeTransferTransaction(
|
||||
createTx,
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
0
|
||||
)
|
||||
|
||||
export const bob = new Ed25519Keypair()
|
||||
export const bobCondition = Transaction.makeEd25519Condition(bob.publicKey)
|
||||
export const bobOutput = Transaction.makeOutput(bobCondition)
|
||||
|
||||
|
||||
// TODO: https://github.com/avajs/ava/issues/1190
|
||||
test('', () => 'dirty hack. TODO: Exclude this file from being run by ava')
|
310
test/integration/test_integration.js
Normal file
310
test/integration/test_integration.js
Normal file
@ -0,0 +1,310 @@
|
||||
import test from 'ava'
|
||||
import { Ed25519Keypair, Transaction, Connection } from '../../src'
|
||||
|
||||
import {
|
||||
alice,
|
||||
aliceCondition,
|
||||
aliceOutput,
|
||||
bob,
|
||||
bobOutput,
|
||||
asset,
|
||||
metaData
|
||||
} from '../constants'
|
||||
|
||||
const API_PATH = 'http://localhost:9984/api/v1/'
|
||||
|
||||
|
||||
test('Keypair is created', t => {
|
||||
const keyPair = new Ed25519Keypair()
|
||||
|
||||
t.truthy(keyPair.publicKey)
|
||||
t.truthy(keyPair.privateKey)
|
||||
})
|
||||
|
||||
|
||||
// TODO: The following tests are a bit messy currently, please do:
|
||||
//
|
||||
// - tidy up dependency on `pollStatusAndFetchTransaction`
|
||||
test('Valid CREATE transaction', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
|
||||
const tx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
const txSigned = Transaction.signTransaction(tx, alice.privateKey)
|
||||
|
||||
return conn.postTransaction(txSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(resTx => t.truthy(resTx))
|
||||
})
|
||||
|
||||
|
||||
test('Valid TRANSFER transaction with single Ed25519 input', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
alice.privateKey
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(() => {
|
||||
const transferTx = Transaction.makeTransferTransaction(
|
||||
createTxSigned,
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
0
|
||||
)
|
||||
const transferTxSigned = Transaction.signTransaction(
|
||||
transferTx,
|
||||
alice.privateKey
|
||||
)
|
||||
return conn.postTransaction(transferTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(resTx => t.truthy(resTx))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
test('Valid TRANSFER transaction with multiple Ed25519 inputs', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[aliceOutput, bobOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
alice.privateKey
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ 'id': txId }) => conn.pollStatusAndFetchTransaction(txId))
|
||||
.then(() => {
|
||||
const transferTx = Transaction.makeTransferTransaction(
|
||||
createTxSigned,
|
||||
metaData,
|
||||
[Transaction.makeOutput(aliceCondition, '2')],
|
||||
0,
|
||||
1
|
||||
)
|
||||
const transferTxSigned = Transaction.signTransaction(
|
||||
transferTx,
|
||||
alice.privateKey,
|
||||
bob.privateKey
|
||||
)
|
||||
return conn.postTransaction(transferTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(resTx => t.truthy(resTx))
|
||||
})
|
||||
})
|
||||
|
||||
|
||||
test('Search for spent and unspent outputs of a given public key', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
const carol = new Ed25519Keypair()
|
||||
const carolCondition = Transaction.makeEd25519Condition(carol.publicKey)
|
||||
const carolOutput = Transaction.makeOutput(carolCondition)
|
||||
const trent = new Ed25519Keypair()
|
||||
const trentCondition = Transaction.makeEd25519Condition(trent.publicKey)
|
||||
const trentOutput = Transaction.makeOutput(trentCondition)
|
||||
|
||||
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[carolOutput, carolOutput],
|
||||
carol.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
carol.privateKey,
|
||||
carol.privateKey
|
||||
)
|
||||
|
||||
// We spent output 1 (of 0, 1)
|
||||
const transferTx = Transaction.makeTransferTransaction(
|
||||
createTxSigned,
|
||||
metaData,
|
||||
[trentOutput],
|
||||
1
|
||||
)
|
||||
const transferTxSigned = Transaction.signTransaction(
|
||||
transferTx,
|
||||
carol.privateKey,
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(() => conn.postTransaction(transferTxSigned))
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(() => conn.listOutputs(carol.publicKey))
|
||||
// now listOutputs should return us outputs 0 and 1 (unfiltered)
|
||||
.then(outputs => t.truthy(outputs.length === 2))
|
||||
})
|
||||
|
||||
|
||||
test('Search for unspent outputs for a given public key', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
const carol = new Ed25519Keypair()
|
||||
const carolCondition = Transaction.makeEd25519Condition(carol.publicKey)
|
||||
const carolOutput = Transaction.makeOutput(carolCondition)
|
||||
const trent = new Ed25519Keypair()
|
||||
const trentCondition = Transaction.makeEd25519Condition(trent.publicKey)
|
||||
const trentOutput = Transaction.makeOutput(trentCondition)
|
||||
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[carolOutput, carolOutput, carolOutput],
|
||||
carol.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
carol.privateKey,
|
||||
carol.privateKey
|
||||
)
|
||||
|
||||
// We spent output 1 (of 0, 1, 2)
|
||||
const transferTx = Transaction.makeTransferTransaction(
|
||||
createTxSigned,
|
||||
metaData,
|
||||
[trentOutput],
|
||||
1
|
||||
)
|
||||
const transferTxSigned = Transaction.signTransaction(
|
||||
transferTx,
|
||||
carol.privateKey,
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(() => conn.postTransaction(transferTxSigned))
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
// now listOutputs should return us outputs 0 and 2 (1 is spent)
|
||||
.then(() => conn.listOutputs(carol.publicKey, 'false'))
|
||||
.then(outputs => t.truthy(outputs.length === 2))
|
||||
})
|
||||
|
||||
|
||||
test('Search for spent outputs for a given public key', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
const carol = new Ed25519Keypair()
|
||||
const carolCondition = Transaction.makeEd25519Condition(carol.publicKey)
|
||||
const carolOutput = Transaction.makeOutput(carolCondition)
|
||||
const trent = new Ed25519Keypair()
|
||||
const trentCondition = Transaction.makeEd25519Condition(trent.publicKey)
|
||||
const trentOutput = Transaction.makeOutput(trentCondition)
|
||||
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[carolOutput, carolOutput, carolOutput],
|
||||
carol.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
carol.privateKey,
|
||||
carol.privateKey
|
||||
)
|
||||
|
||||
// We spent output 1 (of 0, 1, 2)
|
||||
const transferTx = Transaction.makeTransferTransaction(
|
||||
createTxSigned,
|
||||
metaData,
|
||||
[trentOutput],
|
||||
1
|
||||
)
|
||||
const transferTxSigned = Transaction.signTransaction(
|
||||
transferTx,
|
||||
carol.privateKey,
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(() => conn.postTransaction(transferTxSigned))
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
// now listOutputs should only return us output 1 (0 and 2 are unspent)
|
||||
.then(() => conn.listOutputs(carol.publicKey, true))
|
||||
.then(outputs => t.truthy(outputs.length === 1))
|
||||
})
|
||||
|
||||
|
||||
test('Search for an asset', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
alice.privateKey
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(() => conn.searchAssets(createTxSigned.asset.data.message))
|
||||
.then(assets => t.truthy(
|
||||
assets.pop(),
|
||||
createTxSigned.asset.data.message
|
||||
))
|
||||
})
|
||||
|
||||
|
||||
test('Search blocks containing a transaction', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
alice.privateKey
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
|
||||
.then(({ id }) => conn.listBlocks(id, 'VALID'))
|
||||
.then(blocks => conn.getBlock(blocks.pop()))
|
||||
.then(({ block: { transactions } }) => transactions.filter(
|
||||
({ id }) => id === createTxSigned.id
|
||||
))
|
||||
.then(transactions => t.truthy(transactions.length === 1))
|
||||
})
|
||||
|
||||
|
||||
test('Search transaction containing an asset', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
asset(),
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
const createTxSigned = Transaction.signTransaction(
|
||||
createTx,
|
||||
alice.privateKey
|
||||
)
|
||||
|
||||
return conn.postTransaction(createTxSigned)
|
||||
.then(({ id }) => conn.pollStatusAndFetchTransaction(id, 'CREATE'))
|
||||
.then(({ id }) => conn.listTransactions(id))
|
||||
.then(transactions => t.truthy(transactions.length === 1))
|
||||
})
|
30
test/test.js
30
test/test.js
@ -1,30 +0,0 @@
|
||||
import test from 'ava'
|
||||
import { Ed25519Keypair, Transaction, Connection } from '../src'
|
||||
|
||||
const API_PATH = 'http://localhost:9984/api/v1/'
|
||||
|
||||
test('Keypair is created', t => {
|
||||
const keyPair = new Ed25519Keypair()
|
||||
|
||||
t.truthy(keyPair.publicKey)
|
||||
t.truthy(keyPair.privateKey)
|
||||
})
|
||||
|
||||
test('Valid CREATE transaction is evaluated by BigchainDB', t => {
|
||||
const alice = new Ed25519Keypair()
|
||||
const asset = { name: 'Shmui', type: 'cat' }
|
||||
const metadata = { dayOfTheWeek: 'Caturday' }
|
||||
|
||||
const tx = Transaction.makeCreateTransaction(
|
||||
asset,
|
||||
metadata,
|
||||
[Transaction.makeOutput(Transaction.makeEd25519Condition(alice.publicKey))],
|
||||
alice.publicKey
|
||||
)
|
||||
|
||||
const txSigned = Transaction.signTransaction(tx, alice.privateKey)
|
||||
const conn = new Connection(API_PATH)
|
||||
return conn.postTransaction(txSigned)
|
||||
.then(resTx => t.truthy(resTx))
|
||||
})
|
||||
|
@ -1,29 +1,17 @@
|
||||
import test from 'ava'
|
||||
import sinon from 'sinon'
|
||||
|
||||
import { Transaction, Ed25519Keypair } from '../../src'
|
||||
import { Transaction } from '../../src'
|
||||
import * as makeTransaction from '../../src/transaction/makeTransaction' // eslint-disable-line
|
||||
import makeInputTemplate from '../../src/transaction/makeInputTemplate'
|
||||
|
||||
|
||||
// TODO: Find out if ava has something like conftest, if so put this there.
|
||||
const alice = new Ed25519Keypair()
|
||||
const aliceCondition = Transaction.makeEd25519Condition(alice.publicKey)
|
||||
const aliceOutput = Transaction.makeOutput(aliceCondition)
|
||||
const assetMessage = { assetMessage: 'assetMessage' }
|
||||
const metaDataMessage = { metaDataMessage: 'metaDataMessage' }
|
||||
const createTx = Transaction.makeCreateTransaction(
|
||||
assetMessage,
|
||||
metaDataMessage,
|
||||
[aliceOutput],
|
||||
alice.publicKey
|
||||
)
|
||||
const transferTx = Transaction.makeTransferTransaction(
|
||||
import {
|
||||
alice,
|
||||
aliceOutput,
|
||||
metaData,
|
||||
createTx,
|
||||
metaDataMessage,
|
||||
[aliceOutput],
|
||||
0
|
||||
)
|
||||
transferTx
|
||||
} from '../constants'
|
||||
|
||||
|
||||
test('Create valid output with default amount', t => {
|
||||
@ -84,14 +72,14 @@ test('Create TRANSFER transaction based on CREATE transaction', t => {
|
||||
|
||||
Transaction.makeTransferTransaction(
|
||||
createTx,
|
||||
metaDataMessage,
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
0
|
||||
)
|
||||
const expected = [
|
||||
'TRANSFER',
|
||||
{ id: createTx.id },
|
||||
metaDataMessage,
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
[makeInputTemplate(
|
||||
[alice.publicKey],
|
||||
@ -112,14 +100,14 @@ test('Create TRANSFER transaction based on TRANSFER transaction', t => {
|
||||
|
||||
Transaction.makeTransferTransaction(
|
||||
transferTx,
|
||||
metaDataMessage,
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
0
|
||||
)
|
||||
const expected = [
|
||||
'TRANSFER',
|
||||
{ id: transferTx.asset.id },
|
||||
metaDataMessage,
|
||||
metaData,
|
||||
[aliceOutput],
|
||||
[makeInputTemplate(
|
||||
[alice.publicKey],
|
||||
|
Loading…
Reference in New Issue
Block a user