Skip to content

Commit ad03590

Browse files
author
manolodewiner
committed
Merge branch 'search-metadata'
2 parents 6d57f5b + ba7f194 commit ad03590

File tree

5 files changed

+135
-39
lines changed

5 files changed

+135
-39
lines changed

.travis.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ before_install:
1818
-e BIGCHAINDB_KEYPAIR_PRIVATE=5C5Cknco7YxBRP9AgB1cbUVTL4FAcooxErLygw1DeG2D
1919
-e BIGCHAINDB_DATABASE_BACKEND=mongodb
2020
-e BIGCHAINDB_DATABASE_HOST=172.17.0.1
21-
bigchaindb/bigchaindb:1.0.0
21+
bigchaindb/bigchaindb:1.3.0
2222
start
2323
- gem install cowsay
2424
- npm install -g codecov

docs/source/usage.rst

+83-37
Original file line numberDiff line numberDiff line change
@@ -36,11 +36,11 @@ A simple connection with BigchainDB can be established like this.
3636
const conn = new driver.Connection(API_PATH)
3737
3838
It is also possible to connect to a BigchainDB node of the IPDB test net.
39-
To do so, you need to pass the **app_id and app_key**.
39+
To do so, you need to pass the **app_id and app_key**.
4040

41-
.. code-block:: js
41+
.. code-block:: js
4242
43-
let bdb = new driver.Connection('https://test.ipdb.io/api/v1/', {
43+
let bdb = new driver.Connection('https://test.ipdb.io/api/v1/', {
4444
app_id: 'dgi829l9',
4545
app_key: 'u008ik1bf83b43ce3a95uu0727e66fb9'
4646
})
@@ -71,10 +71,10 @@ that represents a bicycle:
7171
}
7272
}
7373
74-
We'll suppose that the bike belongs to Alice, and that it eventually will be
74+
We'll suppose that the bike belongs to Alice, and that it eventually will be
7575
transferred to Bob.
7676

77-
In general, you are free to define any JSON object you which to store for the
77+
In general, you are free to define any JSON object you which to store for the
7878
``'data'`` property (assetdata).
7979

8080
Metadata Definition (*optional*)
@@ -91,11 +91,11 @@ For example, the bicycle will be transferred on earth which is metadata:
9191
Asset Creation
9292
--------------
9393

94-
We're now ready to create the digital asset. First, let's make a 'CREATE'
94+
We're now ready to create the digital asset. First, let's make a 'CREATE'
9595
transaction:
9696

9797
.. code-block:: js
98-
98+
9999
const txCreateAliceSimple = driver.Transaction.makeCreateTransaction(
100100
assetdata,
101101
metadata,
@@ -113,10 +113,10 @@ For `CREATE` Transactions, this should usually just be a list of
113113
Outputs wrapping Ed25519 Conditions generated from the issuers' public
114114
keys (so that the issuers are the recipients of the created asset).
115115

116-
``alice.publicKey`` can be considered as the Input for the transaction.
117-
Each input spends/transfers a previous output by satisfying/fulfilling
118-
the crypto-conditions on that output. A CREATE transaction should have
119-
exactly one input. A TRANSFER transaction should have at least one input (i.e. ≥1).
116+
``alice.publicKey`` can be considered as the Input for the transaction.
117+
Each input spends/transfers a previous output by satisfying/fulfilling
118+
the crypto-conditions on that output. A CREATE transaction should have
119+
exactly one input. A TRANSFER transaction should have at least one input (i.e. ≥1).
120120

121121
Sign the transaction with private key of Alice to fulfill it:
122122

@@ -142,7 +142,7 @@ To check the status of the transaction:
142142
143143
conn.getStatus(txCreateAliceSimpleSigned.id)
144144
145-
It is also possible to check the status every 0.5 seconds
145+
It is also possible to check the status every 0.5 seconds
146146
with use of the transaction ``id``:
147147

148148
.. code-block:: js
@@ -168,7 +168,7 @@ Alice could retrieve the transaction:
168168
169169
conn.getTransaction(txCreateAliceSimpleSigned.id)
170170
171-
First, let's prepare the transaction to be transferred.
171+
First, let's prepare the transaction to be transferred.
172172

173173
.. code-block:: js
174174
@@ -179,7 +179,7 @@ First, let's prepare the transaction to be transferred.
179179
// metadata
180180
{price: '100 euro'},
181181
182-
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
182+
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
183183
0
184184
);
185185
@@ -190,7 +190,7 @@ The function ``makeTransferTransaction()`` needs following parameters:
190190
- 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.
191191
- Indices of the outputs in `unspent transaction` that this transaction fulfills.
192192

193-
Fulfill transaction by signing it with Alice's private key.
193+
Fulfill transaction by signing it with Alice's private key.
194194

195195
.. code-block:: js
196196
@@ -228,6 +228,10 @@ Querying for Assets
228228

229229
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.
230230

231+
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:
232+
- In the assets search the call returns the asset id which is the same id of the transaction that created the asset.
233+
- In the metadata search the call returns the transaction id that contains this metadata.
234+
231235
Let’s assume that we created 3 assets that look like this:
232236

233237
.. code-block:: js
@@ -245,9 +249,9 @@ Let’s perform a text search for all assets that contain the word 'Bicycle Inc.
245249
conn.searchAssets('Bicycle Inc.')
246250
.then(assets => console.log('Found assets with serial number Bicycle Inc.:', assets))
247251
248-
Which leads to following result:
252+
Which leads to following result:
249253

250-
.. code-block:: js
254+
.. code-block:: js
251255
252256
[
253257
{
@@ -265,7 +269,49 @@ Which leads to following result:
265269
]
266270
267271
268-
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.
272+
This call returns all the assets that match the string 'Bicycle Inc.', sorted by text score, as well as the asset id.
273+
274+
275+
Querying for Metadata
276+
-------------------
277+
278+
Similar as querying for assets, in BigchainDB you can query for metadata using simple text search.
279+
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.
280+
281+
Having 3 metadata objets that look like this:
282+
283+
.. code-block:: js
284+
285+
metadata = [
286+
{'state': {'price': 145, 'eur/us': '1.32'}},
287+
{'state': {'price': 236, 'eur/us': '1.15'}},
288+
{'state': {'price': 102, 'eur/us': '1.32'}},
289+
]
290+
291+
Let’s perform a text search for all metadata that contains the word '1.32':
292+
293+
.. code-block:: js
294+
295+
conn.searchMetadata('Bicycle Inc.')
296+
.then(assets => console.log('Found assets with serial number Bicycle Inc.:', assets))
297+
298+
Which leads to following result:
299+
300+
.. code-block:: js
301+
302+
[
303+
{
304+
'metadata': {'state': {'price': 145, 'eur/us': '1.32'}},
305+
'id': '14045a0e27ea971f8ac88762d2d74518d3a21f3f0fcd9d8a9a3b644b689cf3eb'
306+
},
307+
{
308+
'metadata': {'state': {'price': 102, 'eur/us': '1.32'}},
309+
'id': '6dd91f4700b3f66c55c50be009018e96f026d37f565d042d1aedfb322623d17d'
310+
}
311+
]
312+
313+
314+
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.
269315

270316

271317

@@ -335,9 +381,9 @@ Recap: Asset Creation & Transfer
335381
txCreateAliceSimpleSigned,
336382
// metadata
337383
{price: '100 euro'},
338-
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
384+
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
339385
0)
340-
386+
341387
// Sign with alice's private key
342388
let txTransferBobSigned = driver.Transaction.signTransaction(txTransferBob, alice.privateKey)
343389
console.log('Posting signed transaction: ', txTransferBobSigned)
@@ -356,13 +402,13 @@ Recap: Asset Creation & Transfer
356402
// Search for asset based on the serial number of the bicycle
357403
.then(() => conn.searchAssets('Bicycle Inc.'))
358404
.then(assets => console.log('Found assets with serial number Bicycle Inc.:', assets))
359-
360405
361-
Ed25519Keypair Seed Functionality
406+
407+
Ed25519Keypair Seed Functionality
362408
---------------------------------
363409

364-
BigchainDB JavaScript driver allows you to create a keypair based on a seed.
365-
The constructor accepts a 32 byte seed. One of the ways to create a seed from
410+
BigchainDB JavaScript driver allows you to create a keypair based on a seed.
411+
The constructor accepts a 32 byte seed. One of the ways to create a seed from
366412
a string (e.g. a passphrase) is the one used by ``bip39``, specifically the function ``mnemonicToSeed``.
367413

368414
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
490536
</div>
491537

492538

493-
Besides that, a NodeJs version has been created to display the validated transactions.
539+
Besides that, a NodeJs version has been created to display the validated transactions.
494540
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``.
495541

496542
.. code-block:: js
@@ -514,22 +560,22 @@ All transactions are printed to the console. To use this piece of code, you will
514560
Difference unspent and spent output
515561
-----------------------------------
516562
An unspent output is simply an output of a transaction which isn't yet an input of another transaction.
517-
So, if we transfer an asset, the output becomes spent, because it becomes the input of the transfer transaction.
563+
So, if we transfer an asset, the output becomes spent, because it becomes the input of the transfer transaction.
518564
The transfer transactions its output becomes unspent now until he transfers the asset again to somebody else.
519565

520-
We will demonstrate this with a piece of code where we transfer a bicycle from Alice to Bob,
566+
We will demonstrate this with a piece of code where we transfer a bicycle from Alice to Bob,
521567
and further we transfer it from Bob to Chris. Expectations:
522568

523-
* Output for Alice is spent
569+
* Output for Alice is spent
524570
* Output for Bob is spent
525571
* Output for Chris is unspent (he is the last person in transaction chain)
526572

527573
.. code-block:: js
528574
529575
const driver = require('bigchaindb-driver')
530576
const API_PATH = 'http://localhost:9984/api/v1/'
531-
const conn = new driver.Connection(API_PATH)
532-
577+
const conn = new driver.Connection(API_PATH)
578+
533579
const alice = new driver.Ed25519Keypair()
534580
const bob = new driver.Ed25519Keypair()
535581
const chris = new driver.Ed25519Keypair()
@@ -573,9 +619,9 @@ and further we transfer it from Bob to Chris. Expectations:
573619
const txTransferBob = driver.Transaction.makeTransferTransaction(
574620
txCreateAliceSimpleSigned,
575621
{'newOwner': 'Bob'},
576-
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
622+
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(bob.publicKey))],
577623
0)
578-
624+
579625
// Sign with alice's private key
580626
txTransferBobSigned = driver.Transaction.signTransaction(txTransferBob, alice.privateKey)
581627
console.log('\n\nPosting signed transaction to Bob:\n', txTransferBobSigned)
@@ -590,9 +636,9 @@ and further we transfer it from Bob to Chris. Expectations:
590636
const txTransferChris = driver.Transaction.makeTransferTransaction(
591637
txTransferBobSigned,
592638
{'newOwner': 'Chris'},
593-
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(chris.publicKey))],
639+
[driver.Transaction.makeOutput(driver.Transaction.makeEd25519Condition(chris.publicKey))],
594640
0)
595-
641+
596642
// Sign with bob's private key
597643
let txTransferChrisSigned = driver.Transaction.signTransaction(txTransferChris, bob.privateKey)
598644
console.log('\n\nPosting signed transaction to Chris:\n', txTransferChrisSigned)
@@ -627,7 +673,7 @@ and further we transfer it from Bob to Chris. Expectations:
627673
})
628674
.catch(res => {console.log(res)})
629675
630-
Output of above code looks like this. As you can see, Chris has no spent output, but one unspent output.
676+
Output of above code looks like this. As you can see, Chris has no spent output, but one unspent output.
631677

632678
.. code-block:: js
633679
@@ -654,7 +700,7 @@ Let's assume we have created a token to pay each other for small transactions li
654700
}
655701
656702
Let's create the asset. Note that we give an extra parameter to the ``makeOutput()`` function.
657-
We give it the parameter ``'4'`` to indicate that we want to create 4 tokens.
703+
We give it the parameter ``'4'`` to indicate that we want to create 4 tokens.
658704
**Pay attention to give the function a String instead of a plain Number.**
659705

660706
.. code-block:: js
@@ -690,7 +736,7 @@ To make the use of the last parameter of ``makeTransferTransaction()`` function
690736
We will fulfill the first and second output of the create transaction (0, 1) because Carly and Bob decide to redistribute some money.
691737

692738
* Output 0 represents 2 tokens for Carly
693-
* Output 1 represents 1 token for Bob
739+
* Output 1 represents 1 token for Bob
694740

695741
This gives us 3 tokens to redistribute. I want to give 1 token to Carly and 2 tokens Alice.
696742

src/connection.js

+13-1
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export default class Connection {
2525
'transactions': 'transactions',
2626
'transactionsDetail': 'transactions/%(transactionId)s',
2727
'assets': 'assets',
28+
'metadata': 'metadata',
2829
'votes': 'votes'
2930
}[endpoint]
3031
}
@@ -167,7 +168,6 @@ export default class Connection {
167168
})
168169
}
169170

170-
171171
/**
172172
* @public
173173
* @param search
@@ -179,4 +179,16 @@ export default class Connection {
179179
}
180180
})
181181
}
182+
183+
/**
184+
* @public
185+
* @param search
186+
*/
187+
searchMetadata(search) {
188+
return this._req(this.getApiUrls('metadata'), {
189+
query: {
190+
search
191+
}
192+
})
193+
}
182194
}

test/connection/test_connection.js

+15
Original file line numberDiff line numberDiff line change
@@ -219,3 +219,18 @@ test('Get asset for text', t => {
219219
{ query: { search } }
220220
))
221221
})
222+
223+
224+
test('Get metadata for text', t => {
225+
const expectedPath = 'path'
226+
const search = 'abc'
227+
228+
conn._req = sinon.spy()
229+
conn.getApiUrls = sinon.stub().returns(expectedPath)
230+
231+
conn.searchMetadata(search)
232+
t.truthy(conn._req.calledWith(
233+
expectedPath,
234+
{ query: { search } }
235+
))
236+
})

test/integration/test_integration.js

+23
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,29 @@ test('Search for an asset', t => {
264264
})
265265

266266

267+
test('Search for metadata', t => {
268+
const conn = new Connection(API_PATH)
269+
270+
const createTx = Transaction.makeCreateTransaction(
271+
asset(),
272+
metaData,
273+
[aliceOutput],
274+
alice.publicKey
275+
)
276+
const createTxSigned = Transaction.signTransaction(
277+
createTx,
278+
alice.privateKey
279+
)
280+
281+
return conn.postTransaction(createTxSigned)
282+
.then(({ id }) => conn.pollStatusAndFetchTransaction(id))
283+
.then(() => conn.searchMetadata(createTxSigned.metadata.message))
284+
.then(assets => t.truthy(
285+
assets.pop(),
286+
createTxSigned.metadata.message
287+
))
288+
})
289+
267290
test('Search blocks containing a transaction', t => {
268291
const conn = new Connection(API_PATH)
269292

0 commit comments

Comments
 (0)