mirror of
https://github.com/bigchaindb/js-bigchaindb-driver.git
synced 2024-11-22 09:46:58 +01:00
Merge branch 'search-metadata'
This commit is contained in:
commit
ad03590347
@ -18,7 +18,7 @@ before_install:
|
||||
-e BIGCHAINDB_KEYPAIR_PRIVATE=5C5Cknco7YxBRP9AgB1cbUVTL4FAcooxErLygw1DeG2D
|
||||
-e BIGCHAINDB_DATABASE_BACKEND=mongodb
|
||||
-e BIGCHAINDB_DATABASE_HOST=172.17.0.1
|
||||
bigchaindb/bigchaindb:1.0.0
|
||||
bigchaindb/bigchaindb:1.3.0
|
||||
start
|
||||
- gem install cowsay
|
||||
- npm install -g codecov
|
||||
|
@ -36,11 +36,11 @@ A simple connection with BigchainDB can be established like this.
|
||||
const conn = new driver.Connection(API_PATH)
|
||||
|
||||
It is also possible to connect to a BigchainDB node of the IPDB test net.
|
||||
To do so, you need to pass the **app_id and app_key**.
|
||||
To do so, you need to pass the **app_id and app_key**.
|
||||
|
||||
.. code-block:: js
|
||||
.. code-block:: js
|
||||
|
||||
let bdb = new driver.Connection('https://test.ipdb.io/api/v1/', {
|
||||
let bdb = new driver.Connection('https://test.ipdb.io/api/v1/', {
|
||||
app_id: 'dgi829l9',
|
||||
app_key: 'u008ik1bf83b43ce3a95uu0727e66fb9'
|
||||
})
|
||||
@ -71,10 +71,10 @@ that represents a bicycle:
|
||||
}
|
||||
}
|
||||
|
||||
We'll suppose that the bike belongs to Alice, and that it eventually will be
|
||||
We'll suppose that the bike belongs to Alice, and that it eventually will be
|
||||
transferred to Bob.
|
||||
|
||||
In general, you are free to define any JSON object you which to store for the
|
||||
In general, you are free to define any JSON object you which to store for the
|
||||
``'data'`` property (assetdata).
|
||||
|
||||
Metadata Definition (*optional*)
|
||||
@ -91,11 +91,11 @@ For example, the bicycle will be transferred on earth which is metadata:
|
||||
Asset Creation
|
||||
--------------
|
||||
|
||||
We're now ready to create the digital asset. First, let's make a 'CREATE'
|
||||
We're now ready to create the digital asset. First, let's make a 'CREATE'
|
||||
transaction:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
|
||||
const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
|
||||
assetdata,
|
||||
metadata,
|
||||
@ -113,10 +113,10 @@ For `CREATE` Transactions, this should usually just be a list of
|
||||
Outputs wrapping Ed25519 Conditions generated from the issuers' public
|
||||
keys (so that the issuers are the recipients of the created asset).
|
||||
|
||||
``alice.publicKey`` can be considered as the Input for the transaction.
|
||||
Each input spends/transfers a previous output by satisfying/fulfilling
|
||||
the crypto-conditions on that output. A CREATE transaction should have
|
||||
exactly one input. A TRANSFER transaction should have at least one input (i.e. ≥1).
|
||||
``alice.publicKey`` can be considered as the Input for the transaction.
|
||||
Each input spends/transfers a previous output by satisfying/fulfilling
|
||||
the crypto-conditions on that output. A CREATE transaction should have
|
||||
exactly one input. A TRANSFER transaction should have at least one input (i.e. ≥1).
|
||||
|
||||
Sign the transaction with private key of Alice to fulfill it:
|
||||
|
||||
@ -142,7 +142,7 @@ To check the status of the transaction:
|
||||
|
||||
conn.getStatus(txCreateAliceSimpleSigned.id)
|
||||
|
||||
It is also possible to check the status every 0.5 seconds
|
||||
It is also possible to check the status every 0.5 seconds
|
||||
with use of the transaction ``id``:
|
||||
|
||||
.. code-block:: js
|
||||
@ -168,7 +168,7 @@ Alice could retrieve the transaction:
|
||||
|
||||
conn.getTransaction(txCreateAliceSimpleSigned.id)
|
||||
|
||||
First, let's prepare the transaction to be transferred.
|
||||
First, let's prepare the transaction to be transferred.
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
@ -179,7 +179,7 @@ First, let's prepare the transaction to be transferred.
|
||||
// metadata
|
||||
{price: '100 euro'},
|
||||
|
||||
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
|
||||
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
|
||||
0
|
||||
);
|
||||
|
||||
@ -190,7 +190,7 @@ The function ``makeTransferTransaction()`` needs following parameters:
|
||||
- Array of output objects to add to the transaction: Think of these as the recipients of the asset after the transaction. For `TRANSFER` transactions, this should usually just be a list of outputs wrapping Ed25519 conditions generated from the public keys of the recipients.
|
||||
- Indices of the outputs in `unspent transaction` that this transaction fulfills.
|
||||
|
||||
Fulfill transaction by signing it with Alice's private key.
|
||||
Fulfill transaction by signing it with Alice's private key.
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
@ -228,6 +228,10 @@ Querying for Assets
|
||||
|
||||
BigchainDB allows you to query for assets using simple text search. This search is applied to all the strings inside the asset payload and returns all the assets that match a given text search string.
|
||||
|
||||
BigchainDB also allows you to query for metadata, but there are some differences. The response of the text search call, beside retrieving the asset or metadata in each case, it consist of:
|
||||
- In the assets search the call returns the asset id which is the same id of the transaction that created the asset.
|
||||
- In the metadata search the call returns the transaction id that contains this metadata.
|
||||
|
||||
Let’s assume that we created 3 assets that look like this:
|
||||
|
||||
.. code-block:: js
|
||||
@ -245,9 +249,9 @@ Let’s perform a text search for all assets that contain the word 'Bicycle Inc.
|
||||
conn.searchAssets('Bicycle Inc.')
|
||||
.then(assets => console.log('Found assets with serial number Bicycle Inc.:', assets))
|
||||
|
||||
Which leads to following result:
|
||||
Which leads to following result:
|
||||
|
||||
.. code-block:: js
|
||||
.. code-block:: js
|
||||
|
||||
[
|
||||
{
|
||||
@ -265,7 +269,49 @@ Which leads to following result:
|
||||
]
|
||||
|
||||
|
||||
This call returns all the assets that match the string 'Bicycle Inc.', sorted by text score, as well as the asset id. This is the same id of the transaction that created the asset.
|
||||
This call returns all the assets that match the string 'Bicycle Inc.', sorted by text score, as well as the asset id.
|
||||
|
||||
|
||||
Querying for Metadata
|
||||
-------------------
|
||||
|
||||
Similar as querying for assets, in BigchainDB you can query for metadata using simple text search.
|
||||
This search is applied to all the strings inside the metadata payload and returns all the metadata payloads that match a given text search string.
|
||||
|
||||
Having 3 metadata objets that look like this:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
metadata = [
|
||||
{'state': {'price': 145, 'eur/us': '1.32'}},
|
||||
{'state': {'price': 236, 'eur/us': '1.15'}},
|
||||
{'state': {'price': 102, 'eur/us': '1.32'}},
|
||||
]
|
||||
|
||||
Let’s perform a text search for all metadata that contains the word '1.32':
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
conn.searchMetadata('Bicycle Inc.')
|
||||
.then(assets => console.log('Found assets with serial number Bicycle Inc.:', assets))
|
||||
|
||||
Which leads to following result:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
[
|
||||
{
|
||||
'metadata': {'state': {'price': 145, 'eur/us': '1.32'}},
|
||||
'id': '14045a0e27ea971f8ac88762d2d74518d3a21f3f0fcd9d8a9a3b644b689cf3eb'
|
||||
},
|
||||
{
|
||||
'metadata': {'state': {'price': 102, 'eur/us': '1.32'}},
|
||||
'id': '6dd91f4700b3f66c55c50be009018e96f026d37f565d042d1aedfb322623d17d'
|
||||
}
|
||||
]
|
||||
|
||||
|
||||
This call returns all the metadata objects that match the string '1.32', sorted by text score, as well as the transaction id corresponding to each metadata object.
|
||||
|
||||
|
||||
|
||||
@ -335,9 +381,9 @@ Recap: Asset Creation & Transfer
|
||||
txCreateAliceSimpleSigned,
|
||||
// metadata
|
||||
{price: '100 euro'},
|
||||
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
|
||||
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
|
||||
0)
|
||||
|
||||
|
||||
// Sign with alice's private key
|
||||
let txTransferBobSigned = driver.Transaction.signTransaction(txTransferBob, alice.privateKey)
|
||||
console.log('Posting signed transaction: ', txTransferBobSigned)
|
||||
@ -356,13 +402,13 @@ Recap: Asset Creation & Transfer
|
||||
// Search for asset based on the serial number of the bicycle
|
||||
.then(() => conn.searchAssets('Bicycle Inc.'))
|
||||
.then(assets => console.log('Found assets with serial number Bicycle Inc.:', assets))
|
||||
|
||||
|
||||
Ed25519Keypair Seed Functionality
|
||||
|
||||
Ed25519Keypair Seed Functionality
|
||||
---------------------------------
|
||||
|
||||
BigchainDB JavaScript driver allows you to create a keypair based on a seed.
|
||||
The constructor accepts a 32 byte seed. One of the ways to create a seed from
|
||||
BigchainDB JavaScript driver allows you to create a keypair based on a seed.
|
||||
The constructor accepts a 32 byte seed. One of the ways to create a seed from
|
||||
a string (e.g. a passphrase) is the one used by ``bip39``, specifically the function ``mnemonicToSeed``.
|
||||
|
||||
Install bip39 with npm: ``npm install bip39``
|
||||
@ -490,7 +536,7 @@ Below piece of code can be opened in your web browser. It will connect to your w
|
||||
</div>
|
||||
|
||||
|
||||
Besides that, a NodeJs version has been created to display the validated transactions.
|
||||
Besides that, a NodeJs version has been created to display the validated transactions.
|
||||
All transactions are printed to the console. To use this piece of code, you will need the ``ws`` (WebSocket package) through npm: ``npm install --save ws``.
|
||||
|
||||
.. code-block:: js
|
||||
@ -514,13 +560,13 @@ 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.
|
||||
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,
|
||||
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 Alice is spent
|
||||
* Output for Bob is spent
|
||||
* Output for Chris is unspent (he is the last person in transaction chain)
|
||||
|
||||
@ -528,8 +574,8 @@ and further we transfer it from Bob to Chris. Expectations:
|
||||
|
||||
const driver = require('bigchaindb-driver')
|
||||
const API_PATH = 'http://localhost:9984/api/v1/'
|
||||
const conn = new driver.Connection(API_PATH)
|
||||
|
||||
const conn = new driver.Connection(API_PATH)
|
||||
|
||||
const alice = new driver.Ed25519Keypair()
|
||||
const bob = new driver.Ed25519Keypair()
|
||||
const chris = new driver.Ed25519Keypair()
|
||||
@ -573,9 +619,9 @@ and further we transfer it from Bob to Chris. Expectations:
|
||||
const txTransferBob = driver.Transaction.makeTransferTransaction(
|
||||
txCreateAliceSimpleSigned,
|
||||
{'newOwner': 'Bob'},
|
||||
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
|
||||
[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)
|
||||
@ -590,9 +636,9 @@ and further we transfer it from Bob to Chris. Expectations:
|
||||
const txTransferChris = driver.Transaction.makeTransferTransaction(
|
||||
txTransferBobSigned,
|
||||
{'newOwner': 'Chris'},
|
||||
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(chris.publicKey))],
|
||||
[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)
|
||||
@ -627,7 +673,7 @@ and further we transfer it from Bob to Chris. Expectations:
|
||||
})
|
||||
.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.
|
||||
Output of above code looks like this. As you can see, Chris has no spent output, but one unspent output.
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
@ -654,7 +700,7 @@ Let's assume we have created a token to pay each other for small transactions li
|
||||
}
|
||||
|
||||
Let's create the asset. Note that we give an extra parameter to the ``makeOutput()`` function.
|
||||
We give it the parameter ``'4'`` to indicate that we want to create 4 tokens.
|
||||
We give it the parameter ``'4'`` to indicate that we want to create 4 tokens.
|
||||
**Pay attention to give the function a String instead of a plain Number.**
|
||||
|
||||
.. code-block:: js
|
||||
@ -690,7 +736,7 @@ To make the use of the last parameter of ``makeTransferTransaction()`` function
|
||||
We will fulfill the first and second output of the create transaction (0, 1) because Carly and Bob decide to redistribute some money.
|
||||
|
||||
* Output 0 represents 2 tokens for Carly
|
||||
* Output 1 represents 1 token for Bob
|
||||
* Output 1 represents 1 token for Bob
|
||||
|
||||
This gives us 3 tokens to redistribute. I want to give 1 token to Carly and 2 tokens Alice.
|
||||
|
||||
|
@ -25,6 +25,7 @@ export default class Connection {
|
||||
'transactions': 'transactions',
|
||||
'transactionsDetail': 'transactions/%(transactionId)s',
|
||||
'assets': 'assets',
|
||||
'metadata': 'metadata',
|
||||
'votes': 'votes'
|
||||
}[endpoint]
|
||||
}
|
||||
@ -167,7 +168,6 @@ export default class Connection {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @param search
|
||||
@ -179,4 +179,16 @@ export default class Connection {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
/**
|
||||
* @public
|
||||
* @param search
|
||||
*/
|
||||
searchMetadata(search) {
|
||||
return this._req(this.getApiUrls('metadata'), {
|
||||
query: {
|
||||
search
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -219,3 +219,18 @@ test('Get asset for text', t => {
|
||||
{ query: { search } }
|
||||
))
|
||||
})
|
||||
|
||||
|
||||
test('Get metadata for text', t => {
|
||||
const expectedPath = 'path'
|
||||
const search = 'abc'
|
||||
|
||||
conn._req = sinon.spy()
|
||||
conn.getApiUrls = sinon.stub().returns(expectedPath)
|
||||
|
||||
conn.searchMetadata(search)
|
||||
t.truthy(conn._req.calledWith(
|
||||
expectedPath,
|
||||
{ query: { search } }
|
||||
))
|
||||
})
|
||||
|
@ -264,6 +264,29 @@ test('Search for an asset', t => {
|
||||
})
|
||||
|
||||
|
||||
test('Search for metadata', 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.searchMetadata(createTxSigned.metadata.message))
|
||||
.then(assets => t.truthy(
|
||||
assets.pop(),
|
||||
createTxSigned.metadata.message
|
||||
))
|
||||
})
|
||||
|
||||
test('Search blocks containing a transaction', t => {
|
||||
const conn = new Connection(API_PATH)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user