aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--examples/web-demo/index.html13
-rw-r--r--examples/web-demo/package-lock.json98
-rw-r--r--examples/web-demo/src/index.js141
-rw-r--r--src/eris.js2
4 files changed, 181 insertions, 73 deletions
diff --git a/examples/web-demo/index.html b/examples/web-demo/index.html
index 62d9dd3..6381519 100644
--- a/examples/web-demo/index.html
+++ b/examples/web-demo/index.html
@@ -21,9 +21,8 @@
<div id="input">
<h2>Input</h2>
- <p>Enter some text and click Encode to get the URN that uniquely identifies the text.</p>
-
- <textarea id="input-textarea"></textarea>
+ <textarea id="input-textarea"
+ placeholder="Enter some text and click Encode..."></textarea>
<br> <br>
@@ -85,6 +84,14 @@
<div id="blocks">
<h3>Blocks</h3>
+ <p>Blocks are stored in memory and can be removed or randomized (corrupted).</p>
+
+ <details>
+ <summary>IPFS</summary>
+ <p>Optionally IPFS can be used as block storage and transport. Note: This does not work reliably from the browser. For more reliable demos of how to use ERIS with IPFS see the <a href="https://gitlab.com/openengiadina/data-model/">Guile</a> and <a href="https://gitlab.com/openengiadina/js-eris/-/tree/master/examples/ipfs">node.js </a> implementations/demos.</p>
+ <input id="checkbox-enable-ipfs" type="checkbox">enable IPFS</input>
+ </details>
+
<div id="block-container">
</div>
</div>
diff --git a/examples/web-demo/package-lock.json b/examples/web-demo/package-lock.json
index 64c3c06..b7d072a 100644
--- a/examples/web-demo/package-lock.json
+++ b/examples/web-demo/package-lock.json
@@ -4710,16 +4710,16 @@
}
},
"ipld": {
- "version": "0.26.2",
- "resolved": "https://registry.npmjs.org/ipld/-/ipld-0.26.2.tgz",
- "integrity": "sha512-HGBXh3kBXVGpvmuIaHYn18tBGqNmmaGv4PLgKkKuwqnn6YE/zl/EI5qrKDuPmZ1Vu07GJdacCw2+Tf/PzG3eug==",
+ "version": "0.26.3",
+ "resolved": "https://registry.npmjs.org/ipld/-/ipld-0.26.3.tgz",
+ "integrity": "sha512-x6Udh4LVMerZduKk0eRNOhBKJeZwQgZ1YIH9AR7E5RjRJ0cPqEpq43DGbiHhU5XOXjBQiwdJwX5p9pxxiKkG9Q==",
"requires": {
"buffer": "^5.6.0",
"cids": "~0.8.0",
"ipld-block": "~0.9.1",
"ipld-dag-cbor": "~0.15.0",
"ipld-dag-pb": "~0.18.1",
- "ipld-raw": "^4.0.0",
+ "ipld-raw": "^5.0.0",
"merge-options": "^2.0.0",
"multicodec": "^1.0.0",
"typical": "^6.0.0"
@@ -4733,6 +4733,16 @@
"base64-js": "^1.0.2",
"ieee754": "^1.1.4"
}
+ },
+ "ipld-raw": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/ipld-raw/-/ipld-raw-5.0.0.tgz",
+ "integrity": "sha512-z1Fie224lTtQZbFg+wC5WDY692G3SIpO8vT86yCU83vqpIvasVuV3SzDSv7G36kRxP03PPZOkvKAOFrcjb7gpw==",
+ "requires": {
+ "cids": "~0.8.0",
+ "multicodec": "^1.0.1",
+ "multihashing-async": "~0.8.1"
+ }
}
}
},
@@ -4802,9 +4812,9 @@
}
},
"ipld-dag-cbor": {
- "version": "0.15.2",
- "resolved": "https://registry.npmjs.org/ipld-dag-cbor/-/ipld-dag-cbor-0.15.2.tgz",
- "integrity": "sha512-Ioni4s959P/CtkWQOt1TXrj4zqc3MoPxvHrEmybCn5JFdG3dpBNJR1oBVvP6uUrmF5bBtUGKNbX1pSI5SEOaHg==",
+ "version": "0.15.3",
+ "resolved": "https://registry.npmjs.org/ipld-dag-cbor/-/ipld-dag-cbor-0.15.3.tgz",
+ "integrity": "sha512-m23nG7ZyoVFnkK55/bLAErc7EfiMgaEQlqHWDTGzPI+O5r6bPfp+qbL5zTVSIT8tpbHmu174dwerVtLoVgeVyA==",
"requires": {
"borc": "^2.1.2",
"buffer": "^5.5.0",
@@ -5692,6 +5702,9 @@
},
"js-eris": {
"version": "file:../..",
+ "requires": {
+ "libsodium-wrappers-sumo": "^0.7.6"
+ },
"dependencies": {
"libsodium-sumo": {
"version": "0.7.6",
@@ -6234,9 +6247,9 @@
}
},
"libp2p-crypto": {
- "version": "0.17.6",
- "resolved": "https://registry.npmjs.org/libp2p-crypto/-/libp2p-crypto-0.17.6.tgz",
- "integrity": "sha512-ixTSlXXObarf2x+8voGBywr2SyiZh4nw21ZRe1FVz4sxg47crXLqBXhb7gGy2U6Kf0ANbTVaOgLs45WAtM/HpQ==",
+ "version": "0.17.7",
+ "resolved": "https://registry.npmjs.org/libp2p-crypto/-/libp2p-crypto-0.17.7.tgz",
+ "integrity": "sha512-z5Vkser8oGKsF8MAWovmXtFnEG7PqsgxrIgdSDejs2N6X+g3hUKFtxL/sKZpWD3tlLywcH9wqoE9L096ExB1lA==",
"requires": {
"buffer": "^5.5.0",
"err-code": "^2.0.0",
@@ -6245,7 +6258,7 @@
"keypair": "^1.0.1",
"multibase": "^0.7.0",
"multihashing-async": "^0.8.1",
- "node-forge": "~0.9.1",
+ "node-forge": "^0.9.1",
"pem-jwk": "^2.0.0",
"protons": "^1.0.1",
"secp256k1": "^4.0.0",
@@ -6570,65 +6583,16 @@
}
},
"libp2p-keychain": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/libp2p-keychain/-/libp2p-keychain-0.6.0.tgz",
- "integrity": "sha512-r0EmaRvEwOImiYxrhTAjxzFf+JHxk66ooMezHF/LkXIdncc/eGt32k80UvnJ/xgoCzDHl4IlzXu1j8VKxy/80g==",
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/libp2p-keychain/-/libp2p-keychain-0.6.1.tgz",
+ "integrity": "sha512-7K7MZ4KHQVtudAatPnJ2eWI0NvnXxtdEnp3+AXdiDd4/DmwF4wLu+XJ0PR9EQpnsMNu8tIgsNUIA8bmDyUU5iw==",
"requires": {
"err-code": "^2.0.0",
- "interface-datastore": "^0.8.0",
+ "interface-datastore": "^1.0.2",
"libp2p-crypto": "^0.17.1",
"merge-options": "^2.0.0",
"node-forge": "^0.9.1",
"sanitize-filename": "^1.6.1"
- },
- "dependencies": {
- "buffer": {
- "version": "5.6.0",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.6.0.tgz",
- "integrity": "sha512-/gDYp/UtU0eA1ys8bOs9J6a+E/KWIY+DZ+Q2WESNUA0jFRsJOc0SNUO6xJ5SGA1xueg3NL65W6s+NY5l9cunuw==",
- "requires": {
- "base64-js": "^1.0.2",
- "ieee754": "^1.1.4"
- }
- },
- "interface-datastore": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/interface-datastore/-/interface-datastore-0.8.3.tgz",
- "integrity": "sha512-0boeaQbqRUV+7edgdkDDNl8/m0bzFbBEfM3tC0Prro2ZE7N9dtcIDh/cW812P/22Gjhlj1J7KIn0mPzbO4HjPQ==",
- "requires": {
- "buffer": "^5.5.0",
- "class-is": "^1.1.0",
- "err-code": "^2.0.0",
- "ipfs-utils": "^1.2.3",
- "iso-random-stream": "^1.1.1",
- "nanoid": "^3.0.2"
- }
- },
- "ipfs-utils": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/ipfs-utils/-/ipfs-utils-1.2.4.tgz",
- "integrity": "sha512-xUP7SmOAb50OHL8D2KasRHRBOtRdyHHerfCEJBmS9+qpe6wzpbhftdsZJ2UD2v7HXgi7IH9eTps5uPXKUd2aVg==",
- "requires": {
- "abort-controller": "^3.0.0",
- "buffer": "^5.4.2",
- "err-code": "^2.0.0",
- "fs-extra": "^9.0.0",
- "is-electron": "^2.2.0",
- "iso-url": "^0.4.7",
- "it-glob": "0.0.7",
- "merge-options": "^2.0.0",
- "nanoid": "^2.1.11",
- "node-fetch": "^2.6.0",
- "stream-to-it": "^0.2.0"
- },
- "dependencies": {
- "nanoid": {
- "version": "2.1.11",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-2.1.11.tgz",
- "integrity": "sha512-s/snB+WGm6uwi0WjsZdaVcuf3KJXlfGl2LcxgwkEwJF0D/BWzVWAZW/XY4bFaiR7s0Jk3FPvlnepg1H1b1UwlA=="
- }
- }
- }
}
},
"libp2p-mdns": {
@@ -9457,9 +9421,9 @@
}
},
"timeout-abort-controller": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.0.tgz",
- "integrity": "sha512-xLV+Ms6mDc8UKpBAGGwRkZ137VqS63nGYRnzvI2f1bbv5TWqr4S7ST81870ekn+zlODruVsUexU6GCnErkM7Pw==",
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/timeout-abort-controller/-/timeout-abort-controller-1.1.1.tgz",
+ "integrity": "sha512-BsF9i3NAJag6T0ZEjki9j654zoafI2X6ayuNd6Tp8+Ul6Tr5s4jo973qFeiWrRSweqvskC+AHDKUmIW4b7pdhQ==",
"requires": {
"abort-controller": "^3.0.0",
"retimer": "^2.0.0"
diff --git a/examples/web-demo/src/index.js b/examples/web-demo/src/index.js
index ea4db5f..6faadd1 100644
--- a/examples/web-demo/src/index.js
+++ b/examples/web-demo/src/index.js
@@ -2,6 +2,11 @@ const ERIS = require('js-eris')
const rdfParser = require('rdf-parse').default
const Streamify = require('streamify-string')
const FragmentGraph = require('./rdf/fragment-graph.js')
+const IPFS = require('ipfs')
+const CID = require('cids')
+const multihash = require('multihashes')
+const base32 = require('../../../src/base32.js')
+const crypto = require('../../../src/crypto.js')
const signify = `
@prefix rdf: <http://www.w3.org/1999/02/22-rdf-syntax-ns#> .
@@ -58,6 +63,92 @@ const alyssa = `
"liked": "https://social.example/alyssa/liked/"}
`
+function MapAndIPFSContentAddressableStorage () {
+ this._map = new Map()
+
+ this._ipfsPut = async function (block) {
+ // put block in IPFS
+ const ipfsBlock = await this._ipfs.block.put(Buffer.from(block), {
+ version: 1, // CIDv1
+ format: 'raw', // don't do any tricks IPFS
+ mhtype: 'blake2b-256', // use BLAKE2b (256bit)
+ timeout: 2000
+ })
+
+ console.log('Put block on IPFS: ' + ipfsBlock.cid.toString())
+
+ // decode the multihash
+ const mhash = await multihash.decode(ipfsBlock.cid.multihash)
+
+ // return the digest
+ return Uint8Array.from(mhash.digest)
+ }
+
+ this._ipfsGet = async function (ref) {
+ // encode ref as mhash
+ const mhash = multihash.encode(Buffer.from(ref), 'blake2b-256')
+ // and as cid
+ const cid = new CID(1, 'raw', mhash)
+
+ // get block from IPFS (timeout after 5s)
+ const block = await this._ipfs.block.get(cid, { timeout: 2000 })
+
+ return Uint8Array.from(block.data)
+ }
+
+ this.activateIPFS = async function () {
+ const ipfs = await IPFS.create({
+ config: {
+ Addresses: {
+ Swarm: [
+ // This is a public webrtc-star server
+ // '/dns4/star-signal.cloud.ipfs.team/wss/p2p-webrtc-star'
+ ]
+ }
+ },
+ repo: 'ipfs-eris',
+ relay: {
+ enabled: true,
+ hop: {
+ enabled: true
+ }
+ }
+ })
+ this._ipfs = ipfs
+ const version = await ipfs.version()
+ console.log('JS-IPFS Version:', version.version)
+ return version
+ }
+
+ this.deactivateIPFS = async function () {
+ await this._ipfs.stop()
+ delete this._ipfs
+ }
+
+ ERIS.ContentAddressableStorage.call(
+ this,
+ async function (block) {
+ const ref = await crypto.hash(block)
+ const key = base32.encode(ref)
+ this._map.set(key, block)
+
+ if (this._ipfs) {
+ await this._ipfsPut(block)
+ }
+
+ return ref
+ }, async function (ref) {
+ const key = base32.encode(ref)
+
+ if (this._map.has(key)) {
+ return this._map.get(key)
+ } else if (this._ipfs) {
+ return this._ipfsGet(key)
+ }
+ }
+ )
+}
+
function rdfParse (input, contentType) {
return new Promise((resolve, reject) => {
const textStream = Streamify(input)
@@ -99,9 +190,10 @@ async function main () {
const encodedErisReadCap = document.getElementById('encoded-eris-read-cap')
const encodedErisVerificationCap = document.getElementById('encoded-eris-verification-cap')
const blockContainer = document.getElementById('block-container')
+ const checkBoxEnableIPFS = document.getElementById('checkbox-enable-ipfs')
- // a ContentAddressableStorage based on a JavaScipt Map
- const cas = new ERIS.MapContentAddressableStorage()
+ // a ContentAddressableStorage based on a JavaScript Map and optionally on IPFS
+ const cas = new MapAndIPFSContentAddressableStorage()
// a TextEncoder for encoding strings as UTF-8 encoded Uint8Array
const utf8Encoder = new TextEncoder()
@@ -183,8 +275,21 @@ async function main () {
controlsSuccess.innerText = msg
}
+ function disableControls () {
+ controlsEncode.disabled = true
+ controlsDecode.disabled = true
+ controlsVerify.disabled = true
+ }
+
+ function enableControls () {
+ controlsEncode.disabled = false
+ controlsDecode.disabled = false
+ controlsVerify.disabled = false
+ }
+
controlsEncode.onclick = async function (e) {
setSuccess('')
+ disableControls()
try {
const urn = await encode()
encodedErisReadCap.value = urn
@@ -192,31 +297,63 @@ async function main () {
encodedErisVerificationCap.value = verifyUrn
renderBlocks(cas)
setSuccess('Encoded!')
+ enableControls()
} catch (err) {
console.error(err)
setError(err)
+ enableControls()
}
}
controlsDecode.onclick = async function (e) {
setSuccess('')
+ disableControls()
try {
const decoded = await decode()
inputTextarea.value = utf8Decoder.decode(decoded)
setSuccess('Decoded!')
+ enableControls()
} catch (err) {
setError(err)
+ enableControls()
}
}
controlsVerify.onclick = async function (e) {
setSuccess('')
+ disableControls()
try {
const verificationCap = encodedErisVerificationCap.value
await ERIS.verify(verificationCap, cas)
setSuccess('Verification passed!')
+ enableControls()
} catch (err) {
setError(err)
+ enableControls()
+ }
+ }
+
+ checkBoxEnableIPFS.onchange = async function (e) {
+ setSuccess('')
+ disableControls()
+ if (checkBoxEnableIPFS.checked) {
+ try {
+ await cas.activateIPFS()
+ setSuccess('IPFS enabled!')
+ enableControls()
+ } catch (err) {
+ setError(err)
+ enableControls()
+ }
+ } else {
+ try {
+ await cas.deactivateIPFS()
+ setSuccess('IPFS disabled')
+ enableControls()
+ } catch (err) {
+ setError(err)
+ enableControls()
+ }
}
}
diff --git a/src/eris.js b/src/eris.js
index e4ddaea..1ea59fc 100644
--- a/src/eris.js
+++ b/src/eris.js
@@ -173,7 +173,7 @@ async function buildMerkleTree (input, verificationKey, cas) {
return finalize(state, 0)
}
-function makeCapability(type, level, rootReference, readKey) {
+function makeCapability (type, level, rootReference, readKey) {
const cap = new Uint8Array(67)
// Set version to 0