mirror of
https://github.com/bigchaindb/js-bigchaindb-driver.git
synced 2024-11-22 01:36:56 +01:00
Merge branch 'master' into websocket-api-doc
This commit is contained in:
commit
8804998546
@ -64,7 +64,7 @@ that represents a bicycle:
|
|||||||
|
|
||||||
.. code-block:: js
|
.. code-block:: js
|
||||||
|
|
||||||
assetdata = {
|
const assetdata = {
|
||||||
'bicycle': {
|
'bicycle': {
|
||||||
'serial_number': 'abcd1234',
|
'serial_number': 'abcd1234',
|
||||||
'manufacturer': 'Bicycle Inc.',
|
'manufacturer': 'Bicycle Inc.',
|
||||||
@ -86,7 +86,7 @@ For example, the bicycle will be transferred on earth which is metadata:
|
|||||||
|
|
||||||
.. code-block:: js
|
.. code-block:: js
|
||||||
|
|
||||||
metadata = {'planet': 'earth'}
|
const metadata = {'planet': 'earth'}
|
||||||
|
|
||||||
Asset Creation
|
Asset Creation
|
||||||
--------------
|
--------------
|
||||||
@ -288,7 +288,7 @@ Recap: Asset Creation & Transfer
|
|||||||
|
|
||||||
// Define the asset to store, in this example
|
// Define the asset to store, in this example
|
||||||
// we store a bicycle with its serial number and manufacturer
|
// we store a bicycle with its serial number and manufacturer
|
||||||
assetdata = {
|
const assetdata = {
|
||||||
'bicycle': {
|
'bicycle': {
|
||||||
'serial_number': 'cde',
|
'serial_number': 'cde',
|
||||||
'manufacturer': 'Bicycle Inc.',
|
'manufacturer': 'Bicycle Inc.',
|
||||||
@ -298,7 +298,7 @@ Recap: Asset Creation & Transfer
|
|||||||
// Metadata contains information about the transaction itself
|
// Metadata contains information about the transaction itself
|
||||||
// (can be `null` if not needed)
|
// (can be `null` if not needed)
|
||||||
// E.g. the bicycle is fabricated on earth
|
// E.g. the bicycle is fabricated on earth
|
||||||
metadata = {'planet': 'earth'}
|
const metadata = {'planet': 'earth'}
|
||||||
|
|
||||||
// Construct a transaction payload
|
// Construct a transaction payload
|
||||||
const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
|
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
|
Divisible Assets
|
||||||
----------------
|
----------------
|
||||||
@ -494,4 +623,4 @@ Yet to come!
|
|||||||
.. TODO:
|
.. TODO:
|
||||||
.. - Add lexer: https://stackoverflow.com/questions/4259105/which-sphinx-code-block-language-to-use-for-json
|
.. - Add lexer: https://stackoverflow.com/questions/4259105/which-sphinx-code-block-language-to-use-for-json
|
||||||
.. - Add divisible assets example
|
.. - Add divisible assets example
|
||||||
.. - Add more readable code with promises possibly.
|
.. - Add more readable code with promises possibly.
|
||||||
|
@ -54,7 +54,7 @@
|
|||||||
"husky": "^0.14.0",
|
"husky": "^0.14.0",
|
||||||
"lint-staged": "^4.0.0",
|
"lint-staged": "^4.0.0",
|
||||||
"nyc": "^11.0.2",
|
"nyc": "^11.0.2",
|
||||||
"release-it": "^2.7.3",
|
"release-it": "^3.0.0",
|
||||||
"rimraf": "^2.5.4",
|
"rimraf": "^2.5.4",
|
||||||
"sinon": "^3.0.0",
|
"sinon": "^3.0.0",
|
||||||
"webpack": "^3.0.0"
|
"webpack": "^3.0.0"
|
||||||
|
@ -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
|
// 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
|
// See https://developer.mozilla.org/en-US/docs/Web/API/GlobalFetch/fetch
|
||||||
if (!(res && res.ok)) {
|
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
|
return res
|
||||||
})
|
})
|
||||||
|
@ -7,8 +7,21 @@ import { Connection } from '../../src'
|
|||||||
const API_PATH = 'http://localhost:9984/api/v1/'
|
const API_PATH = 'http://localhost:9984/api/v1/'
|
||||||
const conn = new Connection(API_PATH)
|
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 = {
|
const endpoints = {
|
||||||
'blocks': 'blocks',
|
'blocks': 'blocks',
|
||||||
'blocksDetail': 'blocks/%(blockId)s',
|
'blocksDetail': 'blocks/%(blockId)s',
|
||||||
|
Loading…
Reference in New Issue
Block a user