OriginTrail
Search…
DKG v6 JS client
This page intends to introduce a basic flow using dkg-client:
  • publishing a dataset to the DKG
  • resolving a dataset to the DKG
  • searching for it via the search API
  • querying using SPARQL
  • validating triplets

Installation

You can install DKG client in you project by executing next command in your project root directory:
1
npm install [email protected]
Copied!

Initialization of client

To use DKG client we need to have OT-node v6 endpoint, you can run it locally or setup a node that will be part of public beta DKG.
In the code snippet below we will enter our node hostname and port, and after connecting to our node we will perform informations about node just to confirm that everything is working fine.
1
const DKGClient = require('dkg-client');
2
​
3
const OT_NODE_HOSTNAME = '0.0.0.0';
4
const OT_NODE_PORT = '8900';
5
​
6
// initialize connection to your DKG Node
7
let options = { endpoint: OT_NODE_HOSTNAME, port: OT_NODE_PORT, useSSL: false, loglevel: 'info' };
8
const dkg = new DKGClient(options);
9
​
10
// get info about endpoint that you are connected to
11
dkg.nodeInfo().then(result => console.log(result));
Copied!

Publishing product dataset on DKG

Dataset Description
The dataset used in this tutorial is maintained by jsonld.com can be found here https://jsonld.com/product/
It follows Schema.org as standard and contains an object of type Product with its description, identifier, brand, rating and other details. An extensive documentation for Product class can be found here https://schema.org/Product. The sample dataset values can be referred below:
1
{
2
"@context": "https://schema.org/",
3
"@type": "Product",
4
"name": "Executive Anvil",
5
"image": "http://www.example.com/anvil_executive.jpg",
6
"description": "Sleeker than ACME's Classic Anvil, the Executive Anvil is perfect for the business traveler looking for something to drop from a height.",
7
"mpn": "925872",
8
"brand": {
9
"@type": "Thing",
10
"name": "ACME"
11
},
12
"aggregateRating": {
13
"@type": "AggregateRating",
14
"ratingValue": "4.4",
15
"reviewCount": "89"
16
},
17
"offers": {
18
"@type": "Offer",
19
"priceCurrency": "USD",
20
"price": "119.99",
21
"priceValidUntil": "2020-11-05",
22
"itemCondition": "http://schema.org/UsedCondition",
23
"availability": "http://schema.org/InStock",
24
"seller": {
25
"@type": "Organization",
26
"name": "Executive Objects"
27
}
28
}
29
}
Copied!
Save the above dataset as Product.json

Publishing the dataset

We can also publish the above Product dataset with the publish method in the client:
1
options = {
2
filepath: '{LocalPATH}/Product.json',
3
assets: ['0x123456789123456789123456789'],
4
keywords: ['Product', 'Executive Objects', 'ACME'],
5
visibility: true
6
};
7
​
8
dkg.publish(options).then((result) => {
9
console.log(JSON.stringify(result))
10
});
Copied!
As a result, user will get the following response for publishing the dataset successfully.
1
{
2
status: 'COMPLETED',
3
data: {
4
id: '0b2f32a380f61fda8a3b2461074183dfbc9e19c0cbb59275969e6370aa5b26cf',
5
rootHash: '94ad72c79a88fd2da048cc8c4b3abbdc2cd507ab4b9fccfacd9eae0f8907dac3',
6
signature: '0x2a036001d2ca32fb2e528d6e8c414ab86f5b000e87558ae9c75a74c46bcd4fc16d47e865412341640b3d81e05fd2e4ed9f96d63188ad28476b276ba1d7c06d581b',
7
metadata: {
8
type: 'Product',
9
timestamp: '2021-12-30T13:08:14.770Z',
10
issuer: '0xbd084ab97c704fe4a6d620cb7c30c0be0366646f',
11
visibility: true,
12
dataHash: 'ed13153fa4090eceedf6c1dd1aa030ec45ab75c2f9510c64a2014f1c6424e7dd'
13
},
14
blockchain: {
15
name: 'polygon::testnet',
16
transactionHash: '0x2450007ccaec94e18f2d0ed20e776f05aa43ab6f8480d3ee2d77c61bece71184'
17
}
18
}
19
}
20
​
Copied!
The assertion_id(id) above can be used for Resolve in next section.

Resolve an assertion on the DKG

Data are persisted on the network by publishing on the DKG. Data are published as assertions that are immutable and verifiable, which could be resolved using assertion ID. Assertion ID is signed hash of published triples which is calculated during the publish.
1
options = {
2
ids: [
3
'066787bc7269c062fe73b0ebb004c258e07151777e6dfba027fea046df5caf7c',
4
'0b2f32a380f61fda8a3b2461074183dfbc9e19c0cbb59275969e6370aa5b26cf'
5
]
6
};
7
8
dkg.resolve(options).then((result) => {
9
console.log(JSON.stringify(result));
10
});
Copied!
The result of above is the following:
1
{
2
"status": "COMPLETED",
3
"data": [
4
{
5
"066787bc7269c062fe73b0ebb004c258e07151777e6dfba027fea046df5caf7c": {
6
"metadata": {
7
"dataHash": "ed13153fa4090eceedf6c1dd1aa030ec45ab75c2f9510c64a2014f1c6424e7dd",
8
"issuer": "0xbd084ab97c704fe4a6d620cb7c30c0be0366646f",
9
"timestamp": "2021-12-29T15:33:00.932Z",
10
"type": "Product",
11
"visibility": true
12
},
13
"blockchain": {
14
"name": "polygon::testnet",
15
"transactionHash": "0xa413f4e75f4e858663a45db717a800d2034334fac107791d47158884fe4a712b"
16
},
17
"assets": [
18
"2cb2b246cae224b372d36f10ceae1447597fbb129b8a98c18465a6e2f65444cb"
19
],
20
"keywords": [
21
"Product",
22
"executiveanvil",
23
"product,executive objects,acme"
24
],
25
"signature": "0xfaf131689de19ddebf8b1fc4068274d5d60fc9d050273515292152a4758f886251d80eeb9289fe07f662314b624187f7452a93f5147f5bc26630475b6698548d1c",
26
"rootHash": "c9309614ff33632620fe3904364c92bd1b379ebf59ef16aec69153d92975387b",
27
"id": "066787bc7269c062fe73b0ebb004c258e07151777e6dfba027fea046df5caf7c",
28
"data": {
29
"@context": "https://www.schema.org/",
30
"@graph": [
31
{
32
"aggregateRating": {
33
"id": "_:b1",
34
"ratingValue": "4.4",
35
"reviewCount": "89",
36
"type": "AggregateRating"
37
},
38
"brand": {
39
"id": "_:b2",
40
"name": "ACME",
41
"type": "Thing"
42
},
43
"description": "Sleeker than ACME's Classic Anvil, the Executive Anvil is perfect for the business traveler looking for something to drop from a height.",
44
"image": "http://www.example.com/anvil_executive.jpg",
45
"mpn": "925872",
46
"name": "Executive Anvil",
47
"offers": {
48
"availability": "http://schema.org/InStock",
49
"id": "_:b3",
50
"itemCondition": "http://schema.org/UsedCondition",
51
"price": "119.99",
52
"priceCurrency": "USD",
53
"priceValidUntil": "2020-11-05",
54
"seller": {
55
"id": "_:b4",
56
"name": "Executive Objects",
57
"type": "Organization"
58
},
59
"type": "Offer"
60
},
61
"type": "Product"
62
},
63
{
64
"id": "_:b1",
65
"ratingValue": "4.4",
66
"reviewCount": "89",
67
"type": "AggregateRating"
68
},
69
{
70
"id": "_:b2",
71
"name": "ACME",
72
"type": "Thing"
73
},
74
{
75
"availability": "http://schema.org/InStock",
76
"id": "_:b3",
77
"itemCondition": "http://schema.org/UsedCondition",
78
"price": "119.99",
79
"priceCurrency": "USD",
80
"priceValidUntil": "2020-11-05",
81
"seller": {
82
"id": "_:b4",
83
"name": "Executive Objects",
84
"type": "Organization"
85
},
86
"type": "Offer"
87
},
88
{
89
"id": "_:b4",
90
"name": "Executive Objects",
91
"type": "Organization"
92
}
93
]
94
}
95
}
96
}
97
]
98
}
Copied!
Data integrity could be verified by calculating sha256(sha256(metadata)sha256(data)).

Search for an entity or an assertion on the DKG

DKG can be searched by keywords for related assets and assertions. Search result consists of elements listed by score and issuer.

Search for entities:

1
options = { query: 'ExecutiveAnvil', resultType: 'entities' };
2
​
3
dkg.search(options).then((result) => {
4
console.log(JSON.stringify(result));
5
});
Copied!
The result of Search API route is the following:
1
{
2
"@context": {
3
"@vocab": "http://schema.org/",
4
"goog": "http://schema.googleapis.com/",
5
"resultScore": "goog:resultScore",
6
"detailedDescription": "goog:detailedDescription",
7
"EntitySearchResult": "goog:EntitySearchResult",
8
"kg": "http://g.co/kg"
9
},
10
"@type": "ItemList",
11
"itemListElement": [
12
{
13
"@type": "EntitySearchResult",
14
"result": {
15
"@id": "f7fb9c597ec04c1a7a6c1b03f5ef365ac7b47416b23e4c0772195175258266b8",
16
"@type": "PRODUCT",
17
"@context": "https://www.schema.org/",
18
"@graph": [
19
{
20
"type": "Product",
21
"aggregateRating": {
22
"id": "_:b1",
23
"type": "AggregateRating",
24
"ratingValue": "4.4",
25
"reviewCount": "89"
26
},
27
"brand": {
28
"id": "_:b2",
29
"type": "Thing",
30
"name": "ACME"
31
},
32
"description": "Sleeker than ACME's Classic Anvil, the Executive Anvil is perfect for the business traveler looking for something to drop from a height.",
33
"image": "http://www.example.com/anvil_executive.jpg",
34
"mpn": "925872",
35
"name": "Executive Anvil",
36
"offers": {
37
"id": "_:b3",
38
"type": "Offer",
39
"availability": "http://schema.org/InStock",
40
"itemCondition": "http://schema.org/UsedCondition",
41
"price": "119.99",
42
"priceCurrency": "USD",
43
"priceValidUntil": "2020-11-05",
44
"seller": {
45
"id": "_:b4",
46
"type": "Organization",
47
"name": "Executive Objects"
48
}
49
}
50
},
51
{
52
"id": "_:b1",
53
"type": "AggregateRating",
54
"ratingValue": "4.4",
55
"reviewCount": "89"
56
},
57
{
58
"id": "_:b2",
59
"type": "Thing",
60
"name": "ACME"
61
},
62
{
63
"id": "_:b3",
64
"type": "Offer",
65
"availability": "http://schema.org/InStock",
66
"itemCondition": "http://schema.org/UsedCondition",
67
"price": "119.99",
68
"priceCurrency": "USD",
69
"priceValidUntil": "2020-11-05",
70
"seller": {
71
"id": "_:b4",
72
"type": "Organization",
73
"name": "Executive Objects"
74
}
75
},
76
{
77
"id": "_:b4",
78
"type": "Organization",
79
"name": "Executive Objects"
80
}
81
]
82
},
83
"issuers": [
84
"0xbd084ab97c704fe4a6d620cb7c30c0be0366646f"
85
],
86
"assertions": [
87
"6b02bc68a44c255c0738b94a72a41ae2c0959e7e6a53554f90ec75ed6d7921de"
88
],
89
"nodes": [
90
"QmdD6AuWRoVpAjkxEtBgeUDUBaddNT3SD2cZo8sMV5CMn6"
91
],
92
"resultScore": 0
93
}
94
]
95
}
Copied!

Search for assertions

1
options = { query: 'ExecutiveAnvil', resultType: 'assertions' };
2
​
3
dkg.search(options).then((result) => {
4
console.log(JSON.stringify(result));
5
});
Copied!
The result of Search API route is the following:
1
{
2
"@context": {
3
"@vocab": "http://schema.org/",
4
"goog": "http://schema.googleapis.com/",
5
"resultScore": "goog:resultScore",
6
"detailedDescription": "goog:detailedDescription",
7
"EntitySearchResult": "goog:EntitySearchResult",
8
"kg": "http://g.co/kg"
9
},
10
"@type": "ItemList",
11
"itemListElement": [
12
{
13
"@type": "AssertionSearchResult",
14
"result": {
15
"@id": "6b02bc68a44c255c0738b94a72a41ae2c0959e7e6a53554f90ec75ed6d7921de",
16
"metadata": {
17
"issuer": "0xbd084ab97c704fe4a6d620cb7c30c0be0366646f",
18
"type": "Product",
19
"timestamp": "2021-12-27T16:06:57.912Z",
20
"visibility": true,
21
"dataHash": "ed13153fa4090eceedf6c1dd1aa030ec45ab75c2f9510c64a2014f1c6424e7dd"
22
},
23
"signature": "0xbe37c15aa21835b9fe50b5225cfb61cd8ab3f06374705a91f5a5989105d2d2ec151c8bbb5d0f07c8508d37c77a15ac08456342d156ae52ced4520c15cb94eee91c",
24
"rootHash": "45f04483daac38828d634d404e1a12d60d7b4749813edea7fd8b1701a725f37e"
25
},
26
"nodes": [
27
"QmdD6AuWRoVpAjkxEtBgeUDUBaddNT3SD2cZo8sMV5CMn6"
28
],
29
"resultScore": 0
30
}
31
]
32
}
Copied!

SPARQL query

Querying the DKG is done using the SPARQL query API. It is used to look up all datasets containing a specific identifier/Value.
The SPARQL Construct query helps to get the response as a RDF sub-graph. In case users are interested to create their own application, this returned portable sub-graph contains all of the information needed to build a section of application. Then instead of many select queries to the full database, these queries can be run over the much smaller sub-graph returned by the construct query.
1
options = {
2
query: `PREFIX schema: <http://schema.org/>
3
CONSTRUCT { ?s ?p ?o }
4
WHERE {
5
GRAPH ?g {
6
?s ?p ?o .
7
?s schema:hasVisibility ?v
8
}
9
}`
10
};
11
​
12
dkg.query(options).then((result) => {
13
console.log(JSON.stringify(result));
14
});
Copied!
The returned responses contain an array of all connected nodes for returned dataset which contain objects whose identifiers(or value) fit the given query.
1
{
2
"status": "COMPLETED",
3
"data": {
4
"response": [
5
"<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasDataHash> \"019042b4b5cb5701579a4fd8e339bed0fa983b06920ed8cd4d5864ffcb01c801\" .",
6
"<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasIssuer> \"0xbd084ab97c704fe4a6d620cb7c30c0be0366646f\" .",
7
"<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasSignature> \"0x1303593aa18a94c54d85649915809f6f3849bd28ad3780b1ce458086f8547e10665dd3d8f2900724853fc5b6c34599d68657fa0f5bb3c7542f02673fc6e609b41b\" .",
8
"<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasTimestamp> \"2021-12-14T12:43:10.742Z\" .",
9
"<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasType> \"default\" .",
10
]
11
}
12
}
Copied!

Validation

Using DKG client you can validate triples that you got performing SPARQL queries. We have chosen two triplets from above query result and we will check their integrity:
1
options = {
2
nquads: [
3
'<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasDataHash> \"019042b4b5cb5701579a4fd8e339bed0fa983b06920ed8cd4d5864ffcb01c801\" .',
4
'<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasIssuer> \"0xbd084ab97c704fe4a6d620cb7c30c0be0366646f\" .'
5
],
6
};
7
​
8
dkg.validate(options).then((result) => {
9
console.log(JSON.stringify(result));
10
});
Copied!
Expected output:
1
[
2
{
3
"triple": "<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasDataHash> \"019042b4b5cb5701579a4fd8e339bed0fa983b06920ed8cd4d5864ffcb01c801\" .",
4
"valid": true
5
},
6
{
7
"triple": "<did:dkg:43a5f8c55600a36882f9bac7c69c05a3e0edd1293b56b8024faf3a29d8157435> <http://schema.org/hasIssuer> \"0xbd084ab97c704fe4a6d620cb7c30c0be0366646f\" .",
8
"valid": true
9
}
10
]
Copied!
​
Last modified 16d ago