Merge branch 'master' into websocket-api-doc

This commit is contained in:
Jernej Pregelj 2017-10-15 12:28:24 +02:00 committed by GitHub
commit 8804998546
4 changed files with 155 additions and 8 deletions

View File

@ -64,7 +64,7 @@ that represents a bicycle:
.. code-block:: js
assetdata = {
const assetdata = {
'bicycle': {
'serial_number': 'abcd1234',
'manufacturer': 'Bicycle Inc.',
@ -86,7 +86,7 @@ For example, the bicycle will be transferred on earth which is metadata:
.. code-block:: js
metadata = {'planet': 'earth'}
const metadata = {'planet': 'earth'}
Asset Creation
--------------
@ -288,7 +288,7 @@ Recap: Asset Creation & Transfer
// Define the asset to store, in this example
// we store a bicycle with its serial number and manufacturer
assetdata = {
const assetdata = {
'bicycle': {
'serial_number': 'cde',
'manufacturer': 'Bicycle Inc.',
@ -298,7 +298,7 @@ Recap: Asset Creation & Transfer
// Metadata contains information about the transaction itself
// (can be `null` if not needed)
// E.g. the bicycle is fabricated on earth
metadata = {'planet': 'earth'}
const metadata = {'planet': 'earth'}
// Construct a transaction payload
const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
@ -485,6 +485,135 @@ All transactions are printed to the console. To use this piece of code, you will
});
Difference unspent and spent output
-----------------------------------
An unspent output is simply an output of a transaction which isn't yet an input of another transaction.
So, if we transfer an asset, the output becomes spent, because it becomes the input of the transfer transaction.
The transfer transactions its output becomes unspent now until he transfers the asset again to somebody else.
We will demonstrate this with a piece of code where we transfer a bicycle from Alice to Bob,
and further we transfer it from Bob to Chris. Expectations:
* Output for Alice is spent
* Output for Bob is spent
* Output for Chris is unspent (he is the last person in transaction chain)
.. code-block:: js
const driver = require('bigchaindb-driver')
const API_PATH = 'http://localhost:9984/api/v1/'
const conn = new driver.Connection(API_PATH)
const alice = new driver.Ed25519Keypair()
const bob = new driver.Ed25519Keypair()
const chris = new driver.Ed25519Keypair()
console.log('Alice: ', alice.publicKey)
console.log('Bob: ', bob.publicKey)
console.log('Chris: ', chris.publicKey)
// Define the asset to store, in this example
// we store a bicycle with its serial number and manufacturer
assetdata = {
'bicycle': {
'serial_number': 'cde',
'manufacturer': 'Bicycle Inc.',
}
}
var txTransferBobSigned;
// Construct a transaction payload
const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
assetdata,
{'meta': 'meta'},
// A transaction needs an output
[ driver.Transaction.makeOutput(
driver.Transaction.makeEd25519Condition(alice.publicKey))
],
alice.publicKey
)
// Sign the transaction with private keys of Alice to fulfill it
const txCreateAliceSimpleSigned = driver.Transaction.signTransaction(txCreateAliceSimple, alice.privateKey)
console.log('\n\nPosting signed create transaction for Alice:\n', txCreateAliceSimpleSigned)
conn.postTransaction(txCreateAliceSimpleSigned)
// Check status of transaction every 0.5 seconds until fulfilled
.then(() => conn.pollStatusAndFetchTransaction(txCreateAliceSimpleSigned.id))
// Transfer bicycle from Alice to Bob
.then(() => {
const txTransferBob = driver.Transaction.makeTransferTransaction(
txCreateAliceSimpleSigned,
{'newOwner': 'Bob'},
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
0)
// Sign with alice's private key
txTransferBobSigned = driver.Transaction.signTransaction(txTransferBob, alice.privateKey)
console.log('\n\nPosting signed transaction to Bob:\n', txTransferBobSigned)
// Post and poll status
return conn.postTransaction(txTransferBobSigned)
})
.then(res => conn.pollStatusAndFetchTransaction(res.id))
// Second transfer of bicycle from Bob to Chris
.then(tx => {
const txTransferChris = driver.Transaction.makeTransferTransaction(
txTransferBobSigned,
{'newOwner': 'Chris'},
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(chris.publicKey))],
0)
// Sign with bob's private key
let txTransferChrisSigned = driver.Transaction.signTransaction(txTransferChris, bob.privateKey)
console.log('\n\nPosting signed transaction to Chris:\n', txTransferChrisSigned)
// Post and poll status
return conn.postTransaction(txTransferChrisSigned)
})
.then(res => conn.pollStatusAndFetchTransaction(res.id))
.then(() => conn.listOutputs(alice.publicKey, true))
.then(listSpentOutputs => {
console.log("\nSpent outputs for Alice: ", listSpentOutputs.length) // Spent outputs: 1
return conn.listOutputs(alice.publicKey, false)
})
.then(listUnspentOutputs => {
console.log("Unspent outputs for Alice: ", listUnspentOutputs.length) // Unspent outputs: 0
return conn.listOutputs(bob.publicKey, true)
})
.then(listSpentOutputs => {
console.log("\nSpent outputs for Bob: ", listSpentOutputs.length) // Spent outputs: 1
return conn.listOutputs(bob.publicKey, false)
})
.then(listUnspentOutputs => {
console.log("Unspent outputs for Bob: ", listUnspentOutputs.length) // Unspent outputs: 0
return conn.listOutputs(chris.publicKey, true)
})
.then(listSpentOutputs => {
console.log("\nSpent outputs for Chris: ", listSpentOutputs.length) // Spent outputs: 0
return conn.listOutputs(chris.publicKey, false)
})
.then(listUnspentOutputs => {
console.log("Unspent outputs for Chris: ", listUnspentOutputs.length) // Unspent outputs: 1
})
.catch(res => {console.log(res)})
Output of above code looks like this. As you can see, Chris has no spent output, but one unspent output.
.. code-block:: js
Spent outputs for Alice: 1
Unspent outputs for Alice: 0
Spent outputs for Bob: 1
Unspent outputs for Bob: 0
Spent outputs for Chris: 0
Unspent outputs for Chris: 1
Divisible Assets
----------------
@ -494,4 +623,4 @@ Yet to come!
.. TODO:
.. - Add lexer: https://stackoverflow.com/questions/4259105/which-sphinx-code-block-language-to-use-for-json
.. - Add divisible assets example
.. - Add more readable code with promises possibly.
.. - Add more readable code with promises possibly.

View File

@ -54,7 +54,7 @@
"husky": "^0.14.0",
"lint-staged": "^4.0.0",
"nyc": "^11.0.2",
"release-it": "^2.7.3",
"release-it": "^3.0.0",
"rimraf": "^2.5.4",
"sinon": "^3.0.0",
"webpack": "^3.0.0"

View File

@ -74,7 +74,12 @@ export default function baseRequest(url, { jsonBody, query, urlTemplateSpec, ...
// If status is not a 2xx (based on Response.ok), assume it's an error
// See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
if (!(res && res.ok)) {
throw res
const errorObject = {
message: 'HTTP Error: Requested page not reachable',
status: `${res.status} ${res.statusText}`,
requestURI: res.url
}
throw errorObject
}
return res
})

View File

@ -7,8 +7,21 @@ import { Connection } from '../../src'
const API_PATH = 'http://localhost:9984/api/v1/'
const conn = new Connection(API_PATH)
test('Payload thrown at incorrect API_PATH', t => {
const path = 'http://localhost:9984/api/wrong/'
const connection = new Connection(path)
const target = {
message: 'HTTP Error: Requested page not reachable',
status: '404 NOT FOUND',
requestURI: 'http://localhost:9984/api/wrong/transactions/transactionId'
}
connection.getTransaction('transactionId')
.catch(error => {
t.deepEqual(target, error)
})
})
test('generate API URLS', t => {
test('Generate API URLS', t => {
const endpoints = {
'blocks': 'blocks',
'blocksDetail': 'blocks/%(blockId)s',