{"_id":"3box","_rev":"151-eafa3ddc30a9f94bab9d19da4cfc8001","name":"3box","dist-tags":{"node":"1.7.0-node-1","next":"1.22.2-beta.0","latest":"1.19.1"},"versions":{"0.0.1":{"name":"3box","version":"0.0.1","author":"","license":"Apache-2.0","_id":"3box@0.0.1","maintainers":[{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"00a4e194d99f78910e9b01a4c2c740f5b72d05fb","tarball":"https://registry.npmjs.org/3box/-/3box-0.0.1.tgz","fileCount":7,"integrity":"sha512-Rx3b8d8Og7eiKI0CEPsCQMkio4ZX0qq52f/nKgWx+vGoeonpYvfq7kuj3ASM41Z6crdFmDHon3Nzck/nyz4vLA==","signatures":[{"sig":"MEQCIH+UHR1eoRxUQfLxf4XJUjXnwl1YD3Q+fTNb1TPYMmClAiATmT711xFudcL7AMEratPEZzwHE6aCkzY5moD8yFNXSA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":29304,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbesx6CRA9TVsSAnZWagAAVEAP/0FT0lR/4tCap4+xBF5R\nMR6XOXtuUlOyxqo9Bkcx8D/wzBgRwJeg8nik1ob0XHG9FYSKbeMspy3FM5yW\nxaaREzZmbo3QubLWhqdGCYBB9kExk2sDKlgHMfWmoYf6eJ3/2X1oYSmflvjO\nsVzbuo9PTCLpsKMeTMhSSALosrnFCovV40mlazafFwBGijrOkbEVOzOpia9j\nNH1Medsv1znDaiN1vHsWXELhYC66d4yI63J1DGmcB9juW3qQ/tYBahhE05oF\nsZ76PkOe2C4tHqlOlKT5nssIW1O4/whClSxuvC7ECZT/UTeVyvfWMkL30LIT\n6TaOdpd3SqtTq0bz0eokgfgMh7PTY24+OV5c8QHHFmS+TIsvqiD9AOa/2vu+\nbEMBYoj6QnFBsvte+iSFUMTGKXXm4q91A0w8WJu3HPKMoxLR+NpyIokk5o77\nwHrcj1DYMUg15OE1Q95taxMXWyHiaDloJZIbnOGtuPfZ21kiBX6Ray4hgIVz\nGFp0JBPfr0Fdx1e5NAqNs9GsZJHN81v7jUVfyf1nxZ8d+HJiSGgQrlze8Rn9\nfYctRDNTpEKZxkoL2PYgQUR8BZO5UcJJdwL4U6Zb3Rk518CWKy/cWXdCf2Oc\n6bLN3I/tyuPOXkyvhT8Os1upreXUx+aCNyoTh8yLF2dShbg0iz9lWuybCT5N\nYvdc\r\n=KVG0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/3box.js","gitHead":"b2db4f87639c16b8f19544453fbae221b5b58c94","scripts":{"test":"jest --coverage","build":"babel src --out-dir lib","build:dist":"browserify -s 3Box ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/3box.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","muport-core":"^0.3.1","babel-runtime":"^6.26.0","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^4.1.2","jest":"^22.4.2","babel-cli":"^6.26.0","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_0.0.1_1534774393930_0.6674517938381952","host":"s3://npm-registry-packages"}},"0.0.2":{"name":"3box","version":"0.0.2","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@0.0.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"88ad0248aae106c00d3b2739654b96d7ed87bdd3","tarball":"https://registry.npmjs.org/3box/-/3box-0.0.2.tgz","fileCount":19,"integrity":"sha512-QX68nFNQyVYNMC4bP+PyXf5g2zJgZFMwUsR6DR2korTQMJa/H+utm/dGS3W8BP+cwVDKeQTvn/vQUGASKSgZpQ==","signatures":[{"sig":"MEUCIBVzQRgB1RSd4tx+6GsFAb50gvXKH/HHW52WegTVg7htAiEA+TSmhyy2UFM3JWzsNS3sua54ycKv51OaJxytTRQ6H6Q=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6142908,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbj8SvCRA9TVsSAnZWagAAFNsP/1HzaxREpgSXOarYDXHm\nlZjKj1fXrjmfO/QcvRzK50d3KbXQl8VFMyVqAhMeKtiyh2X7PF5uviSEsN4s\nr5zcsRQBMh95Nz85wf53aasdHIBj2WmTgHZANiszP45oWFEXjCjMIhJhSFIu\nELiJ9rgLxDpAu9etIfEV3LBb6yDKrJkOS+zIAw2xi356jA/sOFoXF8AJPXTp\nNaSZ00tdKDYz8Izj1ARzCFRct8pYSyXYiJaKL0z8rhdrVeVgufoh8sQRf19a\nQomJ6L637wp8xkVwTlBSUProvs4wogr7scaR6pcciIzHlY9pWT/JT0Q8mpxX\nBrlEAuFjV1TVhin2XjEkcpcF+ypDwxlp9xy5a21szdURYqJJva92Apx8YfH1\nrBwa8G+OIPiLKo6Z1tZVUP/1AzJodnpy/aoBZhjvixkmIiwEA4rd1pDobGq6\nwudgulGKfHkpE4RwVCmufaqdL9uQE1LB/5zFKP7exZr8NkmBUl3+UT1XA/pT\niASFi8PZVG32CrCk/o6FMuO1AdfiWY9YjAbqEoMNQVaPRbv8tr7qDY5VarPl\nZ44R6g/UFdU9aJXJ5XTQzE9mPt17TwcmkSG36yQjYM7YFuLcdM7xHuxVLknV\nvmfgtdIgAZQsLQnTVlyMDvFd5eQlZLne3mJKbwC6j8fFMCVCNH80EUcsf1wI\nN05C\r\n=CgJo\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/3box.js","gitHead":"b451bee571ab57cb1650b204b50cd6cba03a99d5","scripts":{"test":"jest --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/3box.js >> README.md"},"_npmUser":{"name":"ajunge","email":"ajunge@yaykuy.cl"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"9.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.0","babel-runtime":"^6.26.0","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^4.1.2","ipfs":"^0.31.7","jest":"^22.4.2","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_0.0.2_1536148654410_0.4206903086775","host":"s3://npm-registry-packages"}},"0.0.3":{"name":"3box","version":"0.0.3","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@0.0.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"ea86181edd937a3b6fba53cf6c02e6b38ff44d73","tarball":"https://registry.npmjs.org/3box/-/3box-0.0.3.tgz","fileCount":20,"integrity":"sha512-19enOLri4UtpllvWqv4/VzaecaEHMC15rumCGw3LZhXmINMU4xbeZAjaVWhuQrDS9QDyorPles36CPn4exQRVA==","signatures":[{"sig":"MEYCIQC0LEvNYSm5gxsDYCU6H6B/0TaD5TxJwGMQKbFeVm2eeAIhAIgHxFVFTfCmYmqArvJ09niXGVXhtzab7IGYiCytM9uo","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6628465,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkgBLCRA9TVsSAnZWagAAlJoP/3w/gdb5irFxd6+lsB83\n6SaoV0mLMqBrvr/eGloUBZr/SuihzqsfR9MF1V+JbHlEs8VDRUW//aNMuAC9\nNmecQR1RbdGjtQhu1UCQSQFarNf8YRGZ2nQ7cIFMH/luY6li4IvkQCd2FRnW\nRZWbpf6kwCtYUrgjLdunmC2ywp06wepwPI6+5H0y82u/pjcUKIybrC0I5LIt\nJYuYnwyBknc5Xbob4KOelw+Go4dZuKdv3MAz/ZC4hig+c308TZ9RRakTj4tD\n1VOJvcfNIL3znGl6O8263QKUuShWaP1jmubE+6dtB9ZcPhvs1T3tn7jPeyon\nOGV3uTvBysdVkoObAhoVo+QkQsly8Dd61F0moLVEfSsXZddaWD1BihsoBzAD\neeNJUc72ZLxTFYIcvaL26mWhXWt53i9AeTUnZW3c1jEEq6HemSNOlde+A2Rk\nVkHuAm+4lxWMZW6lqrU9r1m3ybWBk0X9QJSosOEffEmlyvp+xxs66SLwryll\nSPn4Hjy63Y1/sfiPyC2XzijMuB/ZBdGdCHXsEeAKAjvalR7QP3HLB3c9e+Kf\nWVxNarBQkfBHejNziFpxh1iJME/NXRsCvtv2IHKm8QTP2JInvtQ/QySL6FAx\nJFoitEedAH4bPQmZEXxzMVe8Yi2qdF+2pLrMuHlIZr2Q3C81RmebVPbqj83q\n1/xc\r\n=btm0\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n[Data Schema](./DATA-MODEL.md)\n\n[API Documentation](./API-SPECIFICATION.md)\n\n## Usage\nSimply install using npm\n```\n$ npm install 3box\n```\nand then import into your project\n```js\nconst ThreeBox = require('3box')\n\nThreeBox.openBox(web3.eth.accounts[0]).then(threeBox => {\n  // Code goes here...\n})\n```\n\n## Classes\n\n<dl>\n<dt><a href=\"#ThreeBox\">ThreeBox</a></dt>\n<dd></dd>\n<dt><a href=\"#ProfileStore\">ProfileStore</a></dt>\n<dd></dd>\n<dt><a href=\"#PrivateStore\">PrivateStore</a></dt>\n<dd></dd>\n</dl>\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox(muportDID)](#new_ThreeBox_new)\n    * _instance_\n        * [.profileStore](#ThreeBox+profileStore)\n        * [.privateStore](#ThreeBox+privateStore)\n    * _static_\n        * [.getProfile(address)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.getActivity(address)](#ThreeBox.getActivity) ⇒ <code>Object</code>\n        * [.openBox(address)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox(muportDID)\nInstantiates a threeBox\n\n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n\n<a name=\"ThreeBox+profileStore\"></a>\n\n### threeBox.profileStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| profileStore | [<code>ProfileStore</code>](#ProfileStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+privateStore\"></a>\n\n### threeBox.privateStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| privateStore | [<code>PrivateStore</code>](#PrivateStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address) ⇒ <code>Object</code>\nGet the public profile of the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"ThreeBox.getActivity\"></a>\n\n### ThreeBox.getActivity(address) ⇒ <code>Object</code>\nGet the public activity of the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"ProfileStore\"></a>\n\n## ProfileStore\n**Kind**: global class  \n\n* [ProfileStore](#ProfileStore)\n    * [new ProfileStore(muportDID)](#new_ProfileStore_new)\n    * [.get(key)](#ProfileStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#ProfileStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#ProfileStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_ProfileStore_new\"></a>\n\n### new ProfileStore(muportDID)\nInstantiates a ProfileStore\n\n**Returns**: [<code>ProfileStore</code>](#ProfileStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n\n<a name=\"ProfileStore+get\"></a>\n\n### profileStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+set\"></a>\n\n### profileStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"ProfileStore+remove\"></a>\n\n### profileStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore\"></a>\n\n## PrivateStore\n**Kind**: global class  \n\n* [PrivateStore](#PrivateStore)\n    * [new PrivateStore(muportDID)](#new_PrivateStore_new)\n    * [.get(key)](#PrivateStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#PrivateStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#PrivateStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_PrivateStore_new\"></a>\n\n### new PrivateStore(muportDID)\nInstantiates a PrivateStore\n\n**Returns**: [<code>PrivateStore</code>](#PrivateStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n\n<a name=\"PrivateStore+get\"></a>\n\n### privateStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+set\"></a>\n\n### privateStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"PrivateStore+remove\"></a>\n\n### privateStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","gitHead":"2c8aab2cbb714aee58a5bf0831e0a8f803839720","scripts":{"test":"jest --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/3box.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.0","babel-runtime":"^6.26.0","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"chai":"^4.1.2","ipfs":"^0.31.7","jest":"^22.4.2","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_0.0.3_1536294986286_0.34397157868617123","host":"s3://npm-registry-packages"}},"0.0.4":{"name":"3box","version":"0.0.4","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@0.0.4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"cd78d83dfb3a82c6c3c1e89a27fd096880a8a13c","tarball":"https://registry.npmjs.org/3box/-/3box-0.0.4.tgz","fileCount":20,"integrity":"sha512-pUUTMmgYrLHspgpFicYjDbC+QsKIB2VSAL9kZPkg0ycq4bRn8Netsjlh55Rodbvz33prXIRwmIuuVSs+lNaZdA==","signatures":[{"sig":"MEQCIB0V4fabPJOoRYoKkv/OTbnaxYlsnV0KHAP+4+Fy09MjAiBLGLvA10oqjujG/RglttX7IExeyKrietG/+0ynCZ5fsw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6628313,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbkg49CRA9TVsSAnZWagAAPsoP/iBomP9h8fRrU6UKIIvg\nX95M0A0CTyu4c99LsywuTI0bZiyMYLEPF0+cxEA+nN7K3zpoeWUIOo3aVZwZ\nd1t1c2IQbdRPdmOEkjLl3GRjps0T/jCEZv44XO4s57BAhk/kWAVL6lUXYe6h\nu20lkdqEuHpjXFs4OJVPl1ZxCQ7KXYRFLDlxCUExIHttZf0NiDvORIYojYnD\nCE22MCDvgW3BBUYimXmKWv59UZxtgSIdD0OwV28kHIw3A54rHNGE9/bXoCgE\nFP01h+sQO84fla5r4kCzByFCuQqXamZfM1gfi/QBmgkpLPvNJVbl/7obipxo\nyS6G94RfQ1OfgvpaMXoxhquLxG/n4J6wfOPHjcBkExFJaObBqHV+cNqpELAz\n7qSI46p25WWUe2hkDuSJRETsrdF6fim7+PRGjmm1bcyFC8YuC0ldlHbWi+Ml\nXc8Vs/y2013nLzuNrp52wObpKzCTGMWJsKQMnW8FGXq34OCW4kCEWlLjRxVc\nz0DzpKkWaAAqplNgQvc24N8q9EHD5yjbdfFuiADArDzXJJv88MqD1dnImsj2\nrsxCfwe8O9IAHHwyzSlBpso86D4L0rnc1hRbzLRf+rtjN6wn6TJbARofyB9w\ne7H/nWaN1qzU6QBpKiro7GjIGM5hI5I7rug5Tx8HVWB/LTkyxq/BHXQtyHPP\n76rs\r\n=VrMc\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/3box.js","gitHead":"0f1e5e65fd0578c3770eb1a96371a448e936e689","scripts":{"test":"jest --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/3box.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.0","babel-runtime":"^6.26.0","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"devDependencies":{"chai":"^4.1.2","ipfs":"^0.31.7","jest":"^22.4.2","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_0.0.4_1536298556337_0.260526397761077","host":"s3://npm-registry-packages"}},"0.0.5-beta-1":{"name":"3box","version":"0.0.5-beta-1","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@0.0.5-beta-1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"5987eeabc1a2288e8bc1dfa8bfcdbb04f771a3eb","tarball":"https://registry.npmjs.org/3box/-/3box-0.0.5-beta-1.tgz","fileCount":24,"integrity":"sha512-8jk/cxaSYJahOvKQAr+I2NjQVe7f6OpFtgunv7/SWpkioi8sHi58wkhdZ88DzA0W1o3/T5tgCfaUZ6KoZxD1oQ==","signatures":[{"sig":"MEQCIFiudpw1fewpm0XEuippt/i8Pp4DoTI7cXjJRT26e78iAiAknsE78eLIA3su0aWR2W4aS8E/vcbDD1uKZS8WVnKjow==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6642724,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbl8CjCRA9TVsSAnZWagAAHIcQAKNlsNgA2+tLsG8eNiyG\nMWs3d3HLUt8O6P5sVGC8XKuHAv7HtPofHYXHz276jqUEsaQryBzQVdm1VLxL\nVBSnIO5Ien3rvY4CVOsbPX4LmkoqXu7gETJLCFqQnZ21d4EeADXZSzY4q/12\nNQSpTOa9QEh134Y/pv8XITMx7T3819Uq3wR8HnS5a8O3srI6MIdaHzr+un6/\nUGdAybsz1p8I8Oiu6NFEAsv0y4lN/LSumMYHVNsXD9VQCbfSzU5ji5rI7mw1\nMOBdCYew/p0EGsrCx3GNvEmZRkvBaov4ewDqQwZ2ovpQq2XIyVHFrv+bcHJZ\nj5LZH3akDYZBncWCNhrBye0wh9d1NM2ewLeUJJrG9p8kA1h0Z3sPY3luIX0/\n6Jdj5s9NAHwtWwVM3eRCkGurCF5J1V+GzM4pRy9hwGw3qP+upnSjPBU5knx+\n3Q5moCPNFrl4fSJk51i3BpcmTO9LrUd45fYuv5hzk/NOxjYaxaHTitNbCRpm\nzJDNjkXCZgBkiUzy78mnAv1blHf5CRRvznYLYpxgwyjZq029+BbDJBt5ieca\nc5F3czc96WTgPOuGei2t1Vyp1WZgB/oNWZmW5PJvIb5YofTYGugDKcHHAv71\n2uquth5hP1GJ+VamejhZlklTzbdMt1PkWdlSOEc5ylyvO5HgcgPc6GA2LyJN\nfm23\r\n=FeQN\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n[Data Schema](./DATA-MODEL.md)\n\n[API Documentation](./API-SPECIFICATION.md)\n\n## Usage\nSimply install using npm\n```\n$ npm install 3box\n```\nand then import into your project\n```js\nconst ThreeBox = require('3box')\n\nThreeBox.openBox(web3.eth.accounts[0]).then(threeBox => {\n  // Code goes here...\n})\n```\n\n## Classes\n\n<dl>\n<dt><a href=\"#ThreeBox\">ThreeBox</a></dt>\n<dd></dd>\n<dt><a href=\"#PrivateStore\">PrivateStore</a></dt>\n<dd></dd>\n<dt><a href=\"#ProfileStore\">ProfileStore</a></dt>\n<dd></dd>\n</dl>\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox(muportDID, web3provider, opts)](#new_ThreeBox_new)\n    * _instance_\n        * [.profileStore](#ThreeBox+profileStore)\n        * [.privateStore](#ThreeBox+privateStore)\n    * _static_\n        * [.getProfile(address)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox(muportDID, web3provider, opts)\nInstantiates a threeBox\n\n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox+profileStore\"></a>\n\n### threeBox.profileStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| profileStore | [<code>ProfileStore</code>](#ProfileStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+privateStore\"></a>\n\n### threeBox.privateStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| privateStore | [<code>PrivateStore</code>](#PrivateStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address) ⇒ <code>Object</code>\nGet the public profile of the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"PrivateStore\"></a>\n\n## PrivateStore\n**Kind**: global class  \n\n* [PrivateStore](#PrivateStore)\n    * [new PrivateStore(muportDID, ipfs, updateRoot)](#new_PrivateStore_new)\n    * [.get(key)](#PrivateStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#PrivateStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#PrivateStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#PrivateStore+_sync)\n\n<a name=\"new_PrivateStore_new\"></a>\n\n### new PrivateStore(muportDID, ipfs, updateRoot)\nInstantiates a PrivateStore\n\n**Returns**: [<code>PrivateStore</code>](#PrivateStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n\n<a name=\"PrivateStore+get\"></a>\n\n### privateStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+set\"></a>\n\n### privateStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"PrivateStore+remove\"></a>\n\n### privateStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+_sync\"></a>\n\n### privateStore._sync(hash)\nSync the private store with the given ipfs hash\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the private store OrbitDB |\n\n<a name=\"ProfileStore\"></a>\n\n## ProfileStore\n**Kind**: global class  \n\n* [ProfileStore](#ProfileStore)\n    * [new ProfileStore(ipfs, updateRoot, linkProfile)](#new_ProfileStore_new)\n    * [.get(key)](#ProfileStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#ProfileStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#ProfileStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#ProfileStore+_sync)\n\n<a name=\"new_ProfileStore_new\"></a>\n\n### new ProfileStore(ipfs, updateRoot, linkProfile)\nInstantiates a ProfileStore\n\n**Returns**: [<code>ProfileStore</code>](#ProfileStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n| linkProfile | <code>function</code> | A callback function that is called if the profile is not made public yet |\n\n<a name=\"ProfileStore+get\"></a>\n\n### profileStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+set\"></a>\n\n### profileStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"ProfileStore+remove\"></a>\n\n### profileStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+_sync\"></a>\n\n### profileStore._sync(hash)\nSync the profile store with the given ipfs hash\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the profile object |\n\n","gitHead":"88f3a396086f2afde40d10cb4637cdb69df0d3a3","scripts":{"test":"jest --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"chai":"^4.1.2","ipfs":"^0.31.7","jest":"^22.4.2","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-runtime":"^6.26.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_0.0.5-beta-1_1536671906544_0.8725070925203522","host":"s3://npm-registry-packages"}},"0.0.5-beta-2":{"name":"3box","version":"0.0.5-beta-2","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@0.0.5-beta-2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"d509dc0d8d075ef2c0e37ea007a3775d768cfbff","tarball":"https://registry.npmjs.org/3box/-/3box-0.0.5-beta-2.tgz","fileCount":24,"integrity":"sha512-IeoTe9cbmLpp9+FlKpB8ceJCg0Uv0Sjg5gRpliV6aDFPwtPP6Gyfj+kAEzfQl5bn9uSd0PDURTB45FBuhxx8XA==","signatures":[{"sig":"MEQCIEl9VtpzJyxKpPtKMHW8MvRC0rYMfw9MOV9wCRI9rNwDAiBmtW0cw0M6zlTQQ4KSsZycxbHi5YzGSN8iMku399fVPw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6642724,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbl8DWCRA9TVsSAnZWagAAXxkP/3mUVCLkno0JCai1Z9CA\nE+G91m+HfpQHzkg+5rIPap+SiARjQTYv0/6UoJeZOuzL43MVP4IuHYSLH2FP\nEIJxuqQDPrVEj5YXVM2BKeCbgFFJm/XATzogtjqpSKtgXtrWQhrSCAWlN8UY\n5tuIzOkdzTz70zDXnFloPwAxhJ63vHQBKG1XhNfA5RODinQo2N9WjBuwu8B9\nkrDBq1QCWhVkSxEWhzUDorzQtWv4OvijJpopJyjY8AOtEzTuxU0pl9foMmJq\nRXLFD8Txzn4sGWW4kAnFwSdkZoWyBkw46LOaN+zX/hqU2p0RyWPYf/fEKC//\nJu6r88s0B/9gaihjiUedN3LqlqsbvIarVB+D25wlcmKf9SX72mg8zUKfHHtm\nGmlf/O2D87McIk2B6gqQJzHKXFzrahty5t7E+MbZqRPsuyNiplj7x7Iiv1gU\nt2toajpBy9DB/17Ngm2mR0tKPoQXM4JIGSzGm5Fh4mJUTJNjIWYRB4oX9H9F\nyVZLfJ/EHXH1o123c2FWeLW1rulQPcjpDdEJ4e4mLI7ogIYp0kA2fHAK5PcN\nSAubirQ/Osb9FGGtajX/3Ad7HNzf8Nvplr7IouTSsB7D06jxGgp1xnJA/cv7\n0E+8InL1bjxnKLkiqf6c/faEpqMP/i9NklaIM5Leuv8S+Bx+PI0+9G7+p2BB\ntG8A\r\n=Q0E8\r\n-----END PGP SIGNATURE-----\r\n"},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n[Data Schema](./DATA-MODEL.md)\n\n[API Documentation](./API-SPECIFICATION.md)\n\n## Usage\nSimply install using npm\n```\n$ npm install 3box\n```\nand then import into your project\n```js\nconst ThreeBox = require('3box')\n\nThreeBox.openBox(web3.eth.accounts[0]).then(threeBox => {\n  // Code goes here...\n})\n```\n\n## Classes\n\n<dl>\n<dt><a href=\"#ThreeBox\">ThreeBox</a></dt>\n<dd></dd>\n<dt><a href=\"#PrivateStore\">PrivateStore</a></dt>\n<dd></dd>\n<dt><a href=\"#ProfileStore\">ProfileStore</a></dt>\n<dd></dd>\n</dl>\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox(muportDID, web3provider, opts)](#new_ThreeBox_new)\n    * _instance_\n        * [.profileStore](#ThreeBox+profileStore)\n        * [.privateStore](#ThreeBox+privateStore)\n    * _static_\n        * [.getProfile(address)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox(muportDID, web3provider, opts)\nInstantiates a threeBox\n\n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox+profileStore\"></a>\n\n### threeBox.profileStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| profileStore | [<code>ProfileStore</code>](#ProfileStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+privateStore\"></a>\n\n### threeBox.privateStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| privateStore | [<code>PrivateStore</code>](#PrivateStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address) ⇒ <code>Object</code>\nGet the public profile of the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"PrivateStore\"></a>\n\n## PrivateStore\n**Kind**: global class  \n\n* [PrivateStore](#PrivateStore)\n    * [new PrivateStore(muportDID, ipfs, updateRoot)](#new_PrivateStore_new)\n    * [.get(key)](#PrivateStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#PrivateStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#PrivateStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#PrivateStore+_sync)\n\n<a name=\"new_PrivateStore_new\"></a>\n\n### new PrivateStore(muportDID, ipfs, updateRoot)\nInstantiates a PrivateStore\n\n**Returns**: [<code>PrivateStore</code>](#PrivateStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n\n<a name=\"PrivateStore+get\"></a>\n\n### privateStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+set\"></a>\n\n### privateStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"PrivateStore+remove\"></a>\n\n### privateStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+_sync\"></a>\n\n### privateStore._sync(hash)\nSync the private store with the given ipfs hash\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the private store OrbitDB |\n\n<a name=\"ProfileStore\"></a>\n\n## ProfileStore\n**Kind**: global class  \n\n* [ProfileStore](#ProfileStore)\n    * [new ProfileStore(ipfs, updateRoot, linkProfile)](#new_ProfileStore_new)\n    * [.get(key)](#ProfileStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#ProfileStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#ProfileStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#ProfileStore+_sync)\n\n<a name=\"new_ProfileStore_new\"></a>\n\n### new ProfileStore(ipfs, updateRoot, linkProfile)\nInstantiates a ProfileStore\n\n**Returns**: [<code>ProfileStore</code>](#ProfileStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n| linkProfile | <code>function</code> | A callback function that is called if the profile is not made public yet |\n\n<a name=\"ProfileStore+get\"></a>\n\n### profileStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+set\"></a>\n\n### profileStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"ProfileStore+remove\"></a>\n\n### profileStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+_sync\"></a>\n\n### profileStore._sync(hash)\nSync the profile store with the given ipfs hash\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the profile object |\n\n","gitHead":"88f3a396086f2afde40d10cb4637cdb69df0d3a3","scripts":{"test":"jest --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"chai":"^4.1.2","ipfs":"^0.31.7","jest":"^22.4.2","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-runtime":"^6.26.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_0.0.5-beta-2_1536671957595_0.04610681666368688","host":"s3://npm-registry-packages"}},"1.0.0-beta-1":{"name":"3box","version":"1.0.0-beta-1","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"09c1609f124a8ef4f1357ccd95e20985d61df695","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-1.tgz","fileCount":18,"integrity":"sha512-1vEPc3c33OfK3FfMNSd1Wo75TqwL485GB7RRAOoPM20j3zvLepLLvroQkH2y82kiv2/Xlc3pQ8yFUplAANUNgA==","signatures":[{"sig":"MEUCIDpexu+XatndOS4MR/ixU9nPIqctro53TGUzZiWOQ7wmAiEA/DKd2pgrIBEHq6CB7meuNwjbpiB2flOxdlDRZRfT0OU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6634416,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmX4tCRA9TVsSAnZWagAAeQ0P/1tggeUssgPYAljCOOC0\n+dTOPqyYrnDgnfKDHgWIIwNK7mdRmGJA/y6cB4uQ4ZuUdsWNL8zN/+cg2Z8v\n2SC9izPNeh/VrATDYpiqGyq6y9+IjW3ykMjsCTLi+5KmUwwU83/7ZxV89U/k\njnbWbr9hUJLS6xCEivk1iaIKo6rZmXpP/5IupjBEzRn3c9queLbQBNd5E05f\nVOz4Rkb96leCFTehJw1qT2arxy6UwIF75qsGcjxtfyGl4VAEbMmuO8MY/bil\nQNIeTY/lW3eKNmOTjmQMGHfBUfU4TGYI397vnWJwVSYg4vMZpATYFk6vd3kt\nUvywhq8N4jdyDXKirDKYPMNlBJNO65M62FmQm0Whwj32CE+Iw6ypkmvY7Onu\npHoToSRZLTmGV7zKiPkoYHKVooUN91eTUz5xzBmyDFGOhhFYukAvtqAMbZ/g\nDL8D9jf7vNtx85wT93lKs6s1m9q4Q8Ekyg64zP1e/FUFt5+vISHV4NKCVs3m\n5KZDFls5nNJKlWTHm6YDo4amM5qPZClOL1FD7k1GPkecAri+SInfyyyE9fOB\nI0AZmYGW5JqlX4YurXQhDk/nL5rCghRVgylhxSqKtoH66hfwfnAtDfXLgJ+z\nLp0fa7UjZzkhIRgLgsZAvp9EJm1vRXs9oQuq+ZZTPXbH34mpk9btO8jtKIA2\n7rBw\r\n=FAEh\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n[Data Schema](./DATA-MODEL.md)\n\n[API Documentation](./API-SPECIFICATION.md)\n\n## Usage\nSimply install using npm\n```\n$ npm install 3box\n```\nand then import into your project\n```js\nconst ThreeBox = require('3box')\n\nThreeBox.openBox(web3.eth.accounts[0]).then(threeBox => {\n  // Code goes here...\n})\n```\n\n## Classes\n\n<dl>\n<dt><a href=\"#ThreeBox\">ThreeBox</a></dt>\n<dd></dd>\n<dt><a href=\"#PrivateStore\">PrivateStore</a></dt>\n<dd></dd>\n<dt><a href=\"#ProfileStore\">ProfileStore</a></dt>\n<dd></dd>\n</dl>\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox(muportDID, web3provider, opts)](#new_ThreeBox_new)\n    * _instance_\n        * [.profileStore](#ThreeBox+profileStore)\n        * [.privateStore](#ThreeBox+privateStore)\n    * _static_\n        * [.getProfile(address)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox(muportDID, web3provider, opts)\nInstantiates a threeBox\n\n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox+profileStore\"></a>\n\n### threeBox.profileStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| profileStore | [<code>ProfileStore</code>](#ProfileStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+privateStore\"></a>\n\n### threeBox.privateStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| privateStore | [<code>PrivateStore</code>](#PrivateStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address) ⇒ <code>Object</code>\nGet the public profile of the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"PrivateStore\"></a>\n\n## PrivateStore\n**Kind**: global class  \n\n* [PrivateStore](#PrivateStore)\n    * [new PrivateStore(muportDID, ipfs, updateRoot)](#new_PrivateStore_new)\n    * [.get(key)](#PrivateStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#PrivateStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#PrivateStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#PrivateStore+_sync)\n\n<a name=\"new_PrivateStore_new\"></a>\n\n### new PrivateStore(muportDID, ipfs, updateRoot)\nInstantiates a PrivateStore\n\n**Returns**: [<code>PrivateStore</code>](#PrivateStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n\n<a name=\"PrivateStore+get\"></a>\n\n### privateStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+set\"></a>\n\n### privateStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"PrivateStore+remove\"></a>\n\n### privateStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+_sync\"></a>\n\n### privateStore._sync(hash)\nSync the private store with the given ipfs hash\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the private store OrbitDB |\n\n<a name=\"ProfileStore\"></a>\n\n## ProfileStore\n**Kind**: global class  \n\n* [ProfileStore](#ProfileStore)\n    * [new ProfileStore(ipfs, updateRoot, linkProfile)](#new_ProfileStore_new)\n    * [.get(key)](#ProfileStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#ProfileStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#ProfileStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#ProfileStore+_sync)\n\n<a name=\"new_ProfileStore_new\"></a>\n\n### new ProfileStore(ipfs, updateRoot, linkProfile)\nInstantiates a ProfileStore\n\n**Returns**: [<code>ProfileStore</code>](#ProfileStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n| linkProfile | <code>function</code> | A callback function that is called if the profile is not made public yet |\n\n<a name=\"ProfileStore+get\"></a>\n\n### profileStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+set\"></a>\n\n### profileStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"ProfileStore+remove\"></a>\n\n### profileStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+_sync\"></a>\n\n### profileStore._sync(hash)\nSync the profile store with the given ipfs hash\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the profile object |\n\n","gitHead":"df185f4ae471c2b716985030c5e246e3c8329d36","scripts":{"lint":"standard --verbose src/**","test":"jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/*.js >> README.md"},"_npmUser":{"name":"castelo","email":"castillo85@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.11.4","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.31.7","jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-1_1536785964415_0.2239177250295601","host":"s3://npm-registry-packages"}},"1.0.0-beta-2":{"name":"3box","version":"1.0.0-beta-2","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"a216a96fae73597ffe9e0090c5851d948a40f44d","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-2.tgz","fileCount":28,"integrity":"sha512-1BRaPpCfBXWz3EMYoEIVRbAz5SUwmJlV+/ntnSLt0fUPL7JYnoF595qikDYXE8tBWuhVwMaeC6tKECdjKWwlJA==","signatures":[{"sig":"MEUCIQCWYZi/jpMqOY7jjXb5vg3Stsgyw5hnrAIZFP7fBzXr0AIgdEi0RggwklEor4xMrgz9aB0uqIO4DNKJfdHleq/wCVM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6671472,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmobnCRA9TVsSAnZWagAAA48P/R/zTgdqDdy/XM/gEPev\nJusNs+b7XaSRrF8zEPh7sm+zuOwA1s8EDzecW8t6x1dpldpiKdHumrjE9mK9\nTzxA0B7hHedi1vN+4K7LwPofekvka4mgGx9b10mCm8Uf4gummrhQUYoO1fv8\neyYttdULbxIp8Vcr3yLduZaEVflAcIvVevB0OY/mz2A4AzyPXO+Rzc71V7Mw\ngpRCx23X2EUv1J4DKYBsryOkaFFn37ra/8wRkeOG6AYulmVI1z2NAj8ZV/bv\noADTrfh4sVFU5OZTcOdPOwhAAoWHpRiGcS1LQ0hGUbo8mX//Yoy0MEATvrib\ny+riQBiJ/Fzg0MJ30aBDX1Kgpr2qY1sVvghAo9+EF5yQpidMqitIkQmotpWO\nLutb/2vMTMMOKfV7o2zXEPKCT+dByOlwxp4/vF4ovlN4s0fOlBA4JySgyDjY\nwC2wg4HIw6uJA6ny7senwnfmVt1/HOrwtlnKskj2n0uAkrynoumiVh/LtS8B\n7fNYYi3V5aYmFwZjXG0C9TVLwzbglUwativw4dBQnokrFLTBx0oz6DDQrSWD\n6FB/JsB4/KPerCebRcty4Ub8sc7ak+kJ9vCJvzzCNBJ02r44rLAc4F0XWW4d\nseQfBOMWo/U3QJVmXDtAW2ZS0VLEq9JB/8nFAfkQ/GshefUt9L18zyAb0AqD\nJzf6\r\n=caFN\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n[Data Schema](./DATA-MODEL.md)\n\n[API Documentation](./API-SPECIFICATION.md)\n\n## Usage\nSimply install using npm\n```\n$ npm install 3box\n```\nand then import into your project\n```js\nconst ThreeBox = require('3box')\n\nThreeBox.openBox(web3.eth.accounts[0]).then(threeBox => {\n  // Code goes here...\n})\n```\n\n## Classes\n\n<dl>\n<dt><a href=\"#ThreeBox\">ThreeBox</a></dt>\n<dd></dd>\n<dt><a href=\"#PrivateStore\">PrivateStore</a></dt>\n<dd></dd>\n<dt><a href=\"#ProfileStore\">ProfileStore</a></dt>\n<dd></dd>\n</dl>\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox(muportDID, web3provider, opts)](#new_ThreeBox_new)\n    * _instance_\n        * [.profileStore](#ThreeBox+profileStore)\n        * [.privateStore](#ThreeBox+privateStore)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox(muportDID, web3provider, opts)\nInstantiates a threeBox\n\n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n| opts.hashServer | <code>String</code> | A url to a custom hash server |\n\n<a name=\"ThreeBox+profileStore\"></a>\n\n### threeBox.profileStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| profileStore | [<code>ProfileStore</code>](#ProfileStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+privateStore\"></a>\n\n### threeBox.privateStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| privateStore | [<code>PrivateStore</code>](#PrivateStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"PrivateStore\"></a>\n\n## PrivateStore\n**Kind**: global class  \n\n* [PrivateStore](#PrivateStore)\n    * [new PrivateStore(muportDID, ipfs, updateRoot)](#new_PrivateStore_new)\n    * [.get(key)](#PrivateStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#PrivateStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#PrivateStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#PrivateStore+_sync)\n\n<a name=\"new_PrivateStore_new\"></a>\n\n### new PrivateStore(muportDID, ipfs, updateRoot)\nInstantiates a PrivateStore\n\n**Returns**: [<code>PrivateStore</code>](#PrivateStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n\n<a name=\"PrivateStore+get\"></a>\n\n### privateStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+set\"></a>\n\n### privateStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"PrivateStore+remove\"></a>\n\n### privateStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+_sync\"></a>\n\n### privateStore._sync(hash)\nSync the private store with the given ipfs hash\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the private store OrbitDB |\n\n<a name=\"ProfileStore\"></a>\n\n## ProfileStore\n**Kind**: global class  \n\n* [ProfileStore](#ProfileStore)\n    * [new ProfileStore(ipfs, updateRoot)](#new_ProfileStore_new)\n    * [.get(key)](#ProfileStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#ProfileStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#ProfileStore+remove) ⇒ <code>Boolean</code>\n    * [._uploadProfile()](#ProfileStore+_uploadProfile) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#ProfileStore+_sync)\n\n<a name=\"new_ProfileStore_new\"></a>\n\n### new ProfileStore(ipfs, updateRoot)\nInstantiates a ProfileStore\n\n**Returns**: [<code>ProfileStore</code>](#ProfileStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n\n<a name=\"ProfileStore+get\"></a>\n\n### profileStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+set\"></a>\n\n### profileStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"ProfileStore+remove\"></a>\n\n### profileStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+_uploadProfile\"></a>\n\n### profileStore._uploadProfile() ⇒ <code>Boolean</code>\nUpload the instanced profile to IPFS\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n<a name=\"ProfileStore+_sync\"></a>\n\n### profileStore._sync(hash)\nSync the profile store with the given ipfs hash\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the profile object |\n\n","gitHead":"15dd1b82a01bbf83a577e54f0830fcccba979563","scripts":{"lint":"standard --verbose src/**","test":"jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.31.7","jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-2_1536853734226_0.1266796568364208","host":"s3://npm-registry-packages"}},"1.0.0-beta-3":{"name":"3box","version":"1.0.0-beta-3","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"4da7820c5286c448ee052e70ac603de0eafb7122","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-3.tgz","fileCount":28,"integrity":"sha512-3l2mvhUUBx5p4WlGR+EU5lEKJJBECuZUYB7GRL2R03fZPlhBZW5Hax4TxaaEhC4Um8Ton/n/9CcWN/ekuvWK2g==","signatures":[{"sig":"MEYCIQCQwBR+qcQMZ/zze1xa5/qpEm4VYmMrhA4z8p35wcUG8QIhALn6iIJPrAOk1q4zfk3YKNc/7cM3f3y7+QyS3SdDHMcD","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6671575,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbmp20CRA9TVsSAnZWagAAHOkP/3/o2ZmW00wwXc/gIxFz\nnzt8NWF7YINzX0JCZC5FYjnpGw9czdFaNfR0t8Il0AW2WvxY5/VRtl86Rze8\nYPjYP8eoWXRwZbFggGHFtzWrx5YzY8fGGWi/Awmp0mZH/jVBY1AZAH/12/yG\nOYHTOpEj3ttydqk9BSpGoJiaFC77u2Q0M6B2eYHgUyHojMlzO2abj80N5F9o\nRCEAfU+FOY8Lru28nFY+AC4UJWKxgcHTcmMTule6GLjCyhH2LYD5B9vxxhVo\nmK7OOuFpTa2XArEknAoZWzk4Ku6Av+j+kOEgUI68rsTmeSSUZ0J1z6Mgu9RO\nzTVMnW+wojfC3hArAHLWhDsheKwdjU6D76AfXW8YzYV4xZ95h1xBm2YxQwob\ngBosO0SFeRu1jebpSpXYJ/uhMasZKn2l5ZiBJVnnAY9UOE/6UtLrTu2B+yHn\ndAU+WCjvWLT5uCB4XcG9YrGscsWPWDHrvnfglV2v51wWtW2egDQbozQ3WM/S\nlsEjcT+BlDuKDoVLoBc08Cya7iSPppHdKHwzK6/uhS9kPiKu1gQD0++e5/7f\n+8FmX6UDD1vSsRZuStVbJ19XtaX+cMr9J1o9zpSApUYjpAefuqYBCXFpwZiE\nf4eSUi+8dXvP5McsSZ4deGDOt8WAEZJkftjpCGdVzDE07Gij8KnVDwHGiNL0\nSTjh\r\n=HIlf\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n[Data Schema](./DATA-MODEL.md)\n\n[API Documentation](./API-SPECIFICATION.md)\n\n## Usage\nSimply install using npm\n```\n$ npm install 3box\n```\nand then import into your project\n```js\nconst ThreeBox = require('3box')\n\nThreeBox.openBox(web3.eth.accounts[0]).then(threeBox => {\n  // Code goes here...\n})\n```\n\n## Classes\n\n<dl>\n<dt><a href=\"#ThreeBox\">ThreeBox</a></dt>\n<dd></dd>\n<dt><a href=\"#PrivateStore\">PrivateStore</a></dt>\n<dd></dd>\n<dt><a href=\"#ProfileStore\">ProfileStore</a></dt>\n<dd></dd>\n</dl>\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox(muportDID, web3provider, opts)](#new_ThreeBox_new)\n    * _instance_\n        * [.profileStore](#ThreeBox+profileStore)\n        * [.privateStore](#ThreeBox+privateStore)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox(muportDID, web3provider, opts)\nInstantiates a threeBox\n\n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n| opts.hashServer | <code>String</code> | A url to a custom hash server |\n\n<a name=\"ThreeBox+profileStore\"></a>\n\n### threeBox.profileStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| profileStore | [<code>ProfileStore</code>](#ProfileStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+privateStore\"></a>\n\n### threeBox.privateStore\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| privateStore | [<code>PrivateStore</code>](#PrivateStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"PrivateStore\"></a>\n\n## PrivateStore\n**Kind**: global class  \n\n* [PrivateStore](#PrivateStore)\n    * [new PrivateStore(muportDID, ipfs, updateRoot)](#new_PrivateStore_new)\n    * [.get(key)](#PrivateStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#PrivateStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#PrivateStore+remove) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#PrivateStore+_sync)\n\n<a name=\"new_PrivateStore_new\"></a>\n\n### new PrivateStore(muportDID, ipfs, updateRoot)\nInstantiates a PrivateStore\n\n**Returns**: [<code>PrivateStore</code>](#PrivateStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| muportDID | <code>MuPort</code> | A MuPort DID instance |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n\n<a name=\"PrivateStore+get\"></a>\n\n### privateStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+set\"></a>\n\n### privateStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"PrivateStore+remove\"></a>\n\n### privateStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"PrivateStore+_sync\"></a>\n\n### privateStore._sync(hash)\nSync the private store with the given ipfs hash\n\n**Kind**: instance method of [<code>PrivateStore</code>](#PrivateStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the private store OrbitDB |\n\n<a name=\"ProfileStore\"></a>\n\n## ProfileStore\n**Kind**: global class  \n\n* [ProfileStore](#ProfileStore)\n    * [new ProfileStore(ipfs, updateRoot)](#new_ProfileStore_new)\n    * [.get(key)](#ProfileStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#ProfileStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#ProfileStore+remove) ⇒ <code>Boolean</code>\n    * [._uploadProfile()](#ProfileStore+_uploadProfile) ⇒ <code>Boolean</code>\n    * [._sync(hash)](#ProfileStore+_sync)\n\n<a name=\"new_ProfileStore_new\"></a>\n\n### new ProfileStore(ipfs, updateRoot)\nInstantiates a ProfileStore\n\n**Returns**: [<code>ProfileStore</code>](#ProfileStore) - self  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| ipfs | <code>IPFS</code> | An instance of the ipfs api |\n| updateRoot | <code>function</code> | A callback function that is called when the store has been updated |\n\n<a name=\"ProfileStore+get\"></a>\n\n### profileStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+set\"></a>\n\n### profileStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"ProfileStore+remove\"></a>\n\n### profileStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"ProfileStore+_uploadProfile\"></a>\n\n### profileStore._uploadProfile() ⇒ <code>Boolean</code>\nUpload the instanced profile to IPFS\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n<a name=\"ProfileStore+_sync\"></a>\n\n### profileStore._sync(hash)\nSync the profile store with the given ipfs hash\n\n**Kind**: instance method of [<code>ProfileStore</code>](#ProfileStore)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| hash | <code>String</code> | The hash of the profile object |\n\n","gitHead":"3211d7a3524d4392701c86c7e1870359403fbf1e","scripts":{"lint":"standard --verbose src/**","test":"jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.31.7","jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-3_1536859572236_0.2325700297309432","host":"s3://npm-registry-packages"}},"1.0.0-beta-4":{"name":"3box","version":"1.0.0-beta-4","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"2986f4aa04914f7fb1d2ad7307f860d87264157b","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-4.tgz","fileCount":33,"integrity":"sha512-cl/rCZsK/AqXzDes4rru/aqmNpO1mZSd8JRpfbX2wdWPY2wZckusqL2KSA40m9L15yip5aU7TDp52k3k26Q0Mg==","signatures":[{"sig":"MEUCIQD++Oa/IWVAtWFdlnaK2X13l6M7bCThBBNk+I7h6dRInAIgDpxendPHvd2TXq4XJPp/OrrtdG6WrXfmDJOfGec22FM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10084366,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbszpCCRA9TVsSAnZWagAAm5UQAIBPQ0n1vk8gm8Bu9BUk\nCdJYrwe+/ln/sj6ClZQGn99Oo6IN+81aWoqOJMQ+HaP5wcGlpiWSqFw5QVNV\nH3snXFNdK/L4dd4j8QNqUDY29qKjMdv+BKMy9R18aSQvoY3Jl0WQs7z3WiqR\nAyVWv2cEbt07BmZO9Mx/tDp9qCJXWoeap3uln//JDeXxhfGblbEjJQqKtiZe\n8fh3GtM9bZLxx/uZaTVYxMfwxqxydzAheqLklPN9pLGo9qrAnRTJwXQ/Pbsx\nyUNvtgKL0gMjZVXDUSfMRBWVAJkgyEDMBYF8PIqKLZlx17qzGyBlkboIoBhN\nuXXNNj8lkgJoSwSWVAgjt7YtLA/5HIEvv8cGzBdfJEx0VZXzhFh8apK8ifCn\nB6HcvrIAjf+V8yLKFS4XR1MAI94wb2fiybxhMq9pNOTnR/hE65gBkt1iIFWP\nIFs7R9DrN2FtmoMDrzgahAOAhizGC34gZsRqP0A6b26tfYm5PJQVvn0KVHj8\n9X5bNLuMHlvI9lfpmmDzXOA/5U6c3SgpGKIhI0eRT/OWlMB7V5d9ZIYfGezj\nCt6gUF6drRgC7Gqqs5akhinuR4rp3oAAFYT/XPbDtHYdAXBs6lOWQVJQLB+o\nJ+5gQg0CknRHSJs7EdsnTGzTx7OIsxzpSxrc8t4R4PfkFM+F7Iu9P16cex6K\n+Co7\r\n=mH5m\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## Quick Links\n\n[Data Schema](./DATA-SCHEMA.md)\n\n**Report an issue**: Copy the [3Box issue template](https://github.com/uport-project/3box/.github/ISSUE_TEMPLATE.md) and [create a new issue in 3box-js](https://github.com/uport-project/3box-js/issues/new).\n\n## Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.profileStore.get('name')\nconsole.log(nickname)\n// set\nawait box.profileStore.set('name', 'oed')\n// remove\nawait box.profileStore.remove('name')\n\n// use the private store\n// get\nconst email = await box.privateStore.get('email')\nconsole.log(email)\n// set\nawait box.privateStore.set('email', 'oed@email.service')\n// remove\nawait box.privateStore.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.profileStore.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.profileStore.set('name', 'oed').then(() => {\n    // remove\n    box.profileStore.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.privateStore.get('email').then(email => {\n  console.log(email)\n  // set\n  box.privateStore.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.privateStore.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# API Documentation\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","gitHead":"1ba895b81f09c2c54ebf0eb84475e35ce8d0e05a","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-4_1538472513261_0.47520642083909514","host":"s3://npm-registry-packages"}},"1.0.0-beta-5":{"name":"3box","version":"1.0.0-beta-5","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-5","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"04cd665227d7b87adf3739bc42fd9e2a552e8296","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-5.tgz","fileCount":40,"integrity":"sha512-iObmazFFxlWzKM1Hw9wyfC43qU50s6t4eeZoLDtKnbGIBGrkWFEO5txyawZr8OQZHZE62lbC5EDrAFEb0TG7Vw==","signatures":[{"sig":"MEQCIEjckPs6eYN0bm+qMASUlmBv6AUjahl3vgqIW6HMf/FEAiBIlVV//TvMVi9PuLdODrrzbURJ0zRR+H5enxARpMcJ9A==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10096374,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbtIxhCRA9TVsSAnZWagAAFe0P/3H3I4HONW6njRmKa+jg\nFo6B0g2zdlOZxYcFyh9wMy1G9MmqRHYQp0rn0MXBH3OoU4gLpbQtcqf/uZG8\najyKXqw6S2I/uuT9b3pMG+laCPKPo4aN0jwk728GUz58PasV72rKk24Bukea\nHZhh/eL8Q9Np0k6kMS19k/1M8zM+H1DZ/NoKLzD5Ca2B7qUF6KVdf2dsG9zo\nvVji+B5xhS6g6qR4tNsR8l5mUWigsuUXJDhbYLVVg3Hu5XTWe5NWGEDaJv2W\nZet6Pw/t7lyrM99q6m4wetD2KTwLvS+7kDmJb1JvH03v+1STzJQbS6/EuA/P\nkaI5X2GKH5Gfw65s76Zbyu4tJz+HL3iwQnIZVNVq5b5SztqD4SzanqdGJolk\n4Hy+75KQwLCO9b4QKb5DBDYifgnzHbfr34DyrYP/AE6tezUAP0J2lzxu5g6G\nCa4CIw6V99vTtyVIWzKwWMne3XCrlUCgOiM27kwfA6LZ9LDQ6UFiAjhwM2Kn\nTyHr201FfJy5/PrIImF64RtrkUGNeJK8lmz8mpqv+n0XqsCBpo6n5eepYJzD\nwQ8UuesARY4Xln+ZrXABe0I1hhuQlW8wdbnexfuVA6wQUUaqQZdkdhIXAaTu\nCIpfjZ9dGPFdFk/JfBq4QZPJSalnOzjYdr8A92Fn/ogiS2JfOSRUt+IFtv5h\nhmQ+\r\n=O3Pc\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## Quick Links\n\n[Data Schema](./DATA-SCHEMA.md)\n\n**Report an issue**: Copy the [3Box issue template](https://github.com/uport-project/3box/.github/ISSUE_TEMPLATE.md) and [create a new issue in 3box-js](https://github.com/uport-project/3box-js/issues/new).\n\n## Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.profileStore.get('name')\nconsole.log(nickname)\n// set\nawait box.profileStore.set('name', 'oed')\n// remove\nawait box.profileStore.remove('name')\n\n// use the private store\n// get\nconst email = await box.privateStore.get('email')\nconsole.log(email)\n// set\nawait box.privateStore.set('email', 'oed@email.service')\n// remove\nawait box.privateStore.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.profileStore.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.profileStore.set('name', 'oed').then(() => {\n    // remove\n    box.profileStore.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.privateStore.get('email').then(email => {\n  console.log(email)\n  // set\n  box.privateStore.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.privateStore.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# API Documentation\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","gitHead":"01c46fc42c73f6037fcdb9e0b03a7abc3896d035","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:all":"npm run build; npm run build:dist","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.2.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.8.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","browserify":"^16.2.3","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-5_1538559072836_0.7292663974660716","host":"s3://npm-registry-packages"}},"1.0.0-beta-6":{"name":"3box","version":"1.0.0-beta-6","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-6","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"d1b357446846d550306265b6d83a17687e728a2a","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-6.tgz","fileCount":24,"integrity":"sha512-kOO3glDyQUdZPVktuDgtJw55hjAIVUVM2rS7ihRT/iZ/+ngQvEZVLBLrAo6TETSAPaNnlh9HEwhLQJPcKTfaFg==","signatures":[{"sig":"MEUCIHQdKKUYmeztC3yQhSCCJ0ftiReLaTPo30nOCU8wCgcJAiEAmggc/wSMT9cqbMyzT8ptjfgKyT+jXp2IIB/UYMe9dBU=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10025097,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbtl0BCRA9TVsSAnZWagAAtFUP/1R7ZlR5nh22lzG9hEXe\nbJ9c92d3pJJeX2yLHmLXUh2+X4YCVHoA3HgbDBVVdEl1z1NGlnZh+LcGXtbD\nh6ugkUlZDGEblHGsIjdP8WEeENyzl1j7w3mv+4uiZNW292k26JPMoOZwAbrg\nHSLqSx9bngckyXEMTsLUebOIc9pc7pg9t4AP1gAD2259ael9FhhLJsnuR4kM\nu2O9oo0904qhPqVXGKB4uarK2l9FC+BecqCxR2uCv8sRER3XGxB94dI1FpG6\n8Pwuk+QDECSKegqEIHf/4pLpAN06cIRyJxBBopUE+TTVSk28wG8AJkwUOTK6\nTpvJunBycjCOhnxKEJIHxItfsRIkqQrddrPTHQIrvR28QaSdRU7eZFmnkrM+\nUyBhucbJMjQcSRK8ajo0GVKQQ6uWxnX7lWbU8NvfJOLDqi6ixGdD4ZQYtnDi\npUQKIIxWRrk8kOup8E6V9gMPnFNHN/RUH4nTNXzEUVCgREhIIyITHMbCwIw9\nLB6CB35Ax2WOrUlP9QDKJjOOJImt/0lbj0UyPjhUlNU/Tq6yZ713yYiOyRnY\nTlTNzS2v6EAjaZCYtUoaOQtY7svgVLchypFpJEtkWg7nheKF3YGi4zrikkN0\nPMiLcVWIlyOn6nTsp0trcm8PdfUdqEFN58BcV40g/xsjGacBStjPHSn/mdEe\nurl0\r\n=BKiM\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n[Data Schema](./DATA-MODEL.md)\n\n## Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.profileStore.get('name')\nconsole.log(nickname)\n// set\nawait box.profileStore.set('name', 'oed')\n// remove\nawait box.profileStore.remove('name')\n\n// use the private store\n// get\nconst email = await box.privateStore.get('email')\nconsole.log(email)\n// set\nawait box.privateStore.set('email', 'oed@email.service')\n// remove\nawait box.privateStore.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.profileStore.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.profileStore.set('name', 'oed').then(() => {\n    // remove\n    box.profileStore.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.privateStore.get('email').then(email => {\n  console.log(email)\n  // set\n  box.privateStore.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.privateStore.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# API Documentation\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timestamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","gitHead":"f408587f2e6ca3673552cecaacfc922c040c6121","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:all":"npm run build; npm run build:dist","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","browserify":"^16.2.3","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-6_1538678016581_0.9382943861430237","host":"s3://npm-registry-packages"}},"1.0.0-beta-7":{"name":"3box","version":"1.0.0-beta-7","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-7","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"04fdf34b7339da5794498a94debe7aeec20403e3","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-7.tgz","fileCount":30,"integrity":"sha512-kohDtV6RO9GCo1IlO+Pb5DvxrFpGyQWrhnEVlB2QfR5MvK9lJrBzC0vP7boVVp+9/bnWchDpdbO8IDwAdXjGZQ==","signatures":[{"sig":"MEYCIQDqzmaabLzDAL5A84o6wWU+7N2xWEtAA8KFpH4dtuAfPgIhAJwlcJY8rHQt8VQGS5rYoJszdUW6gcYgwQtHFg6uDBh2","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10143320,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbt7GoCRA9TVsSAnZWagAAFdoP/Arz2lF6+AbCHQNCP5Dk\nRDpXH5/AmxH4q5VB8Oni0t9Gx1QK2AIN8pMKMNFp5FUCqpW41rR+Jbur9p1h\n1lfrKDEXxh8/vQ0xTu8VKXf/iC4dlgJXWc2CXtAYXoutZiNWhUeDHgIhy6Pi\nydMydQOXaXY0ZsZuNTBsTPAOymQ9Ty/Z6zCBjwkxMDpn+DYA1nCBucvhy3X+\n4IwoCBoUWMzbXHISJg4FPZgpU6QWQbocUmDX4A/X2JUZKkAuWvGJU7snt2V/\nNDUrhUbfPP9/ybw5xjNpr2grl2fAmvOISxWY7mtHIMlt2kzGsioAuBwID9LF\naeYza3xboIF25tWzbaSKiJZNTREjhYJIDxUBwiNkkmAIyojBa+/Iim+raOfo\n8wdc6zXcRuCFcdEPep+RDcRP0pLKVbDG1vUTnttod4fP6DKG/lZ0qHIqcfUX\nWXhBphnjnBupnT9CzHH01Kh9R768Mx2lfVUkamw3qPBWalgek2+jP0whK9RI\n1yhkpW15VnFyVDdDtpU88IE52TB2erAo4Hiq+gWKSDigKybsmbW5222I0uJw\nuK0AfKC4f5o0yB4cOmszZ6I3t3LiRgxmgKhAx7YIwYKGlurPBP/aWY8MeGGe\nFJN81vnN0vgef+16pGNN/ZebjJqtZilt+o+d7AvbPhh/3D+KG0ZvevrXvBQB\nOj9R\r\n=ktpg\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n\n## Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box@next\n```\n\n## Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.profileStore.get('name')\nconsole.log(nickname)\n// set\nawait box.profileStore.set('name', 'oed')\n// remove\nawait box.profileStore.remove('name')\n\n// use the private store\n// get\nconst email = await box.privateStore.get('email')\nconsole.log(email)\n// set\nawait box.privateStore.set('email', 'oed@email.service')\n// remove\nawait box.privateStore.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.profileStore.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.profileStore.set('name', 'oed').then(() => {\n    // remove\n    box.profileStore.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.privateStore.get('email').then(email => {\n  console.log(email)\n  // set\n  box.privateStore.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.privateStore.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n# API Documentation\n\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n","gitHead":"a0916d37b4948d9e9cb63716aa07ed2fd7c650db","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:all":"npm run build; npm run build:dist","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","example:start":"node example/server.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","browserify":"^16.2.3","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-7_1538765223307_0.3494428365824207","host":"s3://npm-registry-packages"}},"1.0.0-beta-8":{"name":"3box","version":"1.0.0-beta-8","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-8","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"b688f6b654b9ef4fd715eb1f51b979f3f1aeaa24","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-8.tgz","fileCount":30,"integrity":"sha512-G7FWIOyEY66DmACDVurBrJh71ZQSQIwTWL7lLK8NGUKRSSzb11wryOxJQXCWPAzdIlER2qvcZX1sRfLXy9B2Uw==","signatures":[{"sig":"MEQCICyJ9VuQNfprLM8fxM6i0bKwkip92vpohO7lq7PpnLq3AiAiKAcdZAts1mOoXmGg+veqQ8TcnnVik6y2nIGQpyEgVA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10154560,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbvgBsCRA9TVsSAnZWagAAuYMP/A64TKx3z9jJRIODfpj/\nSrn4lpGJLk4ow68PaspJAVFyXiTYa5Jnqm/ACR3BhVwcP9TASM3YTm7zom0F\njHlok77aJmSGzRq6SC/fPHl/hCNdtT8ssYA7Fgaqd4OO7HWcpBMw7qMsVGS2\nRcZrCXTuQPHHBkND9iv9x/3UYAFzU/GwzALQKqVFu3ciCTltq/dqnYiM+mlJ\nNQqB9YRWKyu8WClOdMOC2b84fPT8p+4z5MAOnU8YqASg+dd1K47BeBPxkZYa\nKN3jZJI1VgPMKChNJw6t6hEBLAx+Xqje+thRIG6YuR1cNvFnJlYCNFeCgfWG\nSj5V7KYiJitOVDE7g2zoNemHFRm9uT8UC7D3S36LPw2UZL58uGGo2MWw9EmO\nhGhw6Cp/tad4daYFjCY1bctBUxVWMm4WuH8wUJoPVQBgvP5pfiAyjJmtnkRg\nbnkxRjgKM5hnN3DVPygdbXjIs8zzwMlLCnLMaV3mEWYjru84n/gWMjLYmv0A\nX3XLHgR63AOQsMYEL7/eI+F26lcBNXo7Nq9khJkoqg7yKkHHp9fpUKQuYH4o\nk/3TQu6eR8iVyX9QTUUwL8RRD8bmiMasEuaAqXx30wv+ku9k+YgNouAM9Rlv\nwisSLIDG4DJ3GWoU6bjqFPLxnOLZ0tW2EJSzdPvF6mVCZXBYFV7gNsBZppwb\nJM7H\r\n=g+lA\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n\n## Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box@next\n```\n\n## Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n# API Documentation\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","gitHead":"bcc8eaa09c593e7a572419777a76d23e1fc96f84","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"babel src --out-dir lib","build:all":"npm run build; npm run build:dist","build:dist":"browserify -s ThreeBox ./src/3box.js -o ./dist/3box.js","example:start":"node example/server.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","browserify":"^16.2.3","ganache-cli":"^6.1.0","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-8_1539178603593_0.47748318193137873","host":"s3://npm-registry-packages"}},"1.0.0-beta-9":{"name":"3box","version":"1.0.0-beta-9","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-9","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"817f557d0aed38e56feffd842e14ee37db0f3f99","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-9.tgz","fileCount":41,"integrity":"sha512-a5Zi5Ua6NewVngwsEGL5eeV4gTI5ycgJFOAhZ0SeAQz9jwxfu0x83DASQFSuNlSHQ1LvWeHc9M1ltKsVjLn96A==","signatures":[{"sig":"MEYCIQDsIgZESpPUVPHoldVJEQfods1JP/JbStOUyfYlc8YKSwIhAJevsNDvd8VwMxi1fkgksdmgRYNs2Girhe6Psbtx5+CW","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16796723,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbv4YHCRA9TVsSAnZWagAAQh8P/07Ist5MXEZ5WRc+D39B\nn0UvKDauo5RgGGX8n6AmKquuHEsFQ1w2bo5wLiQPyYcRabo2QSpXRkYNzuTh\nrs3UEYP3rD6C+9YCd4YHUmGlI0CuDfvlB9HK8nZP2IotuR2wJCKcQI86cTlI\n/Qj83Wd3u02MN5D0VCDt2//JnIp5myMlA4sQZ8M3e8LVWucihdMdol02Kpnd\nKTZ2V3CS887ZBL3O7SwPA5PnXPG+seoCXLsawAEH/7cSK5YtbOt28NAeZf3d\nRcto5gx8Ak5oc5oQuTgEHuBq5xbThYvAqOA+zF2UC24b8/tXtda7GSeiKBFs\noqCbepwr6UodX7Fw4zJ9yeHme78bg1x6jOTOHSU0cRmEMVLX5NS8FtgkyS8d\nhSfDlEaEca46qsIN7UAA+SdC53okZsjel1nm75NHWpC/IZKsnf8uK8xKbPae\nrGoYJdT2yIqtBzI9T0RoClq7rf1Bt8eJZzM+VuBmIoNFGngJxqzkR9CNKuWd\nLxH5zSDiJtg0FKXb3SCCW9bkKeCbmYtPDTg7X5AbAOTvIpOPx5gvOtC3FN3V\nEMVeuET5XJpP4k2U22HA5p8lGaBIb7W95zVuIawWJLaukPiiRn2PAJYK16P/\naAeNL6/fH7hpybwkScVicVNL1UQJGsxdNWFbLmOH0/qI/IwImd8zXyhgp26C\n/dN6\r\n=WQzd\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n\n## Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box@next\n```\n\n## Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n# API Documentation\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfs | <code>IPFS</code> | A custom ipfs instance |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","gitHead":"74fd885b4ec012c54eb73100288a688d426adb92","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib  --presets env --plugins syntax-object-rest-spread --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"node example/server.js","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","babel-core":"^6.26.3","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-9_1539278342783_0.3063722230698216","host":"s3://npm-registry-packages"}},"1.0.0-beta-10":{"name":"3box","version":"1.0.0-beta-10","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-10","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"04ee8c34b846f22cbd5c64584635ae02e3a9df8a","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-10.tgz","fileCount":31,"integrity":"sha512-GQJYPnrGODwnIXHQWDXzne6OdXnOpcD1e4Zi9vV5HdTjzaEp2AJZxJhMo0iEbePG4MdOfelYrGSZZK/X/oSBhw==","signatures":[{"sig":"MEUCIGZltbE16m1q8nsef1H9mwuQHbdyBVUFuSzepUTrf0j2AiEAoxohffQaGxCVEb5+VcC1MbTGi+Y9AXF236xrPdh7Hp0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16603334,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbxvhWCRA9TVsSAnZWagAAwRcP/2hJtZ0jhQMmwq1+vHsN\nuR6yAk0i+wE3wNiaIwxQc1Y5Zi0pcyHWqhbJIN8X2AO/8rT/t/N7A46D1BSK\nWEeOOL79JBxFdjyGhX4lbDp92rLpgEYW2MDSwHfagHzSMzbJN2HYiFKQUSq/\nVqwZ9AnCFVH3XVWJEYiCnjTPRspLDsvN/39LCxboj3bywD2/QTnDRBObinZt\nl38PeUwsQ7QFhEGNAeuUfwstXxPHo6EH8ZY24Hs84KOKsLrSQ9NbUvF0jj12\njaWyGNqvwIWODzpRNTq4z1HOsecZjFAr/EAo5d7Jh11749VsgSPon7eaYMae\natw2Tv4U6FcMbpe1hDuK7elQxw1LGuh2YhgdvDokuio1dUlGPASuo3JeNfVW\nYmGNebYBtdjRs+kW8iPAt6jUUQtRtIgYqUwf0doGUPvUcNGhSOslHG0AjmdL\nadlbykCzSYEUdTR7QWfIdNqEpq2QjjeH1pcb/MkdAyXshS4hxIREhPFIbIrB\nrjDJn4pdcK/8p2Rx3I/TOa36Zl1P8Mcaf3QJYteV5xjT6HOvZf9DkwQ+eY2K\nbUt9OYbPSG1PZQ6YS3km6G5SaMWl+KHHdK92kyVmVFH8Vy+qVOCnWYvFIT2w\nQ06Qu7kTaAAmIzA1pc6PoaPPCgPk6elk/onoRPLnrvCIthy/gueZ4lTIswkL\naxWv\r\n=i1FH\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n\n## Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box@next\n```\n\n## Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n# API Documentation\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","gitHead":"1ea5cad9459a10b9270b2f4fcfc98117262ac303","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib  --presets env --plugins=syntax-object-rest-spread,transform-runtime --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"node example/server.js","prepublishOnly":"npm run build","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed3933@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","babel-core":"^6.26.3","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-10_1539766357425_0.9929072833012709","host":"s3://npm-registry-packages"}},"1.0.0-beta-11":{"name":"3box","version":"1.0.0-beta-11","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-11","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"0715c2ebc15d4030efa3cce9b83ef10b5e7692e8","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-11.tgz","fileCount":31,"integrity":"sha512-XcKAcsPmKvlejonxmhlqoVFjuyFcrppUoyXnG4mhKgUxKgFy61mGhWVTHl9mmxRSS6IQzktWSsYxdkB/Un+2Og==","signatures":[{"sig":"MEUCIQCYOAcQum3fcIz7o3W2kkAEMblG+gYyCUHz1t4HY9/lbQIgdfctLI78zT9njGDyEK5QcO1uCgjBlCXTyfJGDZR9XIc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16607775,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbyJ1gCRA9TVsSAnZWagAAdQIP/25BiwblLN91+v51Ks1m\nYK2xLi0HXbOZyQCDF9AHeTx8V1onEft3Pa1fmn+OWaifZxXEGlYgtfX+NhmI\nd2k/UFAzNX7obMqk5gla7RvbaP13rr7O9pkMJA/tfqzefJYeItrGzcTiUWTK\n464v8FVd0hETQGhn1GuqWVz1Y97LERq7xm6bQq9JIg09CXWFzcWFFkr/P21I\nrlRWXQwPKhSuALPuhaqjKkdl9Rj5/js+eMMC1yIZSL2gITSj3JYORVh2Wfqm\nTZGMxckRqaerFnMA8CY8ZkGA60ima7fEVDBIrW3eb0Y4hH05BdCYiZu4w2cB\nO/gkIvjaKG8y2e0kic5bkBiV+iM0lD+yD7GoZX4B6ykyy6Pqz0oiiH00iKQB\nVzPAK7UcyDbNbtNzqlHbUKKRHyXzhZlwKoVRrfDcD+YWCxz1CKqJgTy7pegB\nIpaq2etBHe3W5/3yJ7pq7W63gxDbQNzSvjF/CXMEtb3rSgBERADopXPon7Hc\nU55XOjVZJe1olfwLarkCDaw9ON3sdSYsM0Kk3tYYCIWvCQKLNZeIFchA1PpD\ny6KK0tsampNWCFMJL0YE3ZFpuh88m1S4qvTgO+JN9IoACuIUSWzzLjucwFt+\nglhc1ccnfxzuyjigTbnG5XVjn6RfTtO7pDx65O3DVKiTst8YOFsuU0R+Y0Yq\nJN3Q\r\n=N6xt\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/uport-project/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/uport-project/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box@next\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n# <a name=\"api\"></a> API Documentation\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"991ac909ffd6054851934ef0b3e0eb1e950d9516","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib  --presets env --plugins=syntax-object-rest-spread,transform-runtime --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","babel-core":"^6.26.3","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-11_1539874143709_0.4910485486003442","host":"s3://npm-registry-packages"}},"1.0.0-beta-12":{"name":"3box","version":"1.0.0-beta-12","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-12","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"60dea479111e9c04b275076d7dc5ae3ad093d021","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-12.tgz","fileCount":31,"integrity":"sha512-x+XG25FuYT3fDo922Qx1MYICHRjfhga+UP2gdl59PQ/b2CgpJaYW0wRVowUvfHeItkJ2M7ZXg99VltXY0jisWw==","signatures":[{"sig":"MEQCIHdq7wGzWjJJWa6CTHUNm4hthDaajDmj/K4e20cVGqWgAiAm7FNt8JPyA+Cs9Y8FddfmDtfeXjP5tSqN6XtguuY1Uw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16608231,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbycyECRA9TVsSAnZWagAAD+cQAJQeu0O6Tv16j7e4gkbj\n8EZJHfO7WCOMtv0DO2wt8BquyTV3jVUsN1/HEGaGlhh3hGw5VhEfBoLRjA+/\nU+gUSXT7eSkGciSxmonxuBi5V5yRZRGvLmEL+r2z2maFOnZF4Y/U/Pseurss\neHLDldlpU6+qb4J8mIeQqT0FzKyYlCLC3ymy/Od2K9QWIj1XBdCN1PbMhvSR\nzTPbs7VP/GDVLibq83ieUo5qimrUZbhcipB93T+8ptKo+dPr3AYTKL/tUacr\nnUFeLNYb7awq88mFqNNtfjUW+1XWoPK+lpiUVZThH4batNmN0HenK66bUwsG\nfTJMhPUvonANgM4s7gRuFHEvaPp1xHlw3EP+4tXvmcN73vfXh6DBN52awYT5\nplwSx8yEDpaFQ+Z8E3eaLtGEnzUWkcTtruT3lWEUBvQDd6pTPDwvrvH05BwR\ngOh7qS+VSyiDcARj69LzBVWPyX1adH8/6xtN0s85vpkaO0lax3nyVgCRjQ/i\nRwCDybg49tmNuxkHNBKdbA1DG938kUlDRN0I+r6lH/aM8vKSd/n5Jp0md67X\nKrT6fal7QXduNuuXWQZmcIzJw8YY9LXj1OSN9bkVIKxHCclLIt0I+eHkOahY\nP5bmujWINyTA6nSLlougeD0r6K+vIAZPh6vhxghwMslpkb5o88u1kJCD5MM2\ng1We\r\n=hXlZ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/uport-project/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/uport-project/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box@next\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n# <a name=\"api\"></a> API Documentation\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n        * [.isLoggedIn(address)](#ThreeBox.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"ThreeBox.isLoggedIn\"></a>\n\n### ThreeBox.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"a071a1c475c0495be99ef957272dc5337d2e2f9a","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib  --presets env --plugins=syntax-object-rest-spread,transform-runtime --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","babel-core":"^6.26.3","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-12_1539951747521_0.5257249644618267","host":"s3://npm-registry-packages"}},"1.0.0-beta-13":{"name":"3box","version":"1.0.0-beta-13","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0-beta-13","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"94094b15801db506c8b625b826b2601983001f63","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0-beta-13.tgz","fileCount":31,"integrity":"sha512-JrnXrg7Ll0NQYtAukYL0S8t7KhBJgR3bptz4LTqPOuDvQ7ajSZ7Kc5d9OXgf6OgIk1C0Lbikk4KzLd3sjzGKMg==","signatures":[{"sig":"MEQCIG3RaywymEsgNr9T1kxPusNJ047BQIUUBXZH2uQ466h4AiBLjw5QielGftDDXO67sStcdJirVySWeq62FCIy9CjFCA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16610682,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJbzzzuCRA9TVsSAnZWagAAETwP/2gUcDEk/h0vUyWv6R9S\nMeyq7aMAWUEBt2rRrT0Fm41PW26xuUPv/DRZHFggXBh+KtGn3kjdB/Nq2HpP\nFAghJhAYSgeA8JIcDMVRs7RvXGlN38Kk2i5qEpv7/O2CCHdXPvyBUh80UP8l\nLZ//ZhGh7Rd7RSOklRJrJx3ltR6CbT57E8T/Z3retwPpGHLtVtRfJV+5NqqW\n+H0WP4vo4qDBVrVj2iZ2HdLF3B/RlGGEuTbCoCJ0fAJ6M3Hb2MtvApfNwr7l\nG/5WHacJstg3tD/c5LiZykhgIZb59lfqbWzZCBDdzhyFgNG6eVRQO9Wt9f7l\nReclIQyF6SFRvfs57va7OofIO2xCImiPN3gjVOoTq3fFrU1hy9+y3c+J3JmE\nsoWwrg9PWyCNdi82Wb8N7J0mefND5w40nmAGzzMnAZS4eIL9XR5Y/l7o5fIL\n4RsiuGHJOA440BEIs6wkUrFb5YX6p7W9ixFV/BTHiJmAjqhrl4AZcbsdOSWk\nPp6pXk2PTPnXsT+dYfFKEPHT0/hc+Z3Ibvbxqow2rkqfB8hI7qGI/m9qTNq1\nBeOOIt3h3NyVDxzY+hg0IvtmujxI6TW3yfqTMzHqp1Ok9ezwG159/OZzwQnj\nIj5GeNLjqT0w606vVsvhP/orhpxHypoEXKTVa778536SN4mnqZ9eZh+fjQ0s\n1ZlE\r\n=0a+Z\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/uport-project/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/uport-project/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box@next\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst ThreeBox = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **ThreeBox** object.\n\nUsing `async/await`\n```js\nconst profile = await ThreeBox.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nThreeBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `web3provider` refers to the object that you would get from `web3.currentProvider`, or request directly from the web3 browser, e.g. MetaMask.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await ThreeBox.openBox('0x12345abcde', web3provider)\n```\nor using `.then`\n```js\nThreeBox.openBox('0x12345abcde', web3provider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`. [**What keys can I use?**](./KEY-USAGE.md)\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n# <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n# <a name=\"api\"></a> API Documentation\n<a name=\"ThreeBox\"></a>\n\n## ThreeBox\n**Kind**: global class  \n\n* [ThreeBox](#ThreeBox)\n    * [new ThreeBox()](#new_ThreeBox_new)\n    * _instance_\n        * [.public](#ThreeBox+public)\n        * [.private](#ThreeBox+private)\n        * [.close()](#ThreeBox+close)\n        * [.logout()](#ThreeBox+logout)\n    * _static_\n        * [.getProfile(address, opts)](#ThreeBox.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, web3provider, opts)](#ThreeBox.openBox) ⇒ [<code>ThreeBox</code>](#ThreeBox)\n        * [.isLoggedIn(address)](#ThreeBox.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_ThreeBox_new\"></a>\n\n### new ThreeBox()\nPlease use the **openBox** method to instantiate a ThreeBox\n\n<a name=\"ThreeBox+public\"></a>\n\n### threeBox.public\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users threeBox |\n\n<a name=\"ThreeBox+private\"></a>\n\n### threeBox.private\n**Kind**: instance property of [<code>ThreeBox</code>](#ThreeBox)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users threeBox |\n\n<a name=\"ThreeBox+close\"></a>\n\n### threeBox.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox+logout\"></a>\n\n### threeBox.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>ThreeBox</code>](#ThreeBox)  \n<a name=\"ThreeBox.getProfile\"></a>\n\n### ThreeBox.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n\n<a name=\"ThreeBox.openBox\"></a>\n\n### ThreeBox.openBox(address, web3provider, opts) ⇒ [<code>ThreeBox</code>](#ThreeBox)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: [<code>ThreeBox</code>](#ThreeBox) - the threeBox instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n| web3provider | <code>Web3Provider</code> | A Web3 provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.ipfsOptions | <code>Object</code> | A ipfs options object to pass to the js-ipfs constructor |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"ThreeBox.isLoggedIn\"></a>\n\n### ThreeBox.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>ThreeBox</code>](#ThreeBox)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | an ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n## KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n### new KeyValueStore()\nPlease use **threeBox.profileStore** or **threeBox.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"58caa05d02bbf3bf8104a1b94bb675b6fe950ce0","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib  --presets env --plugins=syntax-object-rest-spread,transform-runtime --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","babel-cli":"^6.26.0","ipfsd-ctl":"^0.39.1","babel-core":"^6.26.3","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","babel-preset-env":"^1.6.1","jsdoc-to-markdown":"^4.0.1","babel-plugin-transform-runtime":"^6.23.0","babel-plugin-transform-object-rest-spread":"^6.26.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0-beta-13_1540308204665_0.49629800801151314","host":"s3://npm-registry-packages"}},"1.0.0":{"name":"3box","version":"1.0.0","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"7b346b80cff6cd2f7549ce89f69e0a114d1667f1","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.0.tgz","fileCount":33,"integrity":"sha512-VaM/dPJ8KW7dXYbEoGc0YKWfQGBuUbrfJDk4/bXNgRKQy/dnVmBLaZn8I/FKiL7wt7S2dPr1rfpW8ak00FBMsg==","signatures":[{"sig":"MEUCIHht0PFp5TIJIb/9f5bn1BmHhiuj4PQQNwgMoxkzg6BbAiEAk2IDPXHPqv7zFGMplkTmQj2P+78UCZJ24KhhFgHJgKY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16602701,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0ImgCRA9TVsSAnZWagAAGocP+wWVddVyGFXSMrz6RgRd\nRAkHAuh/W4XNrT5gs67e2uy94oMcqpcTYl3XaOCu0an//9YrF18z9wgwD4lf\nPCdWNJGNjhdbI6L9jiO5cMf/m13awCiTUD52ALQsY5hp/u40VdbCABFugldk\nxSgpTU/I7xCpoxAk/tX78fL7ju0iRWW5pk1nJYlEaUpV7yO5Lqr7BnYsdw7M\nHpRXYCx96ge4f1ixBGc9907hvHgw2s2wZLGfZgmuqeXwiTz3VQp4/Uhjg67W\n8XwXqlC6m1RU/bQiy9Y1o0W91T1FTNHqXf//dVO7+rOAGFRdbsnSq8DxgEyR\neNumnA+Pgx5vi7GQKa4iYnAxJC/K9xtTicnj5e7foqRfqUfpNYN+33yR9mVs\nI9siv85O9Z1ce6aEKlMUpKTKppnd+p5IvGUZXfvv9StrcHk213x8ICiMY0IX\nz7Xhcl9cA7RRX9LvoVgjyTcqJlCBOY6LWD7AuHHBXDPIenRDKPanI1Vu9VXB\nB7pNiXwEjMNvtX6KmKesv/muibFaMOMpD5BHKUyLczaPVkgtddCqHZ/5uApC\nPRG0xdZ3wSLhb61yhLs2YN9L/huQhiehriaeb10S+GlRWhXeoa2iIhk3qwSd\nsCq6AHNMg6gctMphiJCqf4V3H313VamHYm+gEM0541odHXESuC2kIHx0SiTj\nYi90\r\n=ilrZ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"8be3b04b0ea9fa06e2202a6a6ec860d39160fc12","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/runtime":"^7.1.2","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.0_1540393375153_0.3542933134234201","host":"s3://npm-registry-packages"}},"1.0.1":{"name":"3box","version":"1.0.1","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"fe68ec80886ec8c265198e0938b3d5e3adb95021","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.1.tgz","fileCount":34,"integrity":"sha512-2plDzFL/PK2gnvVJq/ZJQBg9eMIfF2E5sjVR3eroU00HjWeQQFvF9x8T1665J/h70xvropseHVDOlN3TeN+B+w==","signatures":[{"sig":"MEUCIAnsqAWbnH61swhiS5LueDwCrcvy4thQbfonT26Ic+82AiEAulkbocK0ItNZnIOd9WzyR0pCa077B62IraCzhi5+et0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16593177,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0LQdCRA9TVsSAnZWagAAtj4QAJlbAHycHaBpm2w8A7DC\nWtDxJAdSmVcPXaoDORlr/sQYhZq+kFz4cTDwbZMFgXP5O4NOZYhtQmgG63KV\nsEVIqensWyf7r5+McE0UzxTTD3cv09sztNiFSJfwy313iAQ2L4aZ1wXesxgq\ntLKMDU9Jn6t18WLOTLdMZFj6hCEEJFkLrpERpQgz1GCI1MhL7wH+ZtyZdu6B\nkL5KnRVh9hYAOJTZexhwPSOccw8Jysb2AF4eXCJqlWImLo035JKnzYT8O1No\nx8Cp7K+If2FGPrHtbqeFq7faKv/eLJwiM/8uuxVorGsO7nex9KWay0Xyf3zQ\nGokf04OqvX0Yy0cGQQqTx5RdvSgx6krSSXmZbHbBnqrEuyJ0Z9dgZyIyu9Xd\nh/OMc2N2X4fjsCrMgFB9Yzpw8+TAiQY1pnMLwf7h6lkiuGRHa8hzUzVFvRTp\n6kzZML3uOt6Euqm0U5uBCnAKy1yiSGjZYUn6fm7QticA1WBukRwYUO33BY8n\nyyNpPs+Zra1DDxA8az7Hr4NyuhsMO4LLdAbJHUxPqOcvV2KJ5W79fb53sg0G\n9btAR11H7DAx8eHw/fqL+ZyBt/r7ammy58z8/vxSF6Lb8I1YfOOsGl1yo5GY\n8V2PfgFj7LNBZrs1ZH7tfcG+Ix964kIYzkYo1MnBYvuOu3q/PDS3660FyVos\nIgFF\r\n=bTyg\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"7b69454375f67fe4efa79babbe893a5cd6496cbd","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/runtime":"^7.1.2","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.1_1540404252063_0.1831121378179259","host":"s3://npm-registry-packages"}},"1.0.2":{"name":"3box","version":"1.0.2","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"92aa301980a5bba7e4a9ae951b1052d1401ac882","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.2.tgz","fileCount":33,"integrity":"sha512-q9ga5sfAWYVdzyDIcT4ziO6mHXAbieayQfr4muVlx0ClOqyqarBdZ9uPqF1AH+LDEuBPcrh4k2KF3d1qkdOZWg==","signatures":[{"sig":"MEYCIQDv/f93evuKCCQqKP1zXLzo7s2gJZgCqN6JkHd9cjXPxgIhANSXmdn+Pe4j6nifRvQuxEjkvLBmyAC4u73nLDFWttne","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16588451,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb0ftZCRA9TVsSAnZWagAAHPYQAIsqxc4AFvycYvsRksX4\ngRYhpil/fd9epUeWv0Y3GuO3ySJ1loGsYUcYqWVrbs/9LBuqOBVx7ywsE9ty\nWVmmeAryZCZ8FypJHuKUUMeHTCdGQEe3nU2j/LH97+wEw1ORCvv7tn5KA2dj\nM8wrwFfxc+OxDZAf0XscjGwmRmFzptqjEQO0c9V+eSt7AXkVRLDWn9b8CP3T\n8jw0pmTzKgS2ETA6f2nPhekmDOh0ZShYmBQhF15qXFdph3YxB0/Ls3VD2JoI\nOGSG88GalcP255AVO9XtcgZO6457H6wgvGB+qBHr6icRy5YfxWne312DUi8m\nwlCbSoTaoCnPkNMwhH/dV2rDy2Zecp7Qa6S0qTL5xGtFAy2kgr/lb75+MuEE\nG2FQUe/iT8Qx1KXX+B0uLqxn79Nup0Tps83SEc2mP++naf5yslNf3Y/GqxZg\nC5uLP0ZWt1L8YBc2JUfS3nc+lvQbIn9G2qdDr3U4EYGi+YcWvNwqyvgYG3zY\nGxD7LI03yYAXaDId5TtrdpcxsMxdFPp3jBXP7zDRL5WI2xO1H0DILQst36pq\nIOYTQVaE0xzx8m5w0eQuwRU3dg15O44MY5cg48n0KdTb1xC5DMye32m1D5p6\nf9SHb99TjvENju4sbevKvF4T/uvtwYwR5dnBs0/u/FyLGk54aeIQdVHF2mk8\nTsf/\r\n=EI6P\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"0b21ddb3339790628e9f35266f84f9b5d68d2219","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/runtime":"^7.1.2","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.2_1540488024287_0.26229288890935876","host":"s3://npm-registry-packages"}},"1.0.3":{"name":"3box","version":"1.0.3","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"e76d348a3fb11991fd25046d324088d013cfae23","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.3.tgz","fileCount":34,"integrity":"sha512-xdVRjE6ltdd2BQ4d5zHUi3cBP+mI4+bGzuqNvzmjlXS6RuxBqOeLG/4K2CuAoXDoltG6GyBFTNTg4jzTtBXkzw==","signatures":[{"sig":"MEUCIDrvUAjp0O4HHtKMJjNYcFark/uLfSvcKvFAYK1TUHXiAiEA0XvlRdZ1kR22viDGjZ/bd5tdZevcP72yMOhvHYfgACM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16589083,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb04vqCRA9TVsSAnZWagAAkIkP/iMfB/YXK7oiMNsPSvQe\nAzc4mqEbqHvhJvPfk1PctRTGtMoMZWb38ge84rEcSM8Xw4kg/BV9K2/Z48xx\noOH0n50Ty+X/EMpzPPpxfBnj/S+Q1cY5e/yVu+AZsgQtG/H0/jZF50+4Jie+\nwA3PTJ+cyfE3+cuDPtqPcC/d/H97szeprQ72nWcyx51cy18OfBR6fdI3BLe1\nfHi8wnOTNC3LzIm2/zvuKdr5A2E8D0+4ou4MtRi1S3QU+XCThIXfb+XwdiaZ\nJaNADZi/4IPDv1lvlyDjRnW+U5VlmJDkSwEyVCCeEiWHMVaHINL3tWlcavHa\niAZpuAmifQmekdCjHbBKloQUKynGSSLdXuImMxrHwNZNDn4AjxxWAo7LckR2\n9t6vUQ0ArRgj/Wt7SW8hIkzMWUpgKmq/NmavwgFiwHZFhNqIL2Lhg/1wqM0b\nZHv3wo84gmE2L0ch44jrjNn49EIzhdMp8Us3H5bygJIgZm8DfLYxLGaa+DMA\nA/rQN6IocwTJq3BbGm7OTg15BA2ZVStT1lkON5dzDzcSBWS5rd5PxIrMf32+\npXq/FqhMaFt7RgmpXlzjsmktLNmPer89YiEJ0wJCnM8+bU01kZSrI8xSNcm/\nFb1rullIFu9jYGVGGUjvgE+j2h15FIUS+v1rvlYHTVh/fwG6pxyFP1A27/aA\noKly\r\n=SpmV\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"ddfe78718c2c0388231e12592d1796a21a50c095","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/runtime":"^7.1.2","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.3_1540590569640_0.3297369670302208","host":"s3://npm-registry-packages"}},"1.0.4":{"name":"3box","version":"1.0.4","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"841a3cf0bb97d62534ef4e729111c6cafe94a87f","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.4.tgz","fileCount":33,"integrity":"sha512-1+2ISfjqyZbWHhjje2A5AODGQNQoPQTkInpWYqr+3lvT0oS9P81rEnGswGfTfiFSx92KP2+nHdLp23zqPUNvpg==","signatures":[{"sig":"MEUCIQCsXdAeqjJ8YCIqDNu38lUGOlWMjWDACKBUa4egnKf7AQIgfizfBN8/AGeflz6Nc3tkOiD2kDkuZlDVmTaka+qYn6w=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16588914,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb4InUCRA9TVsSAnZWagAAIVIQAIQ5dZynV/Beh3AJd8qT\njeBk4qcaf5PlCrlLdxgBN9SESm94E8DUeG2FbRr5IzS5WsFHk3xh4PrLYucf\n+z074xyMxS6ThcNm3BxnJ3WZyton+FhllbeYb76E/ybY34yAW8Ih7MNpGMyR\n+RnVB9YJ4h3W3EIetxBZ/6yMDeYipCN05hPVMeLey8ZbFekvPaEhzaRoIOi2\nmuiwIdUzg/aZuMkkCE07+5Ufved4IL7E0wNnkUuXvhh70VXMZwyXeYLpCczj\npvOaEmI8zbTr9gJ1xQIoM8sPJ6qF51UMjode/4AyVAKdkyz0auHBbV9amK0s\nKd8nEBuXWmBs3rhxKvBnT2lqqZScFjKxK9QP7jMvuTsg2cNhpqFFyjvomdlh\nYjFUy5Oxklrgeuo1Nuiaybyu5ujrTCfIN2yCGWB9fRSn/K3SnZUBr6M7YfFr\n5FcyO0Vz2Dq/yFBjygGEC0o4CEiuoPJmn2mlZA/7ZP9/7BRB0xoLEd01KA2v\n4Cml+L5zysZOAvRhBCf6O9/pOuWnLT/GD3gcpSLf1oI5DxrRH9xAVuB0dXsF\nyIocWVKTRwaLF//TWfNo/WkPsdd547SEr0lbp6DG2EUNhhmO8bl/GencFkt6\nipr0rQLaxnF6bzc9fdK3nEtXtxCW8y4D6zAu3acf0HxdhPo32iYDSnXjdEHi\nxHG9\r\n=pyAJ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"a2909e6bb2f7a3bcc29d54bb967cf1d75b0f9b32","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.4_1541442003586_0.20987029599473517","host":"s3://npm-registry-packages"}},"1.0.5":{"name":"3box","version":"1.0.5","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.5","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"20cde542482b69c462e0a74169e62d94f76c4087","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.5.tgz","fileCount":33,"integrity":"sha512-g49V0FAocqdr/DioJjzOS51zKxt+oiJIsLAdKobkcSyrjV/2CsKl3LZPsHwOI2OqDpwuTw5LvQmvyDkH4TBVNA==","signatures":[{"sig":"MEYCIQC5ZNEKQuHJsjI509/LzgNcSWmlH7xD8swuuwxdml6p8AIhAKjFQEPxcC2XFDgX2o3FY28vHnLz8zzPY9VytluviI/n","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16590088,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJb7ImPCRA9TVsSAnZWagAARRkQAIoqF67+BdQaz/WBuCh4\ng1nTC1nQdBxXXyPaIplaICUHdMbGa/K1glrm3lq18NDGnRAcUMrvfMKSJ/8t\nu+NUKLminSOI3kXLbVUGVgcnY9k8oMM7HII4BQ0MrX8f8Vk2ZH23iB1tjbPW\nstg5TtEVhdxItxCoKsuwglbrHvuFik1+Z8/c1eqcg6jIz0IJ4XBQAYe+pDvh\naXfBsgkZZ2T6pPam1seW4qQCVYMYqVMxCyaQbY3fQqc18b4VGxP08BmpbhwB\nQAawPkKCnHLk/eI0eY23k2mODV4jHJ5RKNI6fB3GGUPVNZspzSH6KZ/Om6RI\nesGEYJ40e9ETFHasJxzzaJY2oQ70YGv5K8E37HbuRXEijBgjXPSX64tcFoKW\nUqleM/WPyID85lhv1Tnj81LwtZHIGpjRpviSJ+8gusZwAfECyCWkNucPctUo\nB6nFat2WI/7ozkn56dg7mYCmYi+XIGun9I/HktkuHkHyoVxvpzO4V+YjErt6\n6EjSsN0gA0L2vHBaQP/r+mz1g0PBL7i6LqKqNlV3vkxG4QiRm3gI3UGEPmAp\n2emrqI0cwYp85R1/l6hIvTGGv8W4LIxMmxCcvHkHDn+ydYU+oCH9W//Q7n81\noe6e4aZaiG0okQwUDTd2hkMv5O5vJ9/tNHpCd5ARUB5M+9s2Iy/2AJU1iu24\nDh6X\r\n=HXFj\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"0df3849cb9db961daf6f68457a2a2ab80bc83ea3","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.10.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"9.8.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.5_1542228367003_0.8489837390732486","host":"s3://npm-registry-packages"}},"1.0.6":{"name":"3box","version":"1.0.6","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.6","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"8281605afdb74dad8b243c2f5e610d642757e3a1","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.6.tgz","fileCount":35,"integrity":"sha512-0IkTW9rog2YL8YvKR4PNqyfPg1wfWSxn9HytiykkMs9ftwwK7umR4h0pGsNwZ4LCJCiV1Y0HFfXEevnjIKQvRg==","signatures":[{"sig":"MEYCIQDGw2aUPGwp8lJKWo4iK71rtT3yYqQEoJC+FXHDVP7pngIhAPGsbfEtbJIys6jJXiN2/X8e/zmIdD1gm5hFU/BR5VDN","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":19508784,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcBsTeCRA9TVsSAnZWagAAsTUQAJe9teOPKZzwvz3RU8gt\nMVyYfVqGQ/SI5o6u04cHRP2qvM4+geTc3cF3Z/G9DwR/B9jO2GmVlKvytXAX\nX1meWrEyV0gfneU1iMCuAJlJXhuWQOHttyimfYTz3msShVPP5oBTn3i8oq+5\nQTQglU8NkOBHxoOirZVmamQOTdm2UGcOpBBL51r7pVtzJH/Wxw2UXRBNo3ZM\nYx69lQnL0lV0p+cG0PLlH5eEWUKOp/FaJkyIDVX1RzQR58dxoIYqDJhs72bC\nces6GJ2rFly7+7FtpewqXfSf0iCCoW8QGBKDW4o1JLmRI7VvgCQMJz2G1a4d\n6/4Fom50FrCMe0Kci39rHhb2/3/mPgTx7eftFBVA+0sWSghphxjuiQLY6D2k\nIhj8kInsqrcLfOJ+pP8nSbIJuGe0YDFdJyZeawAzxtnBnlcUp6RlD9uGTaYk\nMX7VBvwWDOfO6wtB0VynC2yuE8CK+w85G84tQrWdQv/F5+pm2JhFS/F7442i\ngVfuXJpDIYCwQQAF2kUy3zmCTjBjd5SBFnl9rw/okEaiUpcGkcWsU5vqoDTM\nl+Kc+zlhx6QF2sfMex+OM16TUN9QI1Y6U9dIUvI/U3CuaDRv+Ff+WBxHBxs/\npsUveoF+IBp1saSO2hiu/SY4yhaE8PBgey3Xpxt5ZnFdotv6OnhwOFOaaKLR\ndVOn\r\n=XUj4\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"c22a28cfb1c1bfe79968360e9d3b2a3addabddaf","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.10.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"9.8.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","ipfs-api":"^24.0.0","orbit-db":"^0.19.9","js-sha256":"^0.9.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","xmlhttprequest":"^1.8.0","ipfs-pubsub-room":"^1.4.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.6_1543947485587_0.7699505435007068","host":"s3://npm-registry-packages"}},"1.0.6-beta-1":{"name":"3box","version":"1.0.6-beta-1","author":{"name":"uPort","email":"team@uport.me"},"license":"Apache-2.0","_id":"3box@1.0.6-beta-1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"1f963e88fee94f457cd773c631dad5fabab0d8f1","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.6-beta-1.tgz","fileCount":35,"integrity":"sha512-5iYRNMbSwssxyIWxc6brOX6HmYgNN9a6jIvv8ZVNgsgrARb2Eb1vBcR43pftdiH2bOssOyYUPw7PekKRV4DTfQ==","signatures":[{"sig":"MEUCIQClCD12xY/CIOnVnsdtPET9dDXkxeRr+zzJRzDN1V+gegIgZaM4Bl9hs5QE4Oeiff23gGAK8SMQYGohOhJUocCZdRI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12135229,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcCAmeCRA9TVsSAnZWagAAmGUQAJcq6ViGaLU4GInTKxXP\n2WunbNA5bmQS+mVbTbwX2ILwUaZCTCal9XXdycPWdOLiTCyViemswzxRwYuq\nF3uLDDbLi5+d3TYQdGd3NJI69jsOH/nKilK7a+nyrCYhrg440TXFu4KxCezg\nou1/e3ZV+i5KDCG/O6kEyW6inWTzpzi7iMsYaz9HgTtujGhIywlZXgC1otfZ\nyBkKglwaIV45aYo4un4BbSE3zeqZ5YFkKdiPSC+bV6uhyldD9xz8+1ezQSHA\nSy3yjGBAxVJzRSVIZLuheqa+UNIAT5gDvvoqJMzlMkHoCMG2zGszAmDPr2ZA\no2iFeMEWEgS63VnTwGOAdginyI/8zxCQksljyYK1j5FWD92i12fibXunJjAT\nA0DdHHWK2jyk5UGpgE0tBEZU5EBfjgcLxfY77eJt9bdoQWvZu7xfw4HREwTi\n+K+iT5uxjphgMN0CWcOfEK0VqyeCI8LsKizrQKVQiuMih9HA0TZe5xij8eGS\nsk8gtyaXzpvZdmAry93JW//WZKN9RjDd1zJ8knYnncdbLKVHIBM+5Zu7Pq9e\njYXfxrpsAS9V6Ypgf0/2Ecx8RgvLeTboKKIsYbkhnFj4UWsvf2QvIuV4hSju\n1X9Zxxgq2PjEFf/rk9XnMGZnpornZ/j7jpZAi/dMSUTKKTxohOA+bNsYQwts\nNia4\r\n=7SN3\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/uport-project/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/uport-project/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\n**Warning:** This project is under active development, APIs are subject to change.\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nor use the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"f299461f640cb5253db39216716d3f9462631df1","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.10.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"9.8.0","dependencies":{"ipfs":"^0.32.2","bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","xmlhttprequest":"^1.8.0","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"0.0.4"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.39.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.6-beta-1_1544030621422_0.21032784732946674","host":"s3://npm-registry-packages"}},"1.0.7-beta-1":{"name":"3box","version":"1.0.7-beta-1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.0.7-beta-1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"31bc238f72a3e716972aba21d9e59bcbe09a2de7","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.7-beta-1.tgz","fileCount":39,"integrity":"sha512-/Lpe2udpNnFvkteah4EUuSqxKLDgkBfePBBEG+okEbtV31Eytg6j/zyqSsugvCTs0XhGgQz5eVmLBXx72VMkiA==","signatures":[{"sig":"MEUCIDxOyxpuvffu12YwG891sR/7XzrfSVUNBO1C/BGmucZwAiEAuDEt+iTqcWML+SkcmRtyDcIasLd4r9ZOAYXA2hvhtno=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":6645995,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcEhk4CRA9TVsSAnZWagAAyJkP/jFlHTvfm3Mu8IXCcIn/\nBcjeQ7y992a8yLLLg+8fHQyqgje/jzFV5d+c/xyLA5HY0ECsGPw/I2/yaM7z\nmh+sylpH3Pa7ZpC0XiVGuv9Mhp7VqdGUJJ5JuQntwDINPrCVCegRpMwGVn5P\nDTfwj/1lxEh5q1QkHsp1iaY4JMm5FDXA/JIg6HZbcjLTVgQq+ANjFhORTMXV\nZXQJYPNt/XRiRjdunK/O1obXpGi90aZzhWPJBK9tBvGr1vF84ruD+dGVm1dZ\nPGVKay29SB3W6JnYnznkxcPsSq1razYPiAIoVGPeTU/sW6nAyxlsXlJcKmf1\neY37lGWlKppn7j3c3NALnjezPYvOG0gvTnGj8+c6vWCyZ62rRyXhJC0vq0Pn\nfPIm066eC6GM4y7+iq6122unHXu3TJPzbbhSerMqb+Wni3KlwTMQQNN6orpv\n9pBWgF6Ef72l1FkrqrBU04+rA2Mmn0EEaqC462I0hF0z6DksF7gHZ0iK+TCZ\nZNQv8mJElXMCLxJYdQyP4UTnk3CzPj4xfVkei7XPa8nt30YT8zg5EltKC1s2\nCsxYpbcvMflHfp2VfU5m9J5YouIIrUsagN6eoTyGASQrXS/QMBs2CBE7TCuX\nN4uyIabpc+o+7ubxfStndhPMBR87iG/4BkbsJqVwgVBRa84SguyNO9t+0AQK\n3dRE\r\n=6MgU\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verifications</code>](#Verifications) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verifications\"></a>\n\n### Verifications\n**Kind**: global class  \n\n* [Verifications](#Verifications)\n    * [new Verifications()](#new_Verifications_new)\n    * [.github()](#Verifications+github) ⇒ <code>String</code>\n    * [.addGithub(gistUrl)](#Verifications+addGithub) ⇒ <code>String</code>\n    * [.twitter()](#Verifications+twitter) ⇒ <code>String</code>\n    * [.addTwitter(tweetUrl)](#Verifications+addTwitter) ⇒ <code>String</code>\n\n<a name=\"new_Verifications_new\"></a>\n\n#### new Verifications()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verifications+github\"></a>\n\n#### verifications.github() ⇒ <code>String</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The github handle of the user  \n<a name=\"Verifications+addGithub\"></a>\n\n#### verifications.addGithub(gistUrl) ⇒ <code>String</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The github handle of the user  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verifications+twitter\"></a>\n\n#### verifications.twitter() ⇒ <code>String</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The twitter handle of the user  \n<a name=\"Verifications+addTwitter\"></a>\n\n#### verifications.addTwitter(tweetUrl) ⇒ <code>String</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The twitter handle of the user  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| tweetUrl | <code>Object</code> | URL of the proof |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"b00b5d9524d448d0ca8e4aba480d50ed6be11af3","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","xmlhttprequest":"^1.8.0","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"0.1.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","uglifyjs-webpack-plugin":"^2.0.1","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.7-beta-1_1544689975698_0.9432046273526298","host":"s3://npm-registry-packages"}},"1.0.7-beta-2":{"name":"3box","version":"1.0.7-beta-2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.0.7-beta-2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"219f7c3efbb914871f42cd1c557906cb8361c0a3","tarball":"https://registry.npmjs.org/3box/-/3box-1.0.7-beta-2.tgz","fileCount":42,"integrity":"sha512-+agjBrnkWWNCTmIxyG3z/xHTr9vxBtsDX8K/KvDghwnXtjw5At1moHKvi85RVugHoqVi4/OGfO7ZfILqLKZGOw==","signatures":[{"sig":"MEYCIQDV+HmDelQRbxfFL241vZRe6Xb/qTK6FWSXn4lYt7SZeAIhAN07BdmQY+IED9lGlS1/3eIdYysMBDGtfBlZXD3rPbNJ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12119428,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcGUwvCRA9TVsSAnZWagAA30UQAI6mJjNil86+NaMdUDrS\n6YEV6RgB19smasGt/g9LigHALv12OWGHMeePeekawKWaVlQA07RuKQBfvk3m\n26JdqY1l/hae+ybJdpHkthyrROGsua59Xlb9ThYnF/4afXWMNP3Ei9xHKp7e\n6q3Ppy9jDzpObABUxZfm/RDzQexZElPHXfs9nf8HA56Mjfdg/GmLof9goyhN\nIR2BmEUQ46i3rlx9pgPWruwy8CjFbL3se/E9+Eup2jfTVWySdtFcBXEJwHep\nqzaqRlu8WWxX+2Ja3FmwPngcDMMSvt5s77zU13vzmTlZX5k5HVxLt9j7ft2b\nkuRWQ5tj6eMzHjsM1zSBg0YO3K0HioRyDsGPlKU0K6lDjemkygvpPbo2ofQ7\nVvo0xx272PgZDnw3jq5BHCmQfMggt1cVUha4FAyFgnvgEU1Z3nMZhlRF28Ur\nfnyRhpEkmBG75G7yTAAjV6RcLWfwLILHxE5etVT+r2bC1mdG35LxJ0Acf6cy\nV3srHvJTF0ysMZI4Ggv0aSUunPzsh7xXFk8mhM8hA2CBhwqeRzZnmT2GPbNr\nBgZ6jscEpbo98asgfVSDhb5B9jqBEFukMRpZvwImqzQ3XYduZwGdYB0BdOps\n0bNRH159d0UW9TA8bpcmCc1gWB+5xcA8flFAKh4iFxxAbZbtoeyrckiJEY9a\nodGT\r\n=VK0G\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verifications</code>](#Verifications) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verifications\"></a>\n\n### Verifications\n**Kind**: global class  \n\n* [Verifications](#Verifications)\n    * [new Verifications()](#new_Verifications_new)\n    * [.github()](#Verifications+github) ⇒ <code>String</code>\n    * [.addGithub(gistUrl)](#Verifications+addGithub) ⇒ <code>String</code>\n    * [.twitter()](#Verifications+twitter) ⇒ <code>String</code>\n    * [.addTwitter(tweetUrl)](#Verifications+addTwitter) ⇒ <code>String</code>\n\n<a name=\"new_Verifications_new\"></a>\n\n#### new Verifications()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verifications+github\"></a>\n\n#### verifications.github() ⇒ <code>String</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The github handle of the user  \n<a name=\"Verifications+addGithub\"></a>\n\n#### verifications.addGithub(gistUrl) ⇒ <code>String</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The github handle of the user  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verifications+twitter\"></a>\n\n#### verifications.twitter() ⇒ <code>String</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The twitter handle of the user  \n<a name=\"Verifications+addTwitter\"></a>\n\n#### verifications.addTwitter(tweetUrl) ⇒ <code>String</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The twitter handle of the user  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| tweetUrl | <code>Object</code> | URL of the proof |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"f3c1101b45072205d9b12808a89f2b272b0730be","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.10.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"9.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"0.1.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","uglifyjs-webpack-plugin":"^2.0.1","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.0.7-beta-2_1545161774409_0.24813541790339388","host":"s3://npm-registry-packages"}},"1.1.0-beta-1":{"name":"3box","version":"1.1.0-beta-1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.1.0-beta-1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"983094fe76df97ec7e7b57b972211eade53ccad0","tarball":"https://registry.npmjs.org/3box/-/3box-1.1.0-beta-1.tgz","fileCount":42,"integrity":"sha512-CHMssTLRX1dRqxt9WoslMZT/LVxiG+ZKgOs6tqIERwCGOR5H5y9dWnlzT7TRFRGRdWakLGFCjVFS4Cpo1+XTEA==","signatures":[{"sig":"MEYCIQCwmjBm8YJFDEeNm7hrZ5Zruty1iqG0ERVJR+OK28x17gIhAMe++BlwsCSsLxPMcRVu57IA5P02DY5F2Oizn9xIqxsw","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12109572,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcHChJCRA9TVsSAnZWagAANlMQAJVuqVY8E5e+3hP9nwVR\nS4LisPst4wwSZJ6WTjG0TUzuEWB5GMlWlbInxYyQChTWfGEouu4u9h0ZA3vj\nkdJSk7/hCKbE0oyXRDQ8GBhvxSTnNiEUPlAIxZAtIRz/Z5RCceeYh1UFCNXE\nXWOnX2Ik75U2I+k9XnK9o2uMFs0CpX4hO7C2lgOeRsa3yf6ik/QDP7rHk/eq\nazFa4GYC0WBAnKSMFOOw1aVLyAHnhuUGGviY9cImfVqU1kEs+JHFM4CsHOhH\nBiO6ZsaAL0JvUzxwRCjvQT9F3Y1F30bfM+SNaMVBlbkfoiRYiuH5t/uO1j1b\nLs+USR1UgG1/BBe+7CyahzDHLHkSDmihuAx3JwuCMc//4ACCgyX4v2TWNCap\nj9YWQUurZoGZJEQmuzoT/2U9nwRtI1mJuL9fVbYT28cWdXV74a3ghgWILenT\nNM4vZM+yiiOgafso9ScNCTwTSzgo4nOHYvIjrBVOsRBVS++7++lg7a1HHI5X\nRkP+j41UBjVhxeJARZjFBGFWsReHxP+GdfwkQZPZcp1EzL79Pc9iJ+LO10a5\nSeDCy+WJffKNzbLG6SozUT4YuL8WAp/+dMqGTbiqKCRdNOU8jF++38EN07+Z\nb5ssHDnvsZQePGhyNXfDmow1vSw/o6TknvmsrV50VVFC+FIQnKSvkhD3mdM7\nhT49\r\n=utLA\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verifications</code>](#Verifications) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verifications\"></a>\n\n### Verifications\n**Kind**: global class  \n\n* [Verifications](#Verifications)\n    * [new Verifications()](#new_Verifications_new)\n    * [.github()](#Verifications+github) ⇒ <code>String</code>\n    * [.addGithub(gistUrl)](#Verifications+addGithub) ⇒ <code>String</code>\n    * [.twitter()](#Verifications+twitter) ⇒ <code>String</code>\n    * [.addTwitter(tweetUrl)](#Verifications+addTwitter) ⇒ <code>String</code>\n\n<a name=\"new_Verifications_new\"></a>\n\n#### new Verifications()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verifications+github\"></a>\n\n#### verifications.github() ⇒ <code>String</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The github handle of the user  \n<a name=\"Verifications+addGithub\"></a>\n\n#### verifications.addGithub(gistUrl) ⇒ <code>String</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The github handle of the user  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verifications+twitter\"></a>\n\n#### verifications.twitter() ⇒ <code>String</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The twitter handle of the user  \n<a name=\"Verifications+addTwitter\"></a>\n\n#### verifications.addTwitter(tweetUrl) ⇒ <code>String</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>String</code> - The twitter handle of the user  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| tweetUrl | <code>Object</code> | URL of the proof |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"6662bf6f049622b5d3ff33f4b83f72bd531ab601","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.10.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"9.8.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.1.0-beta-1_1545349193174_0.08337657342904436","host":"s3://npm-registry-packages"}},"1.1.0":{"name":"3box","version":"1.1.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.1.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"398a4cb1610d6b4b3ab2b5ca9d55ffccf31ee769","tarball":"https://registry.npmjs.org/3box/-/3box-1.1.0.tgz","fileCount":41,"integrity":"sha512-AoOOBklWS1fO7wVUMkS74vx8mqeiV+Zufiw4co9DZbArq1GIaakurmGPriONcsDECP7YpI1tACURo7yZf+xwBQ==","signatures":[{"sig":"MEUCIQDQ+HMahbVf2ShVPiTd2pFsT6LkMvrF6FwIEywZRJvPKQIgMZJEgV8vTt9hfAXsvgm+6vJ5O0iHOmiNW4624coIadk=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9192443,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcJK4cCRA9TVsSAnZWagAAe28P/16bbMmKVR8vBCdF24Xy\nEWimRjuZf193OqhgZrq/8J7J/1IUUqJaPku1xVJoJirw72L6TDXCREh2XMBF\nObzvKIYilu8ZtwV90F1h/94NFFdJG8MfJm+14YVYeOBvLsrLT8YZ2VQ6bdUK\nY/LjOsizfy9SNzRmlxPeqkkneZnHDKusLs7n479RF9Usp5wa8nOAtkgcaFLi\nSmRrz2tCpDE+O6hUo6reevzJSFqqTkP5henJ2ow1UVlC0eY7BqYWr34lewwH\nHRateRG5VnkOzvwv2AJ3HswECZ7zuzC4a/+3vgU0jZKa1cBW+dR0pOC9ChlQ\nAq8E9384Vw+g/RYPpe+TiOX04R/Lr99fHEsCdzxtezu0084xJTj83G4+tyTO\nYZdhqyiPJOesZcz/VuECJCzAyrx9xXZBDa8qu4w4dQkxcSxfHJxI4EGdO4La\n88jnBmCo+YhW4wqI9p20B94wp3igO5ofjxUzl1CYFGbsfzFzkkqMfHH/X/6L\nz1ivanuOQeZ+QvyOIR12tXJDdaJV9lHKkVg+DjJUPWETevz6KWJ3FcqKn8GK\n1cxPxCjz/0Dqo20OtIEL+2o/mXnMhGX+XrDEBVtTK4uEsj6LjnueEIgCPM11\nnZw6v8GXVOAq3u3jaLdkE59uK8PMp3fQHykyFa1JLJrp9jON8EJZ0sZBoUM7\nECJu\r\n=RgDW\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"c64b8acbf32a7205a4dc44a90e30b3bb15f52c0e","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.1.0_1545907739935_0.5648292790321057","host":"s3://npm-registry-packages"}},"1.2.0-beta.1":{"name":"3box","version":"1.2.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"c7917e5be0e7af996e4e7545e14436f2b6dc4a1d","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.0-beta.1.tgz","fileCount":39,"integrity":"sha512-RcslyCJwWIJaJ4FjD2jhZuaVJX2iEVWhSQK61VrWlXdcnPG44hbwrGWMtLg2iEPcrfXJMGoxUlgERApEypdYkQ==","signatures":[{"sig":"MEYCIQCHVthBKEwx1JB19JJkoEoVaMquGeqqbAuNGW3zL1f1RgIhAK4FkMwVznQmScB0u7H+mpTspBmZ/zadH7Ohb+EA6Xco","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9013792,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcJjmwCRA9TVsSAnZWagAACoYP/iikn7iPj/doQZpuP/6K\nQm86dXUA5XHGhnhpxaj4k0XWvvPgot+NvF36zouJZBSIkalqZjDryOjqMWCQ\nfVbA2m5FvtTDPlf4R/vMEKMSKbd5Vk5nTsCwn7vhMng17vrtE+1ggF2HerDr\nRx0QWxUApd/hLE1JNUhoAUaWQjnf/wBsJM4PQJlMXkH5qA8alovVsbj9PVS7\nbnQpy8lA+1xMc1pelWV4ffLlInSMWCS0S7YF5LxDu3X1iU7gu1czLDyEdW1O\nxtOwb9tC1RWnv8LWpLQYjE0Euzmc7gpMghySKrCYDfQ7xyZx3/IpkSLRtGcm\ntiCytO4UXlx1Bqg/lzuqojYRo/eX18CGKfW18PymzS5ce5QXGhe9zNDbKk7M\naIScidho8zalyLnv9H0X3apQ9RTEM6KGJMVFt52jAMy1r1OyUBB/cEkeCNc0\n6wx7n3VY8G3W33LYmC1GH6BUvjGcEdVBRV0ibTOD8xELIZhbA/rWw+V3RlPo\n9AIF+05Vxysnf68vt2YzePzGBjKsX98EesI0SKS1i0wuyPW4aZy9wIlwU7Iv\nBWvzunCxqVPs5DrOCtp7H28yRCRLUrhfXVcvvH8VgTWwZj8Vr88RjFM5x0LL\nGVTx4B1//442oGEl0NRhwC9FQJFEK1GvBMbYANEeZHsWX8DG+5DYAX+u0RS3\nRUth\r\n=u0qZ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"b87ae45587c88fe1b999454a3995bbdf778ad44a","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.0-beta.1_1546009007772_0.002697525196152517","host":"s3://npm-registry-packages"}},"1.2.0-beta.2":{"name":"3box","version":"1.2.0-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.0-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"9dc6daef8f840296e48535319de83795345fbadf","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.0-beta.2.tgz","fileCount":39,"integrity":"sha512-c5X615VsaBEJG1DJD291kcCvq/Pcz5acZth7xzAutcbs6+IKH2IA59o0DETGxxv6PAYsadDxBOPexCJ2KBU23A==","signatures":[{"sig":"MEQCIEsmD1qWqEIwxwXEPNnxbnCPFeiwc/lJAUrOgoqquO60AiAcFQ8Jr7jSyoZyIkTXjr2cyGCIf5N7YfK5jUuy6oomqQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9029906,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcL/e4CRA9TVsSAnZWagAASXwP/jdcCCDp44ij8onKiGfi\nvJCgPooM51d8etuLkh37gcaCsDnCuYIzGqkVtcODBiAJ1zDwy7AHmZDdYzWd\nidyT0cG7gO+bOdfgLNAns+5XGNgrM6YriF15GnnjlBvKJNWD70Dn9JVBPjdb\nYIH56pl45j9OLCIoIIrVVyE4CDBLYWwbfhWlnQXh22PNEDVUUxLPlVrA+cQn\n3SUT6W6gW/+w+tDHtpqwmcJtT/pWUTlMnLh8VF54XbtdQl61tXdtlVKvu9x4\nAwg9GdLXJLn8sWg8+iUGfYFBjy2Y/dN9yOmGMKh4Gc/duT4lbypo20bT41Ji\nochHfhWGyZI4kHmNC+wpMxopwIN0OmXZuFEljIYVGFe4lOu14chCmac6VUDI\nsk9sSUrz4vN4wgq0101HIEWjzG3r9DepVUrmXYuQ6Oc5C3Ym7u4yDp2iSD1q\nT9aUzqYpjZjnK101RO7xSWZ3LjyJVdHjVua+ckrdC68pBZ3kqNL7tLSF4Dgd\nLHZ2Cg1vaJf/4j6MHLE5jGZvUAqz6wHT+NioDmtt62YAoRRozhLoxjPip7ei\nZgEi4RfRupAPoF+Vou3hFRpFzlEa9YLC9DNQD7FlbcOun14yl0UDaBVVDpkD\nEBcZLFKNokP8yRD4JqBYUBAv7O9LSzxs/Agotgl+x1OV695uHgkhzJoDov4G\nm7eO\r\n=2YUT\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verifications</code>](#Verifications) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verifications\"></a>\n\n### Verifications\n**Kind**: global class  \n\n* [Verifications](#Verifications)\n    * [new Verifications()](#new_Verifications_new)\n    * [.github()](#Verifications+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verifications+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verifications+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verifications+addTwitter) ⇒ <code>Object</code>\n\n<a name=\"new_Verifications_new\"></a>\n\n#### new Verifications()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verifications+github\"></a>\n\n#### verifications.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verifications+addGithub\"></a>\n\n#### verifications.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verifications+twitter\"></a>\n\n#### verifications.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verifications+addTwitter\"></a>\n\n#### verifications.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verifications</code>](#Verifications)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"18a68ecbd331ba8acd583b6d4d2c20349ea53d8e","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.0-beta.2_1546647479265_0.6571201884157944","host":"s3://npm-registry-packages"}},"1.2.0-beta.3":{"name":"3box","version":"1.2.0-beta.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.0-beta.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"bf9fc350e35612c5c6354059322031cae40b2044","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.0-beta.3.tgz","fileCount":40,"integrity":"sha512-uSgdqvexHAbJYsKbKZQkK91w6C0TOB1ICWeuQyRrCY9+6mktWj+D1abyDimBJxzslywuAYhgmbTpl7wV9KW+EQ==","signatures":[{"sig":"MEUCICzqOMZMf1T7PyxgSqkwNAXh4NwiWyTBD9LOhJqTwxWXAiEAlhiNJ94dy4CWTdgkAiwCIwJ9PId2/rh7JzWgVp9GwA8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9036825,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcMKZKCRA9TVsSAnZWagAA0+YP/0AupVf+tcTj0nuHcM0U\nnbMcpbgfUpOLYeL9dRBw7rRdHBAQ8YbY9eISBbZW6/mOEHKVpEKLPjKlzK3k\nl+dUjxXsFUQPGXQzKApW6BGmhYFf5f0gkM91yKSvjNhQMv2E1ILPMlXJm4S3\nvpX1gSq4ADEOmEueddwlsmYMUvr1nyMQusdSY8dnowCmh4N4Kah8A/HVVn4a\nLGnx3kFy2jQmOIotOnNQc3wvP2oLg8dkhF7cz2+LLlE3rX5RgSfuXOz6Zr3E\nW40kVWGwk6j0/iEu7nW6fqgbpu5JiRnTLktJNOqJ5xK28pG7xc1O1ASemxSm\nIWI7fRXuPsbR6Go4J260KlalYDVtdCn7oUWupolGDD99OxfGoxU0oZtw9uS1\ncwpUAyhCNjO6ywPgPftEYG5NrRRE9E0jUJQjAcoxBmRRr5VLIoc8Z5AFRUmV\ngnf4DbQGSV9M53p9+8LhgSAcDySHLCLDERgWbeZpBmeveUJKs8OwudAN3lmt\nn6GH+A78nl7LDpCirlV+IdEZg+bmq2E1HgiSattthxvoEk16mfFThBhKsoNW\nFqvTRG4//oCCUEoEQaA3Ujyz9g2xKXqUP9zh/0ZTfeBP0uw9U7ziI2JP78My\nvNSv3tG/3pdDx43U5ci7zuzj4MzdFPPx5Rohr1r3ONXMQninAe2UMj28eoHj\nOZLi\r\n=mQJP\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"1e06567dc704b928fda761690802d5e71f10a67a","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.0-beta.3_1546692169244_0.7017159972069553","host":"s3://npm-registry-packages"}},"1.2.0-beta.4":{"name":"3box","version":"1.2.0-beta.4","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.0-beta.4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"628d1acb7a74650aab5f671ce67b189568d023b2","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.0-beta.4.tgz","fileCount":40,"integrity":"sha512-7mAscZ+tzaxeYFc4UEceCwmBDZOMj3sBvD8Q5n0VC1BZsEc2cuDdlXWCIvQe917CMEZDZxJ6XBWmyQ9BF8/HbQ==","signatures":[{"sig":"MEUCIQCSU1VHDAeCZw1NCqKgF4KP3EYCn+nMok0hOXzDfkqZXwIgUsKQvIA0UgRLsQnhICOqI4iYq6Gjw5+8Y20q2cJyvdI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9037311,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcMjkYCRA9TVsSAnZWagAAQ5QP/2jwZDtgSc/6WGfdBeWB\nJJlXW+9D1Q09iejI37UhW/vZu35ZJlmzL794mUHQno230NWlAdzkhbKFMayd\nq+vFqjOVcm1JbxtgCGfwgS3tbF1OC3kWERmdSsIpZIUlBG2mHlPOjC1AOPkF\ngxDTpHMbac3KUhE8I377nEhSxJMkeBs9RqIXRV8To692XOyqJ9l2Vcliqjez\nlVlbLy1alUm6FPPpvyWDfPXO/BVHp/MObGW1PkMhs41Fkb94VceelMVJOxuX\nQycmXKr4FUEtbeguBIGr7cYXslAuzYDzoWqAQXdgXNanojU04aWYDIEaBc6P\n/yjGvzVyu9dxvqkm6bYALrOi41a9X2TA1xKAD0ZusHDcUdqktA/ygxUxmNSG\nKZa0IbJ8FaG8o8PasuDczzT/rPBwp+HfnE0qhIV/9s+1KaKu5HRpCfEQgBqY\nl+mjAQ6+mIvLnnmwsZxL/6QtX3lO+lZ/R0+jAOkQ4TivxXg0ZIv5rlitTpft\nyUNLx2XZGooQN5mmntYvpwdsN3NFtjGlvwnW2R4cJBRbVay74Gcz8hiQyBPh\n3k3/JjN+fEtwuFPfq+2yAP0ctMu1NRrnj18rq11u6Nm4xxaYHJ7ulnyzeqyR\nlfrdL+VnT2ZOdmY7Z+Z+Y5P/2Kn9ctb15QVTV02/s89UtiXjJC6YqP4NETzd\noTYq\r\n=c7n/\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"c4964820accb39938fb7e26a682fe4dbef544901","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.0-beta.4_1546795287889_0.927244640146994","host":"s3://npm-registry-packages"}},"1.2.0-beta.5":{"name":"3box","version":"1.2.0-beta.5","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.0-beta.5","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"fe574e4fff846241714ab811b80066d17c52a592","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.0-beta.5.tgz","fileCount":40,"integrity":"sha512-KLdz1ohm064JWAxnNYfwTAXdwVFkizj3QLxnJialI3jFo4XQHV/9cYUDtgXXN9hKCD/sA9RBL7GhDgIvNuXxFw==","signatures":[{"sig":"MEUCIEyIKZFs+NDEEtIIs9DT3prOd1L5jP989gHl5nQp9P/RAiEA+NFynHiElqSvXlp/3k0XFG4nJQxPlG9R9HslLC8pPls=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9039250,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNLwgCRA9TVsSAnZWagAAOWYP/jBAS2Z0OBCVOCOCdjd2\nEOPhgh5ia5U8aF8Fxt95gC6X+OsWWezUQzT6Mec8LNHMiRUQCUd+wW55QhlD\nRXG6xKV5FYNMvWm23AnU0334qQXW2mY0KCBTRqzggPrt2jp6L6RRbiWCu3N5\nf7rrK8jdJVpNLCP1zWCwurpxOZ6DlOu4rT3GcTTmNunSoPUGzZAIR30DL5+p\nAbFGkS5rqLdMu1ofF1CBCaNLVwdRiH1uyerBHJ2azbKjpcIukoQt2AdbcQ4F\nQKitjlVi98QIfU9ZC0l3yMapINcRj1U8ExQnSf6oprJhwHh4wofnh/fjE/rC\ntlVOOUZXy2Esfqj3V6WQfDza1nlMNgdV2giOwM8YiHtUmeJSMTMjt2gWT3uZ\noHxVMny4as0IH2EnZSw3i+ZP7rtDZZa8VMsDucWv+MvNY1fUfx3z5INxKJx3\nIw+aXO/2y2xX8QfLclc68bOE7I8li7w/eqAjj3x7+TpPaiuK405rdhXP05f6\nWxA6OMJxJy881/hPwiyJ7gO2LUG8IvCNEVW56fhz4sHUh0Iu91CeRoDLjERr\nIa4sqRE7s30yCdVS22VSxSwhVN8BvU0KmCt5WxKfon+h7ySZ9z+3CDgdePj/\ncddxlaoY8VVXiI0WG+ccUJc/CaAa6RmyEmRMspTWTvONKlSPq0jfcBhcF3Rf\nlFNe\r\n=9zR0\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"635fbd886724fd06cf3855074e0c5da0808c202c","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"ipfs":"^0.32.2","jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.0-beta.5_1546959904256_0.3226286643943683","host":"s3://npm-registry-packages"}},"1.2.0-beta.6":{"name":"3box","version":"1.2.0-beta.6","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.0-beta.6","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"c8bdd266467a0a5d7461f677458e88a169276a48","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.0-beta.6.tgz","fileCount":40,"integrity":"sha512-ysTSXGN/9ZhebS6CKnjjBJUSRkcS3qKJbd/tRDfbm/xVx2lHjXe9ZLKBmzUbwuOqirS41gxcSgYLo408BolaGg==","signatures":[{"sig":"MEYCIQCeQJQAwToiN3ryXtrXYQJvElAtGfiauU+iIMq2puUPCAIhAI6rIRqKOasmjTrofWnb+jjqP+eoPtzX9UYhe50JtPV6","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":19414901,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcNkTWCRA9TVsSAnZWagAAP5IP/0II+HfbYmWh7Rt+9f4C\n3EKOyGp75Bq3IbfqL5WyiOwWG4pVZ6kI9BRMIkxFSMp8tS8QHx1D6PZ/2hf7\nojQ8UhGdCcZI35sOHr2IFrbrJzxB33FhpSZ4rmJY/lMMdUM8Jp42RwToYn/N\n0xRm9JqDOMHOPjlFmZhejXTv5LKmUbqAOMn6j+1dhOm7p+m9wTKDQrJdEj5+\nMoDEHXFeZKCAmKIoE1SICwYQHx/8xgjMAczMoNuYABKnzg6+AuZbLrDYFw13\nUpeeMbtoZVUgWnFAPREcjnGnfYSybDk75sOb9TaLkKwreTEZAFmQtauY0NZj\nRjuY++DwaCFfBAnSGh65vlmy4FrJZVO4YWtqE4gSfEeIZkPIhuG3vwXTW9ti\njtb1MY3cnjIRCEZb9C+Pdr3nsbW7b3E92rhFOw+9puWHGVWs56ZKioxlT/QK\n9clgmIbhI9iLPPH9a0pAM5qPijlgDgJmisgKnRkX3iYedVKCrZpKeQasczG2\n7nX+B9eogImG59stNEN5A2pgz1qUYVyXPxu81V9j2ltnj3fC6QIYXMariz8Q\nB/DCXeRgb5ZKJ8Kw8JwKwjpk11LS9W1GqQwzGZeAQpcSIGCfkbIZV6IPdKVa\nakr6U+z29hm0qqZBX8wNvVqy+jv6GQVHezYWjmYHCWCC7qV9JyV6W4INqf0F\n5jgd\r\n=jgiz\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the user space associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"0495470efda953845a77573f90e574c7363c732e","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.0-beta.6_1547060437014_0.3692760671624711","host":"s3://npm-registry-packages"}},"1.2.0":{"name":"3box","version":"1.2.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"f1fdd0bc63e0d5eb1ede0916dd8338b3e282bee4","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.0.tgz","fileCount":39,"integrity":"sha512-e5v9ofpUtnWFct13vWXdXrr0+JClbl8Y/SuHWNEvOPyfmEdsUJbVCPhWVtPKgzqF5HvbzLs0lj6Ns32s9CST+w==","signatures":[{"sig":"MEUCIQCW+X/sJBA0X4dgsdnGdZIg20vllS8LzJKc1gICH6o7PgIgNMyZImkuSu9nxhfxaWFXrJ641Ze3em6Uj+CzZPDziJE=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":19131604,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcN2pKCRA9TVsSAnZWagAAF1sP/ApqLHVaWGVNf0YGkaj6\nE/CSp7sGnjKARQAImRgc4BRy+SvDONsd4VKLzcd/84mWgdfr0+nnAcwC1Mpz\nuAFKNqXKl46V4JL5fXAggVJuzFg2gqZg42OuA0vqUrfZob33dXNTdV5KLW1u\nWiVjEz3/cKdIwOJD9Vra7QEGbhLNIKQlczttyuo2LukaQeum55SfgTD6nwIy\nXyjL+Kv5TWnvQ0Eg6hWEEkusCSq/ose9mgWKaS7naB3YWOjzdAXjsIDDGxRK\nwLhMyVsZjyFu29neY0W0pHPC+qqnfIh7tWwdlor9WEp3vk9Dgy90s3CiR6wC\ncxJRqpN9TIONmDypAqoYQfqtuYHZOeMYc2MOhRSteynolBpQrrhM8xX3ju5M\nl/jpWe8Y9+SjbaP7I7LNdbsf079r7J5R0xlEpYqsBOP3hAfE/zsQi33JCPmA\nY/m0LPoAdqKoSENjdAscJRgbH+ARhjjAyLa/NOBBjCb6keOAj9gxEyld7htW\n3omqGiGG3Jw6ehpm06FmCdBqLxBqzRW63fbtTKyEpoexrsx/efm175YsXbPe\ngU9HWjssXlKk7pBh5qXWfGUF7ue6MvX/UCZXOiCII48I1ti7ANIttFzp1zoS\nYsozTCV5YY9K0B5/Jk0xebPlHUVf1tD1kHSYBi6hUb8dMP6wvL+qKJ4ObGOw\n78R6\r\n=+/0P\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"fa1982c48aa3ba22576bfe9e097470e031cea1b1","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","bip39":"^2.5.0","store":"^2.0.12","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.0_1547135561514_0.3765771762943606","host":"s3://npm-registry-packages"}},"1.2.1":{"name":"3box","version":"1.2.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"f54ad0dfefce89ffcdcc422b43d41f01db08b85b","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.1.tgz","fileCount":45,"integrity":"sha512-XQBjnJQa7Xs0gW9fDzOBlS/2skNM3kM85K3g6C+91rqpAS5/qfVkuV6XqkUAtcFh3aNOJYhTulHgKXHlmbnKlg==","signatures":[{"sig":"MEYCIQCtL1jqdnKytr3PwaW9sd6IfeyOtgNJVXawZtECgfeX+AIhALpx38kouhNwWJFAhzVMTLkudUR8MUnF/5laW7xSq++5","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":19860680,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcQFHGCRA9TVsSAnZWagAAUScP/j3hBpAr+OJpk4M0YTlZ\nnUc7lPxbJPTaRWBKmQur03nlUzsGx9Qx84UNem0GNFwnOErys64maPyUzRWo\nb1kDbgIeyaXV1eK2kc12nalfmjhwsyTUKTJvVLrUH00K+vcfRQx/O7imrl/B\n4DPSLNWuwYdw4VgfMxMQhqZnBUxn2hh+CdLP03yE9tULIGrDb3P+1gR4EivW\nYD1JlpIWHNYhenZMBhFQOi6wM+1DylQh5itL6rYvLfXTmbYvnN5VDDOiOWUj\nn+jhZxtrCZyhfwe/MwauAxPQgWUcWSKdjBEOoSS+o/bvywC72hRS/B5B1MKy\nAtw6WX/yYUV5R3OPnbPYccYgfIMegJjaNrAoTHp/gBXlItheSHbAbFSOmWu2\ng/WVWfaXHzLfFi0CjTWCVCrErxTgyIHB2mUFdGzwwlnwdY0Rnl0IPxBaJDO/\nMUevHqbduwASQJf0knILEFuEGDZHlEoOyf3HDzRcJtPegglI/Qqc2+IpxefN\n84O5yz86omI48gEQ23w6CpPb/9ZKU/3XpgXM8Zkh3hfcOTv7JIEk3/ZE3tlr\nmH8/iNs87cTC0mH2P3LHDBQNr/jNctkF00znlLKF/sFJ974QfOheLvNC+McE\nZAxn5xWZKJ9K5pRNtL/Gzrx1k/BK2+jw9+SVinRLHRWMIy+3ynOGGTDy/QNP\nuSMk\r\n=EnvB\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"3e6eec5adb3158ff0e6d66c9d7cfdee7338debbe","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.1_1547719109293_0.8348218776004808","host":"s3://npm-registry-packages"}},"1.2.2":{"name":"3box","version":"1.2.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.2.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"387a7abbc325d963da289e40fc2764f30fe306ab","tarball":"https://registry.npmjs.org/3box/-/3box-1.2.2.tgz","fileCount":45,"integrity":"sha512-Ljcvxx29jVvot8bJKO58QpYV1iyHuxnQEz+FCjMEBNwKJ9UmdEl3H6NqnmMa7rPQ/5W2ifH1M7mGeiuydQjhzQ==","signatures":[{"sig":"MEUCIQDzoQI7qI/6xEDgux2UpUOdT0jLnsmCEbv32z7MfkCr/AIgfTwcSBX5BfzESC3qolxjbtnvlUZk8E5WHRB64gQSQ2c=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":22666764,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcS08oCRA9TVsSAnZWagAAIIcP/jQVYqA7v0bSRZCEaBC4\nrvNjBuC5DuSrNUWur7X8RO8FU/xkODkAJITtTsG9mnH8Pa4/VP/FwZ3evFeM\n2jQMsfm7cgGKMYnaKgOg6N4JWOBFbhntWSrCelLYpU/0baRFxA2TZ1QRuvWv\nbuKNrYUbx709NeUoue/iKIUzOKOKYaqfqMY3GYwivZLUGMNGEXGTq9VX6JJb\nmuon5kMu18lIiWuZnPwUzi9BXAvDf/o8kJTY3EIRNPvlOtbeDIbqRFzPE3bE\nUT8X6c3+slt7HlVDGNqgCUWl4BEidyCS9tlWsiIvkPcq386GZgb7MSJR+YAS\npatKUE62SAgsP/SfsqflxQgayGNtxiihPpjHJtWEg7o8MMH6GzlnoAbdAVp6\nXgsVAdXdTQTFUOmTJno2FLgjpPUxC+8Z0YLFiiFGmz1D8990d33Q+aN0vsS/\nw9vo0TLwIUn5/XJU17CR4F/ZnuBB9M5r1DpFsrd9mo7uNCZJg0B/iqIJmJa9\n1GPm9i+W9Ebba5WHweRMDLpaKObg4CmYnpw+hDCj0pWVww0EsGW0hAF++3kU\niBu+plCdAEbmzfCmLHMWR2nZCR0Adgo6hit1gQGrH5IU+k9dA2ng3AjX82XS\nQ0t74i4hVgacHTdix/+MpDPERrAMupZacIAsyeEg0fEw6Ek2ot7w+QPbbB2V\nnG5E\r\n=rfV0\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"e686ca48a72de20596ca74a5e40dd77749637cf1","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","js-sha256":"^0.9.0","node-fetch":"^2.3.0","muport-core":"^0.4.1","@babel/runtime":"^7.1.2","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^7.1.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.2.2_1548439334936_0.5188795982652399","host":"s3://npm-registry-packages"}},"1.3.0-beta.1":{"name":"3box","version":"1.3.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.3.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"a4755198b64c724bcf93c42a95281590d83a8d32","tarball":"https://registry.npmjs.org/3box/-/3box-1.3.0-beta.1.tgz","fileCount":47,"integrity":"sha512-NfQEl9Awl7XJSTbY+EU1wNbzvd5W2DKkAHMXl10v/xSk/WoC9ueRiG3ozHdYEqSlbe6a9LllVcYdCYA8Jg4Lrg==","signatures":[{"sig":"MEQCIDh+Na0s08IS5+WNTXynwfdyuYJ15Gl0RrhPm2ol5glDAiBSwaZYeEaTF5B2nF0+0WEXj2/H3ctVzTx6/h8Hfl6GFw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17513801,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcVH6YCRA9TVsSAnZWagAAqHoQAJdy+nN4ihQ2NmfnNzWK\nGegaTuuRrn/mmAPjdejjFWFTSM7hGyZ1c1FknkZ/zwwNls4szPfjsIEn+ife\ni7892MY6L4ysjdCUwjrtU3Rg/C+Rl3hlD11hjKabcFCEFSEcqBinDBHwkgZ+\nY9BvsYlO/vbktCwlaK1svzmUbLku2AYzs3go9a2IsJLMC7eXpGSD6rZUlkr/\n2r6NlbJvXZHqlGqSN+YMJg1MfYOcXK0UN/hPaXaG+HxToYiBBbZwZycV/U4y\nYNvSZnJfxCRsbkIdR/40MJ1r4Z2v3zIt4wlvFBlGL2StLtjJadJElKBsGKr1\nY0tUcW5Wl7hD3GxVURA1MsXWLbXpBxOMZJ6Jg5cQNqNWgaNGf1d4ubhTNMNU\nafFKW5hYyBp5X0BHoYMeQ9N1nMN40HNy+jPauZujjcCcoQzM2/5hDTDIW7+H\nKSHl8lMs9gHijJZepaBSqjvbdf3rGWVRJ9TIZSIKsoqc/4NINcNzpBDCNrx5\nb3NZ6qo1bsS7o4B6vAXUeWQ0/dMo6NtgNUdARInpPSMq6DrJ+T7YBS/DPq9C\nRl5uhhMReTXJV/9N2RAgX7FWYAzKRljd4EE2XJv96PspWedjNZxX+brIIfjN\nmETjnvny+nehfSazJ6lAFkExSSyElOm97d4J8HeUDxBPLMyti77KzuFK5sbQ\nZV/R\r\n=deRW\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. Currently it supports one shared space which all dapps can access. In the future there will be support for more granular access control using namespaces.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ <code>Space</code>\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.close()](#Box+close)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ <code>Space</code>\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Space</code> - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+close\"></a>\n\n#### box.close()\nCloses the 3box instance without clearing the local cache.\nShould be called after you are done using the 3Box instance,\nbut without logging the user out.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.orbitPath | <code>String</code> | A custom path for orbitdb storage |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.iframeStore | <code>Boolean</code> | Use iframe for storage, allows shared store across domains. Default true when run in browser. |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.profileStore** or **box.profileStore** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"b91da9523ee07d50ccec1d4c0c458dd0fa7f6128","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; node example/server.js","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.0","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"0.0.3","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.2.0","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.3.0-beta.1_1549041304004_0.4211440551773511","host":"s3://npm-registry-packages"}},"1.3.0-beta.2":{"name":"3box","version":"1.3.0-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.3.0-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"8f8996dc48a247695dea36ad5ec87235f5e271c0","tarball":"https://registry.npmjs.org/3box/-/3box-1.3.0-beta.2.tgz","fileCount":50,"integrity":"sha512-vemils3NMR4FLPOyCMNC9r/BgzzvLDicdAima2Hu/ByMl8/u6lTtFZGC5o+7MIUs/goQnP3cpNRoEXnOhkt/Ew==","signatures":[{"sig":"MEUCIQCanv4I58nLez1LniYPze1pKEouISps3oyyphWYZRg8aAIge8dshrH7q/3cA84yMbNcfbhTb/yeg3+jH7ykD7Xt9Ow=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16369671,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcVfIYCRA9TVsSAnZWagAADPAQAJTO9OA1wDrY/FkZuFJH\nundkaokWTQ/M3AsYMNPwUtK8wQdYZrsJrywkgLK36Tfj0IMWXOhA9NhPnIZa\nqc+Lb/qWlLk0mYvAR8q1q8AfRLNhmIuGS0I2sGvX15Aw9Sya8k2Z3+VQ1H2k\n1V835QwXPY2ipu2w4B0Rb8v+ByJvHg3+toBWHSEBLdrYi643lhQqEJZorUWV\n4GrZvDJF7/JnKKmuN8z+6ZP/bOMMLHTV7PAgTzGmqHEHOhYD1LzNcowLduSL\n/LSujS53JBfGpxbuDOnP621nn91lQ1r3wlyMkHSJVcmAU8ahtqd1FCiJIeZv\nWlpvVLL0cOV+hlBCY4Bvnrd30bOfZjRyLFxndtC+eeFm8IU+qPj4++wVBJQx\nQPvoVNF92lTYZ0v6QL93gTZj4sDZqKrOzpLj/MzxFOhjRdnDgs74+6BaLsLl\nfT5dUPqCaSyNNJI9Z8eYe/hZYOmoY2Y/MsbjnjgQpAG9E3qT7RPZ4fnJ4hZZ\nE+1XkM5XqV2xx6lyVRozvAoRx0TvhiQFrVavMpdcxZO50SWJ5PyC9o7qMNH3\ndySXbkioPEoK5ZI54WBMNYBmFtLJ5L/YgVK48bQDD1nZHGBXjHfLJcnfGx8X\nqhuSygUgetlHX3598wAam49378KZt10Ao6jRj11KRiq5GtIV8xGdctjol6px\nBCqv\r\n=n2hE\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"1709cfe65939fbff3de3a45dd7b03a4e6c57cb1b","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.3.0-beta.2_1549136407351_0.04684006199562929","host":"s3://npm-registry-packages"}},"1.3.0":{"name":"3box","version":"1.3.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.3.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"c0c8e09dadb1bc001f1ec131a116d3b1d67695da","tarball":"https://registry.npmjs.org/3box/-/3box-1.3.0.tgz","fileCount":55,"integrity":"sha512-7HlbnQ/kLRAI4WiI+vO+B9J8rUmGKTHoNZdOZ+c0cb1oQnBjrkNz9GnYBBGT6jNbnpHKUc+QgSoNmHYy9eVLpw==","signatures":[{"sig":"MEUCIFeCxzHghS9c8ZMkGgTKuzddgGPwEW17pD9t0jDhBzzpAiEA8X5ZKcpFbgB6MKKfyVzWFsrpMM6Qu0t1V7+ILJizXpY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16675847,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcWfhNCRA9TVsSAnZWagAAMUwQAITn83hTeEa+0k+vhsHS\nVZtd9vNSC0UsWOt9KD0dK+t47SXnrQW6NiLm5ARxNyuxUWEwcFbAW91tcNOC\nvyVOA2iTN/ozTh9xSypcXh3nzpr9Rqzc6Xo1/n6sLCUGFlpnP/zk3Z/6JE6Q\n5y6cAuPjNDgCnl6MeX4/rkf2/oydNocCaaTUV9pprSxhBTAR3/Ltzxn3pgMY\nFHlYT6D1FnBbooAM6kvHb7x0GpT9fygrJiRKlKU2IHQONgjO6+9l9flif2ME\nZSg1MOgBzHAtI9qSb+TQx3lWM1bGmYUSUx6XxbEZ/X5IuRXo68yhiK5aPJ5p\nRZyKFM+pGgquF3BqMgdkgt7J4HIu5w4vFii3N44op9skbmmdnXfBjJ30kwuq\nAAvg6Nut/uhFLlibwegJctiZBOlDRvSi3WuV++5slRUGrhdl841Yy+r8X8eJ\nM77vjpt06IasK2LS/nHlk1AyC+FeTpcCtXBiAQzDqzWVjSGIBzWlHjCs7/3d\nbF30LR8cDw/P5TGwDB5sVmtDjFfWZW6bIN3DIHAGBmZRQg/bZSScsIFgqJrs\nKPLwACnhmHskgp9u8qZg0hoFJjIwM3/9n0CipN9hM3IzNY6Pn27OUgpgNFak\n/kZAhmfJxB6P3rsSFgqqaJzq/nYgJJRJt32oInhC8+8O4+PTAdBPd4jBpIVC\n7/xN\r\n=5cXI\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.3.0_1549400140877_0.3391307774658243","host":"s3://npm-registry-packages"}},"1.4.0-beta.1":{"name":"3box","version":"1.4.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.4.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"5578e684d60130fb8d41931ab224d3ab1f72db06","tarball":"https://registry.npmjs.org/3box/-/3box-1.4.0-beta.1.tgz","fileCount":54,"integrity":"sha512-UyjT4IuoRT1ezkLf4d5QHJ73tNwS66N4J1+OfQtMvcwAeiMwRAuEe7mqUPW4uT3N52LG4sdGE49RG4kw0XEjdQ==","signatures":[{"sig":"MEUCIQDq1xUjyrY3ORow5M833hVDYndKlekIfruH5xHBUUFnLQIgVd8mkaWPcjP6QUw7xA4L2ZDfrpW6qhGs1bulKUqLcZs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16693957,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbwvvCRA9TVsSAnZWagAANVgP/2o6LH67Qi+IO8N3k0Xo\nkezIuqPG4z6FvrFHjoZgglHiF1OYWjFcaD6M4K7EX5JDNzo4KzpLvD8CpRf5\nQQ5wR2QP+EcFX6025Od8KQG/r3jAb75GNLpLbRso81FyNT5KkrdS/mB6Q344\nIM8UEe6k+9iCRe31XTt9eA0M3F3M2d+jxgDvoZYGlM1ArbJr67wBizlLpeKm\nmy9BdZx8vedq0zGLYelIEZMf5o9dCWAS9+4pHAbM1JcQjV7Ap8INlKV1s6TP\n6Ynbnzm7YHnMsH774BdYnL4NXAmq6Nml0bAG4sdqsMHnZ82hCIYibtLhkSTR\nfEbQCeGI6vc7yOeMbgYMly/aXOh51QQ9nBq3Xkuy5RmRU/3IWhiuH4qQ0fL0\n03DeUFwb2i7KuvxFj4o9UHiKpAN9zZB/oty7DdVTjdjlt97eYPVVNXplDqEg\npUPwFdb8bYV4Kc9lMPpFCvHmlLVCu3ssR3scv9ihCWcW1rwHWy80vxNimJGX\nn9c0SmpEm+uAEFncqYiqNN2ue+9drE8NdpNi+LKIbpVp08TFm8QplJfuUSDH\n8JeTNMy2t9ALXq5WHIMAGv2Wm2tJ8V/Njds6/CWn2yURzB+LuunclfDWi6JS\niN8CohPPawXHzlauk0ZbchjMVTFSajyzpubzA4PJ7QLskRQyP4sUtaHi/m+p\npJQU\r\n=pKDW\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\nUsing `async/await`\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\nor using `.then`\n```js\nBox.getProfile('0x12345abcde').then(profile => {\n  console.log(profile)\n})\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\nUsing `async/await`\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\nor using `.then`\n```js\nBox.openBox('0x12345abcde', ethereumProvider).then(box => {\n  // interact with 3Box data\n})\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened.\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box data\nYou can now use the `box` instance object to interact with data in the users private store and profile. In both the profile and the private store you use a `key` to set a `value`.\n\nUsing `async/await`\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\nor using `.then`\n```js\n// use the public profile\n// get\nbox.public.get('name').then(nickname => {\n  console.log(nickname)\n  // set\n  box.public.set('name', 'oed').then(() => {\n    // remove\n    box.public.remove('name').then(() => {\n    })\n  })\n})\n\n// use the private store\n// get\nbox.private.get('email').then(email => {\n  console.log(email)\n  // set\n  box.private.set('email', 'oed@email.service').then(() => {\n    // remove\n    box.private.remove('email').then(() => {\n    })\n  })\n})\n```\n\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](./KEY-CONVENTIONS.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"dappdata\"></a> Optimize build for read only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.4.0-beta.1_1550781422122_0.9953200849604367","host":"s3://npm-registry-packages"}},"1.4.0":{"name":"3box","version":"1.4.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.4.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"1048edab90da819878461898f94fccafe7ba2929","tarball":"https://registry.npmjs.org/3box/-/3box-1.4.0.tgz","fileCount":54,"integrity":"sha512-NbwwRQBrd+2fjFMNB6r+y+t+V+vAbRGo7PfEy6itgVi6MR2UfaCcs2peWpGJdm2mQR443l2G1uQcOeojXEnDWA==","signatures":[{"sig":"MEUCIDB1OdL2rMN2QnxJ3LPhrXqnPiKcG2Q5QM6w4FJSS/BgAiEAmu3wLk8lbr+wKAUoq48tSbonDRW4vbtBiaz6VdjsttI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16694029,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcbxH8CRA9TVsSAnZWagAA5kkP/3usyoofBvTAycIteP8J\njJvbbUDn+Sd0n8onGFEZonu3uCTSpeLmviilKlNzaAveZgJ784o4Qx6HHGZz\ns2Jc6WBL9ahQSsPcXsTJA0hKWY3SVBZ3OQmIFjgpgYWHTopdd6IzCSrirDnk\nPwgSUFbenACWaO0m0FroBsfNboZnA86d0ijyLRjaORrH2i5hxg8MkcuTKLG3\nL6K6BA0Dr4DnsXli2N1b6GXTwTsLY/vyW/DKoCfH9jDxjG9FavJGW/tJIsv/\nb+3TlJuHZm/fxlC/He7Whxx1XPVtfgE2iLR85ixlngjVaN0AS6C0PGMMoD9R\n3HVjVPlq/M/nYP5qGikXGfzpssWxskSuWvnfFkPB/naSrpErsAwS107wYt1K\nLMh5nMfoYGTSZ0GpU3TFXwjxkFdeerPVkVPMbU6Q9b62WePvvZwYWRNz3t1g\nmXO4NQjPHD4HragJmkdvQxUWXsycDsm3ADqnLORq1aAOKOLpHqukpBCBD1ZI\nePtaQa9CJGVTLDhaque3NaccQXJjCdkP0wDupmLZmxONEnHmhlpJM0g3icut\nZ9Nl/VgmMoiYZ7SfDsX1FX6XqP7dAK1tM9OxCKJCUIBUpmjUevjfx+6mkyxl\ntZUQts7YRD5YyALmUsEn+9n/olEXdRX2ifkuhPdA6OVumcTPzRXJ/r4AgsKA\nDGMa\r\n=tXU8\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.4.0_1550782971102_0.9865840811730118","host":"s3://npm-registry-packages"}},"1.5.0":{"name":"3box","version":"1.5.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.5.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"0dfe770fe459d83b4e7e4d6cb9e782a2632fabc8","tarball":"https://registry.npmjs.org/3box/-/3box-1.5.0.tgz","fileCount":54,"integrity":"sha512-1eBKzqJaQAvCqDyrdMEoXB5sW6R1WMV3RX7GjtxVxpMfOMugZyrw5g+tHlniqnANZ4mUy6I7y+t22o8YcRS+/w==","signatures":[{"sig":"MEQCIFQwAYuWILGttReVkB3ib4SMNdGAIVYyP4jC/VLq8xJ8AiBCRKuYQ1IuSVeKbhWV6uOHHVbg1bR7Cn/LFjw+BO8uvQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16715916,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJch8hBCRA9TVsSAnZWagAAJ2wP/2tHp99Z1ok6QVPNHxAb\n6gAwXoewAjai/MCz2eWO+nCzK+WlHgn96UqrgRf37cW+P2Svm4ZifTxSqjMj\nD8QNvCXQXT/k3G0I4Q+H2up2wzxzOu+DRxekqDp9O19uc9RebmkgBfZumRIk\n6q5oQcHSLEVch+8MqosTT3rh/ao2lSk0h00mbnxsdfbLB4LVlXXLFNP1xyKK\nLK5BqMHWLRyXNF50rsxM3SOPPXti8mG+0oeCD0yg+3IjBqzj05Upa10LTGjo\nhuwNICDB6hiG7DE/jjU1t1iik7ZmOTD61TO+otGKuLIQFkk1ne2/z2spWjuX\nq4wGY5wKPyFg/7nA2xRpTxRca6ct6kDHUUUVb8Fmpkz28JlbkQYkTpJQpLkZ\nlMltBW/IWc9/B1OlUSAZHY8Sp5mlb0Hx7yDUrHjb7p6igvhiLmodMiszZZlS\nBDdk0ppJcINLvGw6mU/TN9/KYU+35H8AMlFzHv3+vYUSu5VEEMpBV0LhCW1n\nZaWgkscS9a1SGBwgYqqh97Whc1ls0Z6oBR6dk4g9drp/qEVP6aQdgRGhq222\n9excxzvlSZygJu/DF/mn43HeKYhBoG5ra8FARq8acsF7e0HsYMcPOZw7YQNe\n3h7EsUJOFR0K3rX4lEODQyzInTLYwmSr4tvZ4PvNHykAKh7zIN2JxEeB24sd\nBEn0\r\n=4luX\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.5.0_1552402496291_0.5029890925928597","host":"s3://npm-registry-packages"}},"1.5.1":{"name":"3box","version":"1.5.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.5.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"870e83befacc057ec653226f650a9935655fe6e9","tarball":"https://registry.npmjs.org/3box/-/3box-1.5.1.tgz","fileCount":55,"integrity":"sha512-bxpmPrbYWpsqZaHCvDRGFRBCSCzFkvO2V3WiFGMZF8VbfxR1WEGoJPf0RZQnTUszunPdIsVWLX1q1RQGhmkPPA==","signatures":[{"sig":"MEUCIGtAvQ7CGjP1G4PG82gLyTc4rwXUjS+cz0O/f1UcFh7JAiEAgEREDqM7vXbWTo+OL0LlmHEwc6jZfYPI/VQefbriMPg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":19630669,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJckmISCRA9TVsSAnZWagAAG3IP/0441anq4Z8BCDpHpPOb\nDOV0d27X+1ySwo6IbPrT/3Qp6ZAjK7FpEUWXIYjQj/SHwqE9DPfxqmMUp+1o\nq3Pytp+hWmb/fk8LW9JN8hCqbGF052f2wPkx5wff50XyjNMvZJLBFQvaJfqX\nyPeccNXP3Vx+GDs/erZDEQAyOAjivNas3E6zeULClkLzHhIJS4RF8kjh+x4M\niEjVX85X2mgt5NX+/6A/T/uoa2yIxciQ9HkAxBEMUkfpcWeBdo9KxnkkvkEH\nVirMOhdRAvGez3po6hppzTk4NPAtM77pHIjXlVPRK2Kxy6Dbh5wKEdiLVfAT\nYlLq4K4bAq7Lr0+wy71BeF4bf1hRp6m3mkYZwlteZ+JfJWmJ5hx70VID/LAw\ng2DjFxT8ZrTlACJzoTLXSi+g3UhMZPbwBkSNGkOHH5KIqHjwpy5ovn3XWDoc\neIgPZ2URTniobU0Ck3H7B9QjdVQGOrluM/+w4Qv31zAhg0Ba+3wpPIWmsLFq\nu4HIvE1AAu6keM6oeX+S7suZxKvr+VRpamOe/BDYrEYSq+wgcQGtg15ByT3Q\n/y3tIRPgsZ9l3tNowjFVTTTXMuZMiPIqmYC0pcOb3T+h9JWGQdrHpUDc70wN\n3+ZVC77C2J4ZN5nx7NoQEMGs9W838HgS/iWNkGG6fud4xGvRq0vlejfpQrCb\nmd1B\r\n=O2Rs\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"4eeff0dc543a07e75bd5c28fec182447e486734d","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.5.1_1553097233252_0.8450541775481462","host":"s3://npm-registry-packages"}},"1.6.0":{"name":"3box","version":"1.6.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.6.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"0777d670da489e9761169aafa024bd32750f4ddf","tarball":"https://registry.npmjs.org/3box/-/3box-1.6.0.tgz","fileCount":57,"integrity":"sha512-J45tHgbEPA4pIO08NAJkSA3G6mtl1Riku9rtBztpeePToHDG039o7c2vnwYF4acVYMiHqQQ1C1uoeSMXXCjLew==","signatures":[{"sig":"MEYCIQCHTJIkVKGaNfDeO8/G7cxrMU2fCzR8cYup6b6fhIMsdwIhAIpjbdj6nfo+XOy62DILkwS4isgQPpX4zLXn1/mwM2lN","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17087085,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcnOXwCRA9TVsSAnZWagAA4P8P/AnZBoTnjOffJw5THnne\n/9Nqtw0qULcAt3Chz+oXlulHq1ZJYrejQ4wPnInsOPKse0cs/blHc37aFGsL\nBjfEtc8Zx42x84Gb4xfyvaUbzMabqdNM4vGXaZZs9/Ak9xrnhGJPM0qpYNvi\ncg4z7urdc2BOvczN2GnYYiDoWQEMojq04Ey6117VaAKQJ51zZCzP+wQykxyL\nKyf3sshn3lFANmvECIwFSRnTr8Kg4YUjaQmhMrXNRJVFpI5FphsvBBzO3ZHN\n316iy5FoHBofNhiPMLjQHvF70peaIz0F9r5QmyUdrLiahCBxkDaXFrBgEECZ\nJmrpmHNQI3Ow0b1iTwthTq5LBF4i9wPmsQLRCw2lkLpVcm0aQTsRfxbUk0dV\nznfL/XyN8SZ80gUg199mkO0Y3u8/Yrx+jVP+PzTFYJDsPzeMgLNXBolwkVNT\nm5zt8ajFJyRH5UetaBU9URN166WqCBI8saG0FBZYv0il4HIFrUGQ5tNwhInf\nAmL1EJ1AGZI0cyKtFyZ2pP3kzOoD52aPVFl4hA4I61GOIikx5bUKPf+oSPDB\nG9A2pt3x0EewQ+RwhEyjbPZMbVaFA1c94gepk5AsvOFqXjfl1/Bq9HiKWfk0\nLOrLgzxvv2nkHk9NXtGxEYFQTmnPkGFGLSFDLKBQsebTW3vuizdnSP0yVtLr\nRxKp\r\n=ot6m\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.6.0_1553786351287_0.3643717734639029","host":"s3://npm-registry-packages"}},"1.6.1-beta.1":{"name":"3box","version":"1.6.1-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.6.1-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"1537aa16b8d555f1d16c2015f7313dcd09bf9088","tarball":"https://registry.npmjs.org/3box/-/3box-1.6.1-beta.1.tgz","fileCount":57,"integrity":"sha512-CZIm+MDstISPzlngmXkIZ5Ygy+xYS8BTCB0otQcLL4cazNuOzftx6ow7sojrDbr3pfX8VljR17zegpFOqCM9aA==","signatures":[{"sig":"MEUCIQCzps4Fxi7251fz5TXNNPOWw0whYWVKvzwdudF+38UCAAIgT4pPGaFC/TrK9cuHVZhv4fT+eXjXBy1w1bos3v5Th+M=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17088364,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcnhQZCRA9TVsSAnZWagAABTwP/39eiQ3JLq9DWbrq/to9\npTmxLhaMbzY88MEfdZOcDwZGGAydAoJnUYzfLsMCPtZnhaAU0uCVPEnWlIMY\nSH+ndSOAWjIwWQwUAuwQbEP0IUFIZ7wB/RP0N7oszyWgXs66C5AYn54bgtwM\nX+2B+0V+dSBJcTkdKZnR5h7/1IS8lfWnfTNN7Qg2nJjvKiKJhjdaGAdoNdlV\nVEvO4QYUGLGQ7iIi91CpQ4fgrSbXiBBSOGoU7CAagdbQHNmfmX3FXXSvpa7j\nQlG1cdm0C+GG6t4ktLok1na3L6m0kWVPTTIebzaLVQgWgkZcZlKBWUVbIcAO\nXptfHSesHbI3tA1ULqPqyxuHX8Uwf394eQgZWZWvG64dwQUlIAa/pr7g1IHN\ntaFbiXDpyJeAo6Q+J+CygwPiW2+ZZBRDNu77VqGtft3V0DJ/b5vAJ1N5cUoT\ndReNaewaDNpaLF9qbjbdzlOvoQ1NNL5NZP+IvxDi6ErIlK/GSzR8I74/e4nA\nhLdIQN/GsXJhRa4nUvfHgAgiwZG33DO4nPTnRzOrZHNYIwif3QBRpK3YFsdu\n4W/Qn3lthoBfjQN1SwcGdKxKUVtJ/8OJuDsR1bD2ihKORJUlmYM9mFSQhuuk\nq3S44EyH8op+5whJoP875HJBgkDQZAu3mJFMeUTzpTJ5+Cdu1KfISh7ARIPN\n/CIn\r\n=icMb\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened. However reading data before is fine and encurraged, just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box profile data\nYou can now use the `box` instance object to interact with data in the users private and public data. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n### Using threads\n**WARNING: this is an experimental feature, the api will likely change in the future!**\nThreads are a type of datastore that can be used to communicate between users. For example they could be used to implement a commenting system, among other things. Threads are created within a space and users that join a thread with the same name will be able to communicate.\n#### Joining a thread\n```js\nconst thread = await space.joinThread('myThread')\n```\n#### Posting to thread\n```js\nawait thread.post('hello world')\n```\n#### Getting all posts in a thread\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n#### Listening for updates in thread\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n#### Get all posts in a thread without a space instance\nYou can get all posts made in a thread without opening a space.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\n\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"dappdata\"></a> Optimize build for read only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"api\"></a> API Documentation\n\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.6.1-beta.1_1553863704717_0.4118795384858478","host":"s3://npm-registry-packages"}},"1.6.1":{"name":"3box","version":"1.6.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.6.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"1dde1eba0ce6238ce235a7a60b6a6911cf73c00e","tarball":"https://registry.npmjs.org/3box/-/3box-1.6.1.tgz","fileCount":57,"integrity":"sha512-jhAhhJ/yEszT3NT8UzlhdKy4rs+AQRdZCWyrVDgCGRIWREuPicx1khknMdiiycMJS6ME93szoc0fKjQ3wBw4hA==","signatures":[{"sig":"MEQCIEQ0yKUl6I2Oyl2jszQfevobP5EM8PSmiHS0emCwuOdbAiB0vrpNOe3tL4XYWBc+96e+yPjHBy0W36gxer3cRI7iVg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17088425,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcocfqCRA9TVsSAnZWagAAXykQAKL3RORSfDyAgv2Hvz0l\n+9AANHMSmBuZkZl03gq0rThORWLu/pvhsJw0Sbxx8KnSGI/s0rYAMPvgBjlT\nUbYj60y9LNayRFm0A2E4TY8Hu1b1v9k4Ki1FKXTiwBQlkBEDtN9ojzZb18aE\nO6LjaSrGiWsqvt2k7IkJUzbBzvHu1lWtys9GHx81AX1p8NF0SeCnRN9Pv1ka\n422ytnQc9zNGnU8gYgRC/hQdlhNBMvCvmcVuJXNkKvuPRvdSuwCSIdDhARKS\nAP62+b55RIoHrwBR9cuKadsFu2KkUGZHZWPCHLY3HWF4QRS0dYU2+XeqGph9\nrDHSduXVGRmdnpCY+c2jGTshyknbBRGyUeUCMhpZ+G4O8Bhzw3hFzqgvz78N\n0PgCduG5xRTcdfVrUDJi/v1NK1h7dCL8ymIIIxHHVA5xLYjFX4E2HdYGaqzy\neP0B7SK2pc5ofuvtyMii8ujmlDyeQ142bCnF6UR0CLKZhJJuZA6NngbKlwoz\n81eDnQ4XmPYsxCL6tlVmq1KewHgeg3H0UpjAscx6YUsVsoFP3LeJ4m7jL87p\n7UhIjJuwANsSdDHowBOUkPz7YpicY5rmMjfio8P5w7hsml7o4zsiTr6OqiyS\ndY2sDhff5h2cqRDAWbnWnYT+w9O8GS1/niBdZf7xD9ZBtVxRkKC9gBbPadXT\nAzK6\r\n=5q7Y\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.6.1_1554106345502_0.053531390013992874","host":"s3://npm-registry-packages"}},"1.6.1-node-1":{"name":"3box","version":"1.6.1-node-1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.6.1-node-1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"351409863134af64abce9488b58d30ceef090af0","tarball":"https://registry.npmjs.org/3box/-/3box-1.6.1-node-1.tgz","fileCount":58,"integrity":"sha512-uWoXEUWgQS7SEY1ALggxFPKLUe2i1zLdckkxdZMDAAOvF/btv5ddR8qCu/CmDyY8rv51gePb3+UW61GRmvpycA==","signatures":[{"sig":"MEUCIQCn2KAv7W6lpxOEQ5o5yhDcaeMx3xz6dY00S+ohL+Mq4gIgMzdK7SP97MJyp08lyCT0NqDmxi+j1LiGsACG5n3Dabs=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":19999362,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcq0CQCRA9TVsSAnZWagAA04AP/1cAUx7jJaCW6/1EuHcl\naGMskqG0WT6D2r+TobWSJFfAlllzXuWpMTBuovbAzde9lXNOYhEqVkGhil1N\nDVVo7T39CvSkbVjCqxgewFv9TSSIFD7QNg+o6MluEDQwGIaVr3luT3Z/BNMb\nyDAgYAi3/JLYVgYWmXSMD61klG7X9gde2jhh1jledQBsjd750IAdkDPTxhgM\ndUGoHjibbMsL9dcbGRQZtX7QNlnu6sIKhTTz3MDGJ+8fx3Oj76QaiX5wdD2L\nevIO2YBmEU77riLu9gbukplEGety4c56WI8MOMoxBt6Ff/GJJ68a0zU2WZVz\nvNiJl8W+WnRxLx64Gio9dWcarmU4lO0lwnyJuw/5N61q+6TirLuDl3lxRdKx\nzISfUm4+45qevjD8mUnl+GFa1842aVPVG+vVu+jK6r+p97y3rbuUiTBrDOML\ngT6VsqK/8UVjzs24geBjvJjBI6Vu7IkSwdrh12qtgvK5M8+/tFLzYX1hmHYB\nAe7dMu3XpDwAt27FZQixJIMTfPKOmWX0XHQ7VkWjZRvFGMHVvUzgFUHCADga\nWe5GvHmF9Oe8fLw9/ra3M04+4by06vapGInxN372pKrSafdPkc9NxrHOr7Dv\nYw/CIxeFL8tE0tYvMOIRN7uLiwYclKNoZS48oC8Lc9uoVv6WG865GaOnsBaA\n6eM1\r\n=Ml9G\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened. However reading data before is fine and encurraged, just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box profile data\nYou can now use the `box` instance object to interact with data in the users private and public data. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n### Using threads\n**WARNING: this is an experimental feature, the api will likely change in the future!**\nThreads are a type of datastore that can be used to communicate between users. For example they could be used to implement a commenting system, among other things. Threads are created within a space and users that join a thread with the same name will be able to communicate.\n#### Joining a thread\n```js\nconst thread = await space.joinThread('myThread')\n```\n#### Posting to thread\n```js\nawait thread.post('hello world')\n```\n#### Getting all posts in a thread\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n#### Listening for updates in thread\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n#### Get all posts in a thread without a space instance\nYou can get all posts made in a thread without opening a space.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\n\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"dappdata\"></a> Optimize build for read only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"api\"></a> API Documentation\n\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"fa5c7265e4450c0fd90b4c2a5860f11ab77213df","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.6.1-node-1_1554727055246_0.6114624713957983","host":"s3://npm-registry-packages"}},"1.6.2":{"name":"3box","version":"1.6.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.6.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"aa4705dffc0e1803fdd3de971d31c61f9a1a396c","tarball":"https://registry.npmjs.org/3box/-/3box-1.6.2.tgz","fileCount":57,"integrity":"sha512-+fSsaVbBgn2o/A1Tikm4UDvZgUJR5hjICrKtmCFHZtta7A3e/AiEpxNFWcIrb8dyiPvCC8rpAoOCC0rXp6bNpw==","signatures":[{"sig":"MEQCIG5qbl3my0/3TouMtLzsruDQ/QRi0znaEl0BN8tuginUAiATj3Z8q7YafM7V9UA4UgFwVbtkMxqlCDQX1r4EIRHCkQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17088575,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcrLd5CRA9TVsSAnZWagAAyZMP+wftDHn92vKH/biv3X2r\nW+K2ebHhhXUiPA1D477/bjteaeBuoTiea8iDOztHXzSnCpgrUQNq1ycbobn3\nEnUR3mzJCFdvF8p/qlvlUGvt3qIlkkcpz6AH3Fc899Fl28naJGNbcnjrxVx1\nUIWtYNkvq4ebbUymLgyUgsGcflOrrycElMel3YDWyQHwo99AMX6+h9lH97Cy\nlIQ86cUX+oWfvLMRYCKOenCnQHlBp3Bz1rVie+7DDg0P8kuRLZmFO0bmO4yP\nFjYNZbQKwgwK16dFAOQcUERSweDwNg5RVtYnLbqI865+5PDhvitWUy01emsO\nhKLF7J8kEbvOtOEspTmQFLVBCxsHIkDXo6Ac/Y8zIrjlMrgh2ZaPd5PcwuMo\nc4Jue0o2+zt8NCQkwhxiQxGJnPg53JWmUdJywGnhU5w2Jt3AAa/XoLzvNeJL\nMqk5PAP7HV1T6lQUsxhQP68n4EUWsswgzqWzSgjbjjjnM6T2PT2vEa+Zsl+d\nrgqo9qU9HzzWjFCpzRAf0u2Jt4ooeLjwjzYM6CCvb19r4yoadGbwjOcK6wnF\nw1+meTTKLJlvIRDAJyUcIYdL10YMtyHcOIoHM3mZeIZ0lmKbuvcJ9ECXcPP/\nCUj2UA0shVL8LfG+uMIOr3Ryb9pjOyPOfMmfJjZj+F7v14nKKNQoJD+k+HpE\n0qTL\r\n=1wlT\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.6.2_1554823031561_0.5100354839827579","host":"s3://npm-registry-packages"}},"1.7.0-beta.1":{"name":"3box","version":"1.7.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"49cdc1443dc55ce56cdcd640f3fc19bfee3e8aa4","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.0-beta.1.tgz","fileCount":60,"integrity":"sha512-Zam/kDEbNpNS6Yt2rWJvxFK09jgMwgCOR90v5xk9gfZBJohM7d9ZvawYJ/sqv250/B9tntTw1YWsGjAUtpUBrQ==","signatures":[{"sig":"MEUCIQCSJubPZSbQUc6q8gGgJsrWY8e1LJSwjM3fpBHNiy1gkgIgDVaFGPg/BbSSd7s9rLuhMTuRWzvtJ57KN8slN+ya76o=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17110270,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcr2JXCRA9TVsSAnZWagAA7l8P/A/BW9VGuzox6s0WzRvL\nU+DbVMinFz5a9aAmD8whDmIOJLAWmFlhXHRmtWn93/hMlOhNjIsEcDZ4kKIi\nTAYNhqOqAp4Fv7VuaqAslF369hDyeEBOyjc+Nsl+V+fQG5XkJTxe+LiKhlwH\n0jWnPYVbDb9CVP9E/7ogZNBRyLtsr/4SPGRmlzeFP/U2/nQC6qL7/m5SSDWP\ncRWKNxvfp+DAohN9K5+z3VE8fjHIDanpXeU2dwuJ9uVKZ9B+4wCmCFj3F6mQ\nAButEzlAVryyIgCiaWZIdg9GtwFrXJMOLL6NP2HaMiSDEP7YSdZrhEhvKI5g\nQ97kmkXx+h1rfoFVMY2sLg0o+f5s0FyDH70kgU6rofY3mhrGOUbNRsdqBXmv\n7PXRMQGFOHL3vO+s69kN1YdqqWX9WYqcqMPzRmsr4lbmWOVlnMuuuIB0vw+K\nQsZAJ56XY2aLjGdyZUcNkLjNIi3Jhvr6kQqBDgkGw1AD4vley/XkTOadHjxX\n0mCjLf10NEKWLwrvSTcBGcc44xqDup0sGlIeJH3jGGc48fJW+L8NC5STwqci\nL1SQ4V4bXXAUG1XdAfGhH3MMZTkTu9OhnTZmaqH/wyP3mldsYKc1alvsrCpe\nHItZZIb41smfSHjts8r9AOh+b+BqOJcqvx/T3Eaap5TyKQKTCc21hM1kPVwu\na8hm\r\n=WlEJ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened. However reading data before is fine and encurraged, just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box profile data\nYou can now use the `box` instance object to interact with data in the users private and public data. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n### Using threads\n**WARNING: this is an experimental feature, the api will likely change in the future!**\nThreads are a type of datastore that can be used to communicate between users. For example they could be used to implement a commenting system, among other things. Threads are created within a space and users that join a thread with the same name will be able to communicate.\n#### Joining a thread\n```js\nconst thread = await space.joinThread('myThread')\n```\n#### Posting to thread\n```js\nawait thread.post('hello world')\n```\n#### Getting all posts in a thread\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n#### Listening for updates in thread\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n#### Get all posts in a thread without a space instance\nYou can get all posts made in a thread without opening a space.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\n\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"dappdata\"></a> Optimize build for read only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"api\"></a> API Documentation\n\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.0-beta.1_1554997846652_0.2534991910219362","host":"s3://npm-registry-packages"}},"1.7.0-beta.2":{"name":"3box","version":"1.7.0-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.0-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"3fe09f085ea3442d78c3c553f0c0f21628dce123","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.0-beta.2.tgz","fileCount":60,"integrity":"sha512-/lhniHL+60WUS1Qk9lUOmmmFhsrt02P0S15S9IxucgGfNqExmohaZj35t7eziRkxIA8kQaWmIPtnEEBWtFR2uQ==","signatures":[{"sig":"MEQCIAZo+alGzXwjRR6t+gEL9fC+iLag4O4LWEY2LRW8r2nDAiAPsi1ayO/pAHoqWQrvjNhCwBxg8JEx3x+RqGHhVGdgfQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17110716,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcsMPYCRA9TVsSAnZWagAAiZsP/ReRV9SwtL6TsiDSjl+m\nL3AGyt/gPRGS+6i6B0nxvfte0ioPDUZjui8RLtyb3dhSvxXzDr+5zo4UBWfj\nu3gx0jN2qhOno44UUJAqvmgTJJGBc60rBHXqxm0XUpNsk6QL13uNtoaI+1Ut\n57qwlBsB+tA60LRhznvmV6wbLAPjiE0RXvnCg4Wxp706tS58ZTRibEEOEniR\nRAmDctsplF0ERJw5CjMYcmA2DSsBxBM1SfLpPmoGBjxa3F49/TMYXwOj0di+\nPudeylD3HOL8uLKihQi9XP8VSR5A/cIdbozqrYfCySnDLvUvyLC/3OKzwn6v\nO8f1t6+xHgvYp2lHwLmfo7dGf3l88mIE2xcb8ViGIYtqpNker0RdUrQchl9i\nXGSTddnzUdB+VtdxGPHtiCsvphLI/1sqvwxTzxBho95ykkKRudeyJOi349TE\n8nMNVT/7ipJeSPMV3Uqo0PLxtKC8YhIAeEip0nOVewL3fFMpQJLohEEIaL/p\nEG6LLn41XkY0zIeZ+7CawYsHzD1OO92BGTOXCCdPwrSAlRzbIL14z4esnc37\nf2GgFR8JTA0XVFbc2GXfVwhOhSGgxYy6YBI02HS+xAxXJgEpChEwZu2kkOO4\n1+mfd13M7Er29XJfy3pDYLAhEfxz1K5IYNrjanJcuTVDG0hk9+OtEAR0rkaW\n5s+f\r\n=D8J0\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened. However reading data before is fine and encurraged, just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box profile data\nYou can now use the `box` instance object to interact with data in the users private and public data. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n### Using threads\n**WARNING: this is an experimental feature, the api will likely change in the future!**\nThreads are a type of datastore that can be used to communicate between users. For example they could be used to implement a commenting system, among other things. Threads are created within a space and users that join a thread with the same name will be able to communicate.\n#### Joining a thread\n```js\nconst thread = await space.joinThread('myThread')\n```\n#### Posting to thread\n```js\nawait thread.post('hello world')\n```\n#### Getting all posts in a thread\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n#### Listening for updates in thread\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n#### Get all posts in a thread without a space instance\nYou can get all posts made in a thread without opening a space.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\n\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"dappdata\"></a> Optimize build for read only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"api\"></a> API Documentation\n\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.0-beta.2_1555088342614_0.7233437153624269","host":"s3://npm-registry-packages"}},"1.7.0":{"name":"3box","version":"1.7.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"c43b91334154a64b382034d9b45199f2dc0b6584","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.0.tgz","fileCount":60,"integrity":"sha512-xsLH80IiJYTdBoGi7woyvcq1DsNzHSntpeI0LHX+pnXUrDVZCNVDv7pG63gjRNS9KCNo/1ApnPloLVUiBGhbvw==","signatures":[{"sig":"MEQCIGbdcCpwQcvMwAMdKXYvrOofnY1/b/6VSgteMJbJ9IpRAiBJhWGA6bvWabnXgAhUxATB/ks5qYjdb+q8ulL2i3a4ag==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17110438,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcsNHnCRA9TVsSAnZWagAAytQP/R5bDI7X9SDhYRxYvmrB\nbdXlzVKzRkzWxSlREX5IUvIO1C1ErCC2hM2LxDc1mdJJwWTUV7cY+pCaq+kn\n0h1uUaaT4XPJm97rgxms5EdVujaovU5AYzulCes4AwEm5MDKi9iJwpmYBP6T\nrlNE4HQj/UCXnzaC8eWTgql0GW2WMvtYDT+qFKLhprII50LSNFKTvs4v8EOK\n9zAJuct1OdY9dquo9Bpyuu0nn1RZ8NB22fA1ADtNkAQZX/K4W+EdUC9Vbdxz\nq13opXdqMYyq8vslr+5tX5rWY9tfHIcx4xie4Cv4JoLHXDe2/AEZCjvTiTzO\n5o4cmvdMuoLDOZ+xsjTNJPpZVa9yCMGLQEOOAYdl7XfQ9L/hTC1KS4YQwV0e\nb7oHozSNzqH/UsXwD5YTXryyOermx3I6Xofh0CyVevbKo+qMh/hEwbMIV2Vj\ngkhPUGKKW/e/5yF872q74QTnI+8L2BhKNpKdWMUtO0iVdFZO7L91mgVVB9uP\ny3Bk9UdYM1FLAijk3ZpDoBvVuTOR604RDGU3ZGAItlBtC9Njpe7h4rmPYc6r\n7hL6cxNxGpYvtz0BqLeD3ZYHUj9Hoslig1D20/tIh4wXZYv7BbVGbCq3Sg8x\nShAXy0qVCr7VFFqGORmEfyr3Flf6yY202dU/AjhOxXvda40xRSbqSb2yNA3Z\nIfoH\r\n=ka0K\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.0_1555091941694_0.9345291229453974","host":"s3://npm-registry-packages"}},"1.7.0-node-1":{"name":"3box","version":"1.7.0-node-1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.0-node-1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"7552649904bbe4cdb36559a4d8ba7078e1b0d702","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.0-node-1.tgz","fileCount":61,"integrity":"sha512-SECwb97noyW27BL4XMReflV02pMoBS+wlGtCYVTRZrUfxpGwsMpuzsxZkpP7vSWaa+tgB3p6xIMEef2mHS5KtA==","signatures":[{"sig":"MEUCIQCypLkTP076h6nzK7c+leWda6imji3p0sywNMCh6EJ3DQIgBhREJwUWLkFeqsfV3Q7aqoF5/igqvAZEgtiL6zDWHEw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":20021213,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcsisFCRA9TVsSAnZWagAA+pIP/2k7PYaeudRK7AqTcAGJ\nyj0ggAdJu9IQZeSwfC8itY2+iMg1P6WnqTwGyj9fqvPu6FW0eH9APv3hWnqB\n6qGqaS8n89vGUaCb2VT5TddQV43esbgq/VFAqVbTY0dW3+o9EDn5gb+jJNhy\nnMthc9bDdQ5uXLoIUBO0tWwiS3ac6Rm+nhI705JFKnObuvnihvNOQfEkoDUM\nesDqkFHZNXuF2Ta8eTFPdLuFbpXnl/Nc/atn4NY8qofCwh1P+iY7LwYawuGr\nAVJyqLy3CQ8BdTeHG0G6CLWcxEhHtaPSx0Bz6v3aaqc5+EKe/mzOPWrXcv62\nJ/obmId5BbtBW4pHt56Eb2PirnBY2b/QW4Mx/ona0PbHFuNGZhst80B2dkKJ\nG8bea8J9HOVQxH9OIiWlRsp6cctECijGN0hY0UPufWc/brJwaLsXyVbCsFDP\n1LvY5uLXoNah8LbtcF3COeZsbwYH3N9ji1xIHywf9d60u1cNhtEZj9zVnrY6\ng7tfXyhsmNM5fsyUdeD6njj7SIoEd6W5nLr+Ei+9W6BwHt39IIItSA4jY14G\nOg23VOhx5SP6A5Pc3nvE6OP1+kS6Zws2qYmIOVtSAihCF3ENu88OUCApYfH1\nKEI/9QZWytd6i2welRrDZ6yY5Er3CFWvPwhi+vHM0BnC4KLyu8prnqiMhVJJ\nZ0EZ\r\n=OjAR\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/uport-project/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/uport-project/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Dapp data](#dappdata) | [Example](#example) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n## <a name=\"usage\"></a>Usage\n### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n### Get the public profile of an address\n3Box allows users to create a public profile. In your dapp you might have multiple ethereum addresses that you would like to display a name and picture for. The `getProfile` method allows you to retrieve the profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Get, set, and remove data\nTo get or modify data in a user's 3Box, first open their 3Box by calling the openBox method. This method prompts the user to authenticate your dapp and returns a promise with a threeBox instance. You can only set, get, and remove data of users that are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### Open 3Box session\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### Network sync\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the users data is available to you. We advice against *setting* any data before this has happened. However reading data before is fine and encurraged, just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n\n#### Interact with 3Box profile data\nYou can now use the `box` instance object to interact with data in the users private and public data. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n### Using threads\n**WARNING: this is an experimental feature, the api will likely change in the future!**\nThreads are a type of datastore that can be used to communicate between users. For example they could be used to implement a commenting system, among other things. Threads are created within a space and users that join a thread with the same name will be able to communicate.\n#### Joining a thread\n```js\nconst thread = await space.joinThread('myThread')\n```\n#### Posting to thread\n```js\nawait thread.post('hello world')\n```\n#### Getting all posts in a thread\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n#### Listening for updates in thread\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n#### Get all posts in a thread without a space instance\nYou can get all posts made in a thread without opening a space.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\n\n\n## <a name=\"dappdata\"></a> Dapp data\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a name=\"example\"></a> Example\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## <a name=\"dappdata\"></a> Optimize build for read only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"api\"></a> API Documentation\n\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"32ad00d2ce831d9d83c77805122314c5984c8d5f","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 src/*.js >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.0-node-1_1555180292081_0.12277994577297657","host":"s3://npm-registry-packages"}},"1.7.1":{"name":"3box","version":"1.7.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"91919271dd9afd7aef06fdce4a035c5ff8459765","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.1.tgz","fileCount":60,"integrity":"sha512-sZoGN88ptwQ97LrRlfs4b0ThXlkrs+5rGXFdPXasdYIJT+najxwfhLIDJwPQmdMgY/kQbxnbRkwSeHxxG0mi+g==","signatures":[{"sig":"MEUCIHwXS2AcP8x1eNlyRkI5/nPjVqOMi7WMFxkZPru1wd3ZAiEA58fbCHZQu9IjOyjczIWcbHtQJv9A4yNbo8gNPK9yQVA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17144616,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcwdD/CRA9TVsSAnZWagAAUpgP/ioiBx0Ysq1DkxYA4By+\nq8CUmP3Ku0j94wwcuAkHoVUHOSAmy00GZ06+57oJqigneKWZnC/71Fh1EC5s\npKxHfozQTOI4APajLgGlpPfOSpzWTotFUAQmk6SWK0eO+fvg9/GGNHN3k0nU\n+T2VRIqpfDtO4qDFp+9M0uK5oebnKXipmE4HGZHFmJ4HMlvToOcpfkWFED0b\nDte+/yqeRsW1zSJGPOoBjWKgJlGyWY0iR66AchwvVotXXtLolMGU1yXEtwWy\nJNdB4ZmbUjZWN8A7shTKKfX4Kxx8qOk64vOJpalsuEfxjcY+vij0jefejDVR\ndVpbHiHQL8j4xynkO5zM9q9KXLBRhL2zdR0GJsR8yob+cP5x7/54ijhQC6uD\nHB8oVuThYvV8Q9R3A8shKnnstTLn4Hb+UHzLfGkddBUK76k94vfW8mS/20tq\nagJTYkIGVFyEcGHVtW+WocAI4DGyHVC0Kbahyl3rA8nFdg1oE7NCrdyhaGlo\nlP/s/88hUyH/ogSrKcAIZ50n6/2QVb/N2ftKMlqv+Jz3UbBvVlwferUPPa4g\nxWa7oqKfOdySf23me+B3FYiI4X8hQPJ6Q3KgFuvhDHMh5quBUoVZldE3yJDm\n+Roe9LfSMxOc75hDsrspEMG55o4PVkyb+DqW/wtY+eeKs2J1yTP2FTJdjn89\nSgUH\r\n=n9tK\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@consensys.net"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","elliptic":"^6.4.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.1_1556205822456_0.6662498779669834","host":"s3://npm-registry-packages"}},"1.7.2-beta.1":{"name":"3box","version":"1.7.2-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.2-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"a6b5ceb29af2ea16a701a273640c3e1e4a9e943e","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.2-beta.1.tgz","fileCount":60,"integrity":"sha512-JCR5TXrEWJDeJ5bW0dhhmtUWo9/zAfS1hjMSVF+SdR2XZ74eAQnES+qRQvbuSvlTIWaP3HjEGIME/nzVVlSfOA==","signatures":[{"sig":"MEYCIQCggJUaYYAoxPVWBtvPL7xTnE+oTg7TLZZbtchbw0NrUgIhAPm6cCuNtUvy9qC82ChaGF3MPaKD6ZkeH9aQhX/O8+0d","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17128684,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcxt+TCRA9TVsSAnZWagAAqFkP/jF7oWHdKFcVRKS7NcJn\ncXrVzpuF/W7avVsZoi//5ElQkqC7h29qzk2560kBlMdWwrLfExcyZv7BNViU\nciKt4Ld8wchMlJoft+uyPiTpj/1kRB/dTFd7IRAqFVcQ08m7z1/rik5g6HbR\nRXi99ctgLGPOpE2u3EqGS9xvcuBWC3MAi/v4GV3FBq0DXRFEiADOl3kac5PB\nK+C7tQzcuK2h4xE/MKRk9+NU1YxEjE2ovPPMtdc1tzBozJxFt2UXHk+SkPWa\nplPLNXVni3SWhYS6ae52M0wWTGIBKn9Nu7deS1Sn1d5kLcAZl9e1ZGyMgHr9\nEIfRlPJzhm9KsVS2JsJ8s+J13Mw2FXjgp/peFd7rtgDAsevb00KU7qiihyDh\np+KW1nh5nHLjSlNJ6HpR0Ug1WoJbfLRKKzY5MXG/Uq1YFcDt9R7TI06j1c03\nl5I6uIf4cZHRz2K3aFF2xqBhQjMPVbkYePAzOWDrXUEAn3dpIJyCwPpTSFwi\nkWd7mQ++3SbroaJ1zf/v1yHDhfeayDlVWFDii8MFIW2Soxs1FY1PJQ/Rk7wl\nvLCvrb+1cd6VTC/HmZWWY3jnHaLiJ20DKqIXhAmIPOGLTmUU3K0UYGxuvI2w\nXfEjeCswGbNGeM6gIfWFJYERNZFXTt6eAIjROlax7zCfiygqbCjWY8A8cCBK\n5dsv\r\n=IHTn\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. \n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.2-beta.1_1556537234615_0.1677214219630072","host":"s3://npm-registry-packages"}},"1.7.2-beta.2":{"name":"3box","version":"1.7.2-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.2-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"bdfb013a116c164520ea4a6a8ad0c788a1727f73","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.2-beta.2.tgz","fileCount":60,"integrity":"sha512-9ILS9RCqtP7L1YOUtBu1yWMHVqES/mpvyjnPxqGUPtLHXViw7NR3YNWBR5uxrFGt626RwWSSZgUFfIpJQb85Rg==","signatures":[{"sig":"MEYCIQDwfzByKOVmPRdTIUvI9EFKlXEuyQM3cIn3UGTDnMgznwIhAPpO2kS1E4ELHSbaDIl2uYRsOlJ+OtvHAV5SM0onxENj","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17128720,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcxuF3CRA9TVsSAnZWagAAiW8P/Ay3T/IULmJUkKad5ELf\nLw0fXM/i3Gb3AIKvr75JrkS62kAaKIQFnfETiH2j6o4ynA++eN7NTqODqYEp\nrDI3xN4EvH64GMVZ9GBhK0vKDO/loJEkcLkO4T1OQZ2T0h4kknXRVxfTXPEj\nzkXAiNFfu6CnuUQQ2COzhB2260aSjiY1797kYzK9dPgkLJVbn7NV5owus9MC\n/kixlqIU5ddI+rkNdSWkR4KiR8iPaemud33AUUoFrJdMbYZ9ZekQCODBPIzy\nul96PxW6ZTBySm4r1WdPZkQDD4wTtX1PWAcAOTsgV5GOc7WO//IZdN1Ssza/\nyKs6De5D5Z/TJnFpUQODrfFphRdQC0DxDlnVFJrvMzwJIJQ80ZKpkxqZWYIx\nFqe1e1kuMGJtnPF0gChtH8YsoQfKARymx3J9LWD/B1hXWcJ4EAzpui4iIr6b\nNe4TVb/DTDMVaFwH6BnDw1v4/B8XXBzuD+bGyXkliEmkGUP9sNOsF6I0A1Do\niJrMj1+p7oIFdfxwuPCBlCnL8v1Hshjo40cms0dcYBKUo4OWXMVQyB0Zdyha\nxsCaf//ykOAHHInB/RsNgA1Ny1XQkUnK0Bdoz+ZVXuX+FyRWuMZzo6AsBJ8X\ny0qlf+Ky7ZOSGNRtlZhqyU4/d0lphN7ATn4YxdGFUsyGbe/uKWJ/4oJbbhS2\n8VB8\r\n=q/Lk\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. \n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.2-beta.2_1556537719183_0.6037286872354091","host":"s3://npm-registry-packages"}},"1.7.2-beta.3":{"name":"3box","version":"1.7.2-beta.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.2-beta.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"ecbea4f53620dc261dee0ea8213c0e384b691e4e","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.2-beta.3.tgz","fileCount":60,"integrity":"sha512-Z8wt/N21QluByDVH+/cBr3fOtLE8dCcCUQFd7A29pJRl9gVM1LvQc//Qb+A0hRVJXU+sTeBWdvkhUqEMNhR49g==","signatures":[{"sig":"MEQCIETfsO00Vg9svPsE2xeNg97J04ZvJKojQsoDWljPkviUAiAI1PeTVaAoD0YR2p8R8NAswgIN1QgbB+FfOxeohwJSXA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17129900,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcxuQkCRA9TVsSAnZWagAAuNYP/3EB1TStUoOjw/VY0SHw\nhiw0E9FdZXled9qAutOWQZoiGsSMZ/szqCJVCtZHMeQ8rqkokli48lCikXsz\ntXVzcJNC22D5vSCtyYAuURI4s9U1TUGK3+x+l2i6uL4gln3GFu8YW8S5ncy3\nQHAHzRf+LwWdamoUZJKh3WNWUsAXqA+0T/tO2ewBIRkY12iTrrdRLxrcfw+1\nD0kYQBa3v8J14lJp/xDn8QPuGySj9JOqWjJ2+0sCMdOTSLPl0dmlrzXPeQFt\nYp0K3tQxQJhlurdpU5KAmkPbmf6FAZFdgjP2DmBk2LA6T5ra1riHcX7Cv1le\nFf2sIgVqMrFW4u/Q092j1VNpwIjVmaDoWmvXOX/lwrOXsFnHBTCYaH8Nb2ZF\nBH5pQ1Mzg++5cgbVpYl+xis3aQXsOf80Jeutlp54NPrr5ctGOwa5yuCrAC5y\nsMCoxFX3BKvT5lQgrmjnxnpNnv6+91kVZ12Y87plzEFYt5hqGS7B6B2arXSk\n/R/rmMt4UOHwHUq1wRe2GpE95IpQqi4MR6Q4/zl+YC7W5GTkyR6rXrmgH3cg\n1lXjUczE7BhwO156ps4LFoPEIqkMhD29iZDzHZGNmB+1zqeve2RJaXfGP35e\nD4S+CvjxeYvx9ohKCMkw1XCj4IggGRqtzK3MrAyT3dWBzYSAjz89em2Cb3qr\nXrwu\r\n=OZdE\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. \n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.2-beta.3_1556538403423_0.7058402053575386","host":"s3://npm-registry-packages"}},"1.7.2":{"name":"3box","version":"1.7.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.7.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/uport-project/3box-js#readme","bugs":{"url":"https://github.com/uport-project/3box-js/issues"},"dist":{"shasum":"d1b14c75c9c6b885d476f130315dc7212a8f9631","tarball":"https://registry.npmjs.org/3box/-/3box-1.7.2.tgz","fileCount":60,"integrity":"sha512-E35tvDdwi/AgnV0QidUiV0LFS9ouNn1ofnE68dX0TGnugwC1Dg9Qiq44C0DtY408hitGqrmnYTQbJjICrjZx/g==","signatures":[{"sig":"MEQCIF11qar2BiRvj681o+nQXg6xQO9rH/eUnVQ3TjS9bPGhAiAfCU48dv8y4iRB6RtkOP7UXjoIpcG/nVXJhZkuGxTXAQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17130064,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJcyG3mCRA9TVsSAnZWagAA/pgP/jNPZqblT52O+HQngeBV\n1Uz4DdkYJ/+2ptP9pNzlIg/l9Ni7Vlo7QF8DuCYWV8oa3FFpJrCRi2R52R29\nEUuNzRNyqvDq1iu2X7OvdqNR4eeTBy/dFxDnjsJ4je9NY9f7GltzrEhedvHT\nHw1m+OsaQED2hcvepjhtpBLYlWXYYfDlP9pjLmzALKr2ch+8ngA82jjhoojP\nns6lVmxwTXd28QOYfSSHKDt6EzMREssGFETv1zhIo8qIVpnPwvwu4GcLVGLI\nn9ZtJdqCOFp4i+/wTcyl2XEsQC+KOEadUY+PSzopsgp8f/moAiHSavmWee0k\ndeKF+v6rBnHlTfI+XEzYrjqkqrdGjoQuLj5cojKCn8khzAMvqgKvnl2RsfF+\nBADpHg/UvUYN0d59rCkH8+3Xf+Z/GHOJ575VyrB1gkRqoRxDcEqJ5TCvtm8J\nK7M131rwMfxd7+4itWxx+SFSaJuFMKfieumxmBlShczi6cDc1JCQAzwnaOao\n8iy4HT2z7dYjR0yUj0G859Vf5R7WHL8X9cqSJdaGqFDwk/8QHwmg15yOs5uo\nvNPSq6S+tXjZMIX70s8vVi8ms5z1E0nmOYJEtsWEpORIfbIW9rmbk5WZaWF1\nQPGlXpgmkXH6GVyku+I2IuDCUIgx89D74OjndpDSpHnzcTeNvV3DDFxLwkn4\nXTM1\r\n=pFOg\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/uport-project/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.7.2_1556639204760_0.9319685924417309","host":"s3://npm-registry-packages"}},"1.8.0":{"name":"3box","version":"1.8.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"a6de03d390741667306b7e6901907f34d01788b7","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.0.tgz","fileCount":60,"integrity":"sha512-n5x7Imix5o57Rjz4mChZ/LWNHt2kw/8gRvzBQrJll2IfgRNUGgUr2jGPLMqz9yP+F0/goiCWiMDmlKF8i8PH6Q==","signatures":[{"sig":"MEUCIBKBZ86pGUhtyiJFsuiMAjJd4+0sPTEvKYN0Y9/mwu7GAiEAmIAUHAgF19qTMZSiZpDNXb6TinCajrA4JMVo5ADA02M=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17155168,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc1CDmCRA9TVsSAnZWagAArvUP/i/C6EGiwLBU7nkINCss\nMN14x6L0nI6tweRNAUJujXGZCOkumcnhbm4ZVDd8pvVkwgGXIjqa9MI4nbr1\negagTRksdAn/HRAyvMsTW6sBumEM8Ro02tSYIaXdRB/OsWV8Pi/2KGogiFAs\nzmWDtjw/ugqmQpFcGmuNGWC1FUa9sjJGsswKLkZtykyHmb9FPulk3lTnqkPz\nSMu3JCRXsu0q91YziKf41fJ4Z7SXrUafHPuxszVzq/4LyiqfcO8JRTv8noxd\nflct+xxLh7E9PLM706zk8arUuAeYouI87Q87KV42QQ3/phz7RDh/2ok4hIxz\n7panWuvEmbgDCQOjUeRsZCkHq5KWhcX8dTdWL3Ab+2dzH3Pu0IxsLgj8/dOB\nQdSKbhd2GOqCDq18C4Nr1b1NjuaygxSzoUzs4RFbj+kTF5ShVtLiIJJ9CWfl\nExzxbACf7F6s5cjsMhPbuuv2//yhV68y50K3rvHmAM7/7v+eKLfUXiFCHNPg\nEzi3uYipZBKknaHjKyqvEOwU2QNJsVCom91YTHd/hAfnmaOY4jRrBW8iRScr\nGx+DwbKNK7hHPyHD/EX6FnaeaSE5ChIGbTogfweZXJ0fIok74f4j5GQwX+Xu\nBtv/aA35HRZcj+zWo70SUcz+I0ohcLoU1+xmscIxc702uNz21sBt4DB+MMJD\n58yl\r\n=GEED\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.0_1557405925103_0.08619664034045438","host":"s3://npm-registry-packages"}},"1.8.1-beta.1":{"name":"3box","version":"1.8.1-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.1-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"4e234138a2931196b700c76eb6f71c528343e000","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.1-beta.1.tgz","fileCount":60,"integrity":"sha512-nVySuBz34DovfqVT7aq7auihQaZgpyaKTSMtjc9BXSqQwFHc8k1hlcwyFVvwF0pCgKHZEMBa5rgcMHQyzo8HsA==","signatures":[{"sig":"MEUCIBaMshfD0HFBnNwo4V1FXrw7su9v31nJITDsE1dvLBWGAiEAp0YLXP5P03wGUHUgagTAsP8dYsBGS0+B4q0559+MT1E=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17155174,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc3YW3CRA9TVsSAnZWagAAh/YP/RvRM4lgbVVbgTS++TkZ\nSPy+blcUbPRTCtAXJCLr33NOAg4kYV4zjuOWAjd/ZGUyuSHkYOu/s38LKE4I\ndg5lYgqOIf+FtAO1UD7Pllq1UrVIvz1s4z3zRiA4A9brAVZ+li7lPojEdX+2\nvX4B0BwvCi5mwCBI1ycs/vTMK4zl9Ckp4lkkTF9xEE01ffRm83NKzY/moXYw\n59CiAe0bQfiBFBj+JHnvhAB+et65hgBAwP/o8aeRv0zGpzwyyDJ8gxFjNTbq\nWQYcorJ/tIoxufPweZfkma3a3ssJ6aBiD7rHzq6PNg+Bb+aDoXp9ZXXPhTbd\nU3PPK4FlQmKGFiZayjdBZ41s3S5q+DCHBYbI5v1KtL8d4n+sPGrVcAHRad5i\njHtFwShqve9mRwiVqNGOqtH07dBaMSZZ7lQADa2R/0P0s8ciYFx4LDEsaIrC\nvDOg31T28n9spxQY4doBETBOK8FbOqlm36Ysk6dsuUZzcPQ828n0vNsoZhP4\nEczQBs1d5VTmQh/DupZrTx+qrJq+v6thuzbvAOga8RS/7Ubmcmn1QnhxPRVY\nNX75HzgkO1VE21xPkxAJ7e4sEJrQ8b0Z1yP6+jLu2gyNPC1t6qqNtWV6KSDd\nwLFNBlDjyyFg8YzjjBKXF2C3KotAIQY5GziSbdPive+rwJeldgG43QZGVOwT\n8cSQ\r\n=8Xxr\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.1-beta.1_1558021558689_0.37535472767854006","host":"s3://npm-registry-packages"}},"1.8.1":{"name":"3box","version":"1.8.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"9cea84162f505b18bb8687f960375ee14877ff57","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.1.tgz","fileCount":60,"integrity":"sha512-xt72qqROF8FPuUHoVa/NTH2bek/LQ1wWYlB75aYeWp2QV3f6867BvPRRtISwBpLMsySHQkLdTNGUDmrUiYHgbw==","signatures":[{"sig":"MEYCIQCByYkEB8Q9IH1E3lm18/y49xuYOdww7ibYqVQgDaehEAIhAKMke8x+boCvZnnZKQEMuVcxJlru/rZak8qALsFnrHUx","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17154681,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc3bD3CRA9TVsSAnZWagAArGIQAJzAghczRg0b/Wasv47j\noIEaNdT3dwAY+tuXsPe8qbn7/lUgEa/Lz2yIcB92DyFy17wb7S+FSS4FpIk6\nm/ujxtRSbgSW12sZRJwOtFE7aMr08FrJjf6GcISDFWCYsT8nip6ieM413rVM\nFPg8Ox86j5C65slj2uD6smWgg6SGyy9qBUU7z7JeW45MJw5vLqUINPEUQ87H\nJCriIfHk5GAiP8/LS59thUTPp1h/o/62yZjdPn8gfEZnecxWViPEmUjALkqz\ntA9tJrLuLYgJ8pKzEWSECAA85zZ1hbZYEKUvjSGpOFNCk0yZlnGRotPF68Qb\nO6s5waZopK7BTB2Qx19jNlauhYAtexItYlGr/jMMtNS7KBrsppe4tJT4gb6X\nHnx77PtXivKFRDiLUPDTCT9alggF94cIoOnGtJnf9kU6FZG4E6kIqgoD2eap\no9/I6QrhJHSlhdbaJhMDi7TwJawoMrGe5aEPH/oFv3Nt7gVXnresMhhDyyhx\n5rXnFRaTDLlK0ApJjdRXqclLdsaiEeteBe1HMVD5gkFFBPIYTcgw0bSNIs1a\nMf3xARnXFPKg05LdXR8tGf3UHql51jcyQNRF36sElNhMk2yM9vKJyAbZuXW4\n6dahQq/5VF1qLYCgtsAsL30MHIt4pq6ovPlITrD0uufWtBZ2rZkEwnxg34eM\nFGCW\r\n=VQfW\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"cd374031c6d5c352cfaffaaedeb1c30b6f16b2e4","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --detectOpenHandles --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^4.0.1","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.1_1558032630610_0.9406030922381641","host":"s3://npm-registry-packages"}},"1.8.2":{"name":"3box","version":"1.8.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"778f3526455138330068c6b4f93c64b7378870f0","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.2.tgz","fileCount":60,"integrity":"sha512-7S3OH82qvaENZM62T8y0MvvOhoS2Ws+76C1JInsyvIXriOQ9X5mUzxn6DoHqm8QpsFNmtVru8tjAuHHR8AngMg==","signatures":[{"sig":"MEUCIQC2CmOLLlRnWPDk3nW6MZ2rwtLypOtTxTtRoN8mq61i+gIgLRm31C5te/bieUHLOnK8mD0x9e1VYgZWibKq97IrS3M=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17163680,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc4/gnCRA9TVsSAnZWagAAquMP/0y6fnWWYIkpaS9luKv8\nitlw9pkOjHQXdUpe9il6y6tz3YSUihrvXgwDV/6mAAbHCGL3y5TU3LPcoqVd\nBuct2xUXOAU8IGNSKzx/WLVftfyILy6uZSk+T5voYmOHjlvqRmLv2RIcIlSc\nnydZtTaESQo+GfGqXrF//6WQ4J72M2ERPbITf6fMI/UjWIb5riP9sB83rHlL\nBjEB+wA/r1PHSWipvDmNm3jmjsClESpg7WyuIGJAqyWc7CRieSlUwtgull7Y\nSky0jnyX6GmWwho/baUSQ+EemiG+FdlZ3FwKZh9/+kdqAtnCaiRPfYmxll9f\njWE95p2wjI0hAsKLcg7MUWziTlh6DBMBmEfDnq26n4i/OTVKrPR31kL7Ae8/\nCtiAcdnGXZ1/ZhqD8wlsjlphYKBMnxwAe31wCpb5sxhHppoLxgbBjPPw8B19\nQ0D3JQLiwaievN/YblHLqh4dw1gkNbboXUldQ56+HTRVLWKxD7AXjq0zhkLX\nmxT4MwGR3oVhCbL2zSzOMnvQURAiFMTP2R2mT6/MsdN1zn5ZbkZ03B8uuG3I\nItDIAqCTisK38o+2LO5GOpyK7ZPTO1VQnyNBnrLRgs66aoSqA2HY6MZ33UW6\nXVMO8Q/NUWu5UpeCQRCTkZXaQz+dIgekviZSc0ntd3CiXUVIgLsEHd/8jprG\nENxW\r\n=TfHp\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"980f1314f7e1da39d8af177fdc6a1d52ecc55655","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"5.3.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"8.4.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","webcrypto-shim":"^0.1.4","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.2_1558444070278_0.27888610903467836","host":"s3://npm-registry-packages"}},"1.8.3":{"name":"3box","version":"1.8.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"bff620812117c92067c319a22e25242ec14b1f96","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.3.tgz","fileCount":60,"integrity":"sha512-1ekuLgK7Hur88aZIfNn6yZ+zIbvThpOqln8fCdiYh/5++V0ujrDLVUevjN8HDGvdVmFLaBOv9GRLVP314yJGjA==","signatures":[{"sig":"MEYCIQCktj8M4uL5la49iXPsBuUpYTfoz864BC67SeLyyCkurwIhANo948UDQ9QVQH7nJHtVkdnL8HqYnbLOoXQ0uhp9hwp+","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15222973,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc6BJMCRA9TVsSAnZWagAAl4oQAJSGBVSsE7Z8CcazUgQB\nbkqU2CaBeCEF92NHIQBQzM0ZB+ri91T2p7/H6wSsVK2PcN1ilxQl1Z/Wl56R\niiL8fXkbJ9wJZNC9Ik9OoHTNtTW4WFQzzgKOaYRDZRA2htN3K5BAP3PuM9il\nxOGRedrSsi1BJHLaA+z1jDTvaDMQ35+8qV2eqZPsyPbZ6wkpLnSpb6Vq0QTU\nof4WoWNTHnd34bKwZVLKdk7nREhWakdx8KZMtAhAX7TQjNkGPHARt+O/Yhu+\nr53UtFjUW1GEVzgztqCqftXDFxp5bytf2gu671KZOEJOBy0XZBGUcIgFHNUd\nNXh38YrRxaQZ2HYZgkOChy8MgPDHXvmbryDib+b+Te2aO5ZujcQNXjcqeedx\nh0r8AbL1PucaFV88Zp53ipLA287U3mCgEDfYbt4fI6XnO8pK1n+dXDy7C+Io\nBbn+x5xsfG5EP+1f1DrynuR7O632/1w+Sy1LV29CH/UxEzkLT17Pb0YnRc/Z\nuYBiouNOUjGuwsKtBSFxJ741lvHUisbsGoFPvxBi70wHBsXOVP50Uz9nBwEX\nug6vrnm9QL81dHgwgef5es4jJTbdh6jTXG3mz9K82WsFcdnygW1VmSvLGnBO\nEoJgYuUI759HYKy9EePVi8RBvYNSsp9y0g9rfCq3BTqGLESM3S9CpZS8m2/I\nMxkS\r\n=HJna\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.3_1558712907991_0.8869637870066118","host":"s3://npm-registry-packages"}},"1.8.4-beta.1":{"name":"3box","version":"1.8.4-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.4-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"2cacc23f443e3bc4b6762f60dd2337dfb9f25893","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.4-beta.1.tgz","fileCount":60,"integrity":"sha512-Y5y/cU39L2nJ0eiPd5AFaLoxXvgllusaDxDTCvOR8UEj7IxRjCNI7aMyimesmagJtXTvOAb9XX68WWhGLh6mHA==","signatures":[{"sig":"MEUCIE3oH4UF5lIC0hP1zmCAUtWnf2KVSDkZRiV2CjAL1TFvAiEAuECagA2aF20mNb0sXGLN35GBcLn5lrAct1bf2gn2bh0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16019129,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc768kCRA9TVsSAnZWagAAp3kP/385TKiVXLtKU2aPZkLd\nHHV0TIuRXDrRlnrdoGd+VvPAQ+qjovyl9QB1IS2yyOOjCKwMz+0XsJk8xAEG\nWf242PJ42Kdu2zd7/XZS26dzLsbA5/AEHLX7/WMGc8sx2xYIeXN+ebMCiD2U\nMzOfroAYzHlZa9T9fXgI3/7B5iTRYMaRRWYg7OKrfq2EcoBodSodqGdqQiDI\nSQpCmqJIhz8Ii3l4sUhDSNeQoTtj1EpPPxEdnRxpftB6l8hfdbMDhY4i7rvw\nRGDczT51FXDrKp4yZlKM3tPHogrHXQDwxZp/bB0mqtu2AKy/xANdHErfM0mQ\nPuarUcgIgXOVXC5j60Pu5TCYID+X1vbPQtiaxEYoN6xASeiECsDNkUAAKW9T\ntxNsGnkyh8Oeljf1CBslg1aCASb3WlUF57vhpT1904Q7FwgAfIBdSC7aDDej\nzhMh4b1l5thddeTlVfGueo86tXG/5tq4OHeWtU76rH/7z19nWIvwS2rc8Ixq\nOinKWZZF2SyT+TVO31bDPN2NCayCUp2W+15ncTgeyZHNWMkXxTJ8isrlFdJM\nTIqzqcAC6g629FUGqwSRy7niU+vXQJAq5MwIzKB3tCob6kMjqVeGr4eS+5Ak\nbrCOZuf2OBtLcoe2acmBNH9iFuDsIwNbsmPDR1ZZ/uXLUgwVxEZzjJvXoprL\nyBNt\r\n=IIi6\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAccount(type)](#Box+linkAccount)\n        * [.isAccountLinked(type)](#Box+isAccountLinked)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAccount\"></a>\n\n#### box.linkAccount(type)\nCreates a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default 'ethereum') |\n\n<a name=\"Box+isAccountLinked\"></a>\n\n#### box.isAccountLinked(type)\nChecks if there is a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default ethereum) |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key)](#KeyValueStore+get) ⇒ <code>String</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key) ⇒ <code>String</code>\nGet the value of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(name)](#Space+subscribeThread)\n    * [.unsubscribeThread(name)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;String&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(name)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(name)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;String&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;String&gt;</code> - A list of thread names  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.4-beta.1_1559211811817_0.6934236930053839","host":"s3://npm-registry-packages"}},"1.8.4":{"name":"3box","version":"1.8.4","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"d03568f5d9b677b5ca41b6e520372f095acf622c","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.4.tgz","fileCount":60,"integrity":"sha512-4yVTht6jbebuUtvZVHerx8L+Hfv6PB3dp+z3xvPPGhyDF+WAvnCxOBQ33jaN2zUQWI13rtk1iR9oivgyhS7GOg==","signatures":[{"sig":"MEYCIQDUygNei/hhA0tAY35FUDeQqZwdw9Y6KrgvudaupuKg6AIhAKDDO0JBA8RAi6cmfhZ2M5BqW5MUUxeF/TCEsXubGHw+","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15230126,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc79AOCRA9TVsSAnZWagAA7S8P/jF0rGyapYidV5L/X4tW\nxAqR+YAgoUDRz2TBz+M5LztDR/RSEStSkpngObgoo+ui42KOk8B00htOMk9j\ng1LIGBSL46FmfEfxmqLdKYmZTS2U2qHol9738OyOF3VxwWsZIfFtgaLoD9Iv\nbAa9NdUWbjSqlCRbj/BHC/VDd1S2u3feKEUa4BN+lENFQSbwf3CzpWGkb9dz\n8kuNIUte2L4UIQtUVbEwXNJO5B3boJ6qtZ+8s+0NnzTz1p2eQXE2V/lt0XOc\nIhDrOAeHbIfOrhDr7E0LQMbid7s/5QHiZDZLKQ5fmQ1O/GLxuweVb8nDnwB9\n3nVUKm5mM/okw1PbZP2toR8qeAbvSjOAwI8AqheaVE76wxwOknfmPvyc2qqB\nWcOTqGR96KlTVP7V23FKZZwJxiGUu3asCtRB90zpH1zA5eHeDxOhYmpuyKYT\njUjrd4IgzypscDGBTNWkV7Lzz20viF3UjXBM3ztnIdnfupQl61qi5lWScRjY\nHgJFp9ug1kG3PLJglADtwcfblDZijrSiUz/kqUjXw3sBd2bmufSBQl1pyk7x\nFBTKbXl1S4l9wFE+PTGUMjn/4mw7cGATNHFCy1M2NLoXDsuYj27KBxE/q3r8\nLNkhB0ZbWum9zSlDVbjmc4AhUcp9fZwZoPOcPp0kk/hlv0RHfyVivzwSE+gX\n0iKX\r\n=u2Qx\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.4_1559220236369_0.8225896150954366","host":"s3://npm-registry-packages"}},"1.8.5":{"name":"3box","version":"1.8.5","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.8.5","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"4dc6844ef61c9c28849419756968632c83502f96","tarball":"https://registry.npmjs.org/3box/-/3box-1.8.5.tgz","fileCount":60,"integrity":"sha512-Sg6mGLHnCVRObTBSXfiG4YW3mtqkmk9D1q3B/lev/8S/EzxwjV8w/gitewTOIWHPnzMrL9kvWfjN2QUh2WMsgg==","signatures":[{"sig":"MEYCIQD3v3jn7Gz0MErQOtYV6kTf7YdpIgS5jHlshm22OQgqjQIhAOQQ9kHdgsLrvYz0ZpQC/GBSAqjlm1aSVaJCuFhNoAvl","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15433895,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc7+USCRA9TVsSAnZWagAAdvsQAJYzKqk1mc6nw+n9Xr3A\nfWlDNfnkul1UcdYVtofspgNSuJm1nttLXv2DzTJww/kpof9iVc7H6VLiM1Wx\nae8dOdTwLSmSIqEpoQg9SpOnvU4QXccIIP4+1DV01+R5Us/qOFrHNQa0ts7Y\nt6hd7YtgMCatj6H1oZE9RVGHt0Ose9Y/ya2IDNRespDu/5X6LuBNBZ28AgMQ\nTNElKAq9VWvyqLqwQyUOjxey2NTxzsnO6ewr+Vv/GzmZ+bhomIgYlaMliwt5\nE2zCQK/9nkJrPSsawDVO4MaZNN5SJ452fhGFu+tcOGGY3gajzMcN6aSA1wAi\nBihl9CMYgKG9nGI1nKi8rzzT2lOvaXkHuc4pqyUxHnDYIIjr5rZzeO06WSYB\nBVjfZw2AHjRERK0bhqKcPWfnITg1DNyQX7nlAfwe64Z/1eckwAs1mp2AmjoX\nF1QQfivFWJhdR5ehAKdFbb4MjEQzQlWL8va3FmnfPVXjeMhDuUTbyilZD19u\nXR7NwX49CSGyuD1VXdvCH7QnxSK9V/GFfKd0a2xNUDfdUVmefinZzvYRtp38\npG+YScX7ZcB6MAteQT34SDpoPEIA/aR2SIgQSrFF9wUeB+BO3D+O0zEQqfod\nZ8dFRqskizZHNdXG+EPilFchoS/Ok04T8tQ/eWrVpeOnNx47ttaVa2l6La5J\nMnN4\r\n=bPlj\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.33.1","store":"^2.0.12","ethers":"^4.0.20","did-jwt":"^0.1.1","orbit-db":"git://github.com/orbitdb/orbit-db.git#dddb271","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.3.0","@babel/runtime":"^7.1.2","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.16.4","webpack":"^4.20.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.1","@babel/cli":"^7.1.2","babel-core":"7.0.0-bridge.0","@babel/core":"^7.1.2","ganache-cli":"^6.1.0","webpack-cli":"^3.1.2","babel-loader":"^8.0.5","@babel/preset-env":"^7.1.0","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.1.0","@babel/plugin-transform-modules-commonjs":"^7.2.0","@babel/plugin-proposal-object-rest-spread":"^7.0.0"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.8.5_1559225616847_0.8364542992415458","host":"s3://npm-registry-packages"}},"1.9.0-beta.1":{"name":"3box","version":"1.9.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.9.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"1f7fa4b9625d2db457f7ddeab6187fef93bdce20","tarball":"https://registry.npmjs.org/3box/-/3box-1.9.0-beta.1.tgz","fileCount":68,"integrity":"sha512-xwngJgmEk7gbOQoqKTQ0wjzOZU/YLmoPDRyKbd9TLAxar4IkMxKISo8pR65BKGK4P06UgX1kaCtc6u6Uawk0Kw==","signatures":[{"sig":"MEYCIQDpHTtU5xtBXnyjKFKvP0be2xhhyk0c9VoHdpsAHhYGzgIhAK9SWXrQhuSCwk7skeUQDv9fQ4tJRCzvSptVZQG9S5Ne","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9055733,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9k/CCRA9TVsSAnZWagAAr+sP/ia3H61xcZ3U6YB/4HiD\nF6TPJPmSrlJKq1ojutYmDQxsGRWJlP9XA0Ey3dqMRrL35dBLjWo6VoMNxNPT\nwHTfq2KZJyzA/w+SGwaqxu6Dp2s53dkyYCM8uFt5w72hr1/4A1gujemS8Ts/\ndWGVttMPoBwbpqXQdYxDlcVyKmvQScqX+l5eOJHUWX1it7uFnqdglgXXipXi\nnxq1pA2XKxBhYxRfoQa14ZNAngWrCywkVqViY4kwzHBz+4tyko7NdrJZRIBI\nOgeQdJZQTT0F/3IhumBjG2u4B3A/QFJ+Q03vXvfJW7lr2+3DaeIggOSx0NEQ\nYwlDqTiX5oLrRfkqCE2B3KViU3fSQAE4v2hPQudTK0uU0CDVH41MfO7ygw5r\nGF3TtxV6bnJlcEVE4rP9ZwSoiIdRHNJBaut+h2Hd2VVVjSnv1Fz02jcsEjD+\nrIBxYObYQnvGv9HsaZdkfxAUldFrT0EN/1FqXK2fdjDWVZ88FkDxj7qqOH7N\n4bbKLb45BSxAIA+P+iZNmZ/nZHf8moayrK6hdE0G7VhBIhI6zF22Za7iGZ7s\n4qogfl6ob2+1PzYeAierekwA/AWdG2IH1SlJHgNSPEN0X52heBDGlco/H5G1\nEhQhqB+9DFtbq7Dei+itWQm18TvrsBFZDGT5G+LAru/w94SWYl6DjRF0U3tQ\nqN/5\r\n=CRlA\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAccount(type)](#Box+linkAccount)\n        * [.isAccountLinked(type)](#Box+isAccountLinked)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAccount\"></a>\n\n#### box.linkAccount(type)\nCreates a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default 'ethereum') |\n\n<a name=\"Box+isAccountLinked\"></a>\n\n#### box.isAccountLinked(type)\nChecks if there is a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default ethereum) |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.membersOnly | <code>Boolean</code> | join a members only thread, which only members can post in |\n| opts.rootMod | <code>String</code> | the rootMod, known as first moderator of a thread, by default user is moderator |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.rootMod | <code>String</code> | DID of the root moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, rootMod, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.35.0","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","is-ipfs":"^0.6.1","orbit-db":"^0.21.0","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","orbit-db-io":"^0.0.2","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"0.3.0-alpha.2","3box-orbitdb-plugins":"^1.0.1","orbit-db-access-controllers":"^0.2.0","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.9.0-beta.1_1559646145349_0.3182825895053025","host":"s3://npm-registry-packages"}},"1.9.0-rc.1":{"name":"3box","version":"1.9.0-rc.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.9.0-rc.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"c80a806d6566efefddade048a69ac757bbb022ac","tarball":"https://registry.npmjs.org/3box/-/3box-1.9.0-rc.1.tgz","fileCount":67,"integrity":"sha512-DIi/ToNSPhVjWekVwKLFarvFH880l7CfXfVR+rMyOrjtC3ujORhMnBC+hyphLc/uxX0lkLtjk95zjcLm+U3tlg==","signatures":[{"sig":"MEYCIQDKaWO1D5KF3r26LVHF32oLYsVp6oyCBFBa5/TieyQRvwIhALecrQga3PaeXnvviArdKe4+9p2jc0lZ0ptNjdr4NfOq","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9062720,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc9ofQCRA9TVsSAnZWagAAHbgP/0TJARsMsjb+EZTJc1B3\nc/Q/eh2teyZtqnWV0btzQnpu+ckjHAZ5u+TfxZzIlP1nms0euucOHkuGWmNR\nrKDdS9y/2+VK51V1w67IyyjJSOjs7DU0tjjQ/9Z+ap1KaogRSjupFRqyiofC\nXnCjcrpA/nGB0k+ju6I91TP4pTiRAXM/RjmhRRb5Xbb44iQYvHU1gk1JW164\nTnUGsPZmidv6S8Eacht7KcflQ9qzsvqb7nhaDG60StAH0BsyermC3X8lJaAb\nQqhwNiGfZH8Bp4uuC/JB5XVXcC9W0OXLOlr4EOn5eXQq2srwsEEOU6/avVBO\nTEFplnKv4QyPYcDwkJOBLavcxl4SYQxvLj9LJxAUM6aiSz4VpKmyhq9+D9Vu\n4ifnHtj2oYaOcqpfLQVOC/wXrguK5OTEpUbMPEyL9ghf4H3ra+5wRmjJ2vva\nCEyFomlauMNpEhhH85RwfMkJcoa4J8dKsYv2m7Q2UuoQaQJ9KjOHRKSXcQyh\nOzrycGPlRxDMjzwC8Fi6j+ix8eba4eFLbRpbH3pyPIkB3DNqhfmgzhOnpXXx\n7rjdFQeamdJH7IW93+RzGVSGJ1aYT1BspXwJ5SsBUKA+PRqYmbVi9vVxVUYO\nxqfxFfE+ltbhIUfJNMlNzkjq7JJI+DhPbMzAxiLC5l1T29LH0Xfj4+05OWjo\nnUx3\r\n=4siv\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAccount(type)](#Box+linkAccount)\n        * [.isAccountLinked(type)](#Box+isAccountLinked)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAccount\"></a>\n\n#### box.linkAccount(type)\nCreates a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default 'ethereum') |\n\n<a name=\"Box+isAccountLinked\"></a>\n\n#### box.isAccountLinked(type)\nChecks if there is a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default ethereum) |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.membersOnly | <code>Boolean</code> | join a members only thread, which only members can post in |\n| opts.rootMod | <code>String</code> | the rootMod, known as first moderator of a thread, by default user is moderator |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.rootMod | <code>String</code> | DID of the root moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, rootMod, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"5c9c1c3151e1f353b4d0efe37a4d815fe09c8863","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.35.0","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","is-ipfs":"^0.6.1","orbit-db":"^0.21.0","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","idb-readable-stream":"0.0.4","muport-did-resolver":"0.3.0-alpha.2","3box-orbitdb-plugins":"^1.0.1","orbit-db-access-controllers":"^0.2.0","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.9.0-rc.1_1559660495836_0.686726475354577","host":"s3://npm-registry-packages"}},"1.9.0-rc.2":{"name":"3box","version":"1.9.0-rc.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.9.0-rc.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"0e63ea3fbdfdd182910ae85fbe3e7b3298e5b605","tarball":"https://registry.npmjs.org/3box/-/3box-1.9.0-rc.2.tgz","fileCount":63,"integrity":"sha512-jGV5k23sFvmVBcRv48oso0G/BhXjY8q8vsazIFGNBd8qIXs4GVWYRarBkDM1AuvDli41mnc9wHcYCm0/KvNYsQ==","signatures":[{"sig":"MEQCIAHb2isf8ouLJtd1ZFm719ikumxt6JolqfPBUiPeIypsAiBPrkcBzADC23mYjV954vmIiaSe+xRyeLgBKdYSn9XHRw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":8878318,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc/EpCCRA9TVsSAnZWagAAFXUP/RIdDeGPI9EyS9eck8EK\nV9fbSik7NJucaFiiQB5cPJKR28ORHZ9AXiqtECl8ddJqr+D5eLPKKushKbaZ\ni9re9qfPscPk22mgJhnFIYEDcClsGD2NSsX4fr1IkSHauOk88LohnJMekF1c\nRXfVEj+2lJMOEw23EdaIFIXsBi9niSmRrAFisAeuGQeUcC3OT8sFFzl9tyUd\n8SLvFsm2UXnVyjXS4807uM0se5h7yKPNOjpB42tigmv5fka71ZHZepYMdyzf\n3sp3TAOpa+qrjh40HGKY+7YpDXpfC8sGkEBjeH+V7MGrGWrzW6v2daqwPkTN\nG8ZYUHGog3mPYciZ0hFXd0EOkorMGArZDU5lbrXVCXsOxSKDwQcwjkNdKmXq\nk7XjxN/VWTePe6M6bOzT3r+Ji1GwTVOtfIkhQAMfcifMRVj0DsFcTVLbCcxC\naApqPVKB78/FfVt0DN+tCp24lmMzxBZsgRL+HGCRfoe7d+N3Yf+sY0yETZ+E\ngNKId9lVAirR4YG9+pRqdULEpIAMQN1Ekg7x2c7tRUm0qmc1U5pyq5aFCyfe\nLkOhwPeVDFGujaNnIgPTI2WxO9IAptrWXvp9XvXjucAyrZTnD3id3yGsm1J8\n14HCgfaSU8fumIpawQfFPLITwi5zp26W1M+mynO/otrY1iTn2tWoMUUJEPs5\nL71a\r\n=Qpqs\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAccount(type)](#Box+linkAccount)\n        * [.isAccountLinked(type)](#Box+isAccountLinked)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, rootMod, membersOnly, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAccount\"></a>\n\n#### box.linkAccount(type)\nCreates a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default 'ethereum') |\n\n<a name=\"Box+isAccountLinked\"></a>\n\n#### box.isAccountLinked(type)\nChecks if there is a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default ethereum) |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, rootMod, membersOnly, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| rootMod | <code>String</code> | The DID (or ethereum address) of the root moderator |\n| membersOnly | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name or full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.membersOnly | <code>Boolean</code> | join a members only thread, which only members can post in, ignores if joined by address |\n| opts.rootMod | <code>String</code> | the rootMod, known as first moderator of a thread, by default user is moderator, ignored if joined by address |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.rootMod | <code>String</code> | DID of the root moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, rootMod, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onNewPost(newPostFn)](#Thread+onNewPost)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onNewPost\"></a>\n\n#### thread.onNewPost(newPostFn)\nRegister a function to be called for every new\npost that is received from the network.\nThe function takes one parameter, which is the post.\nNote that posts here might be out of order.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| newPostFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"e3e86904256e6c1dbde45f9a66ebe21d55e57724","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.35.0","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","orbit-db":"^0.21.0","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.3","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.9.0-rc.2_1560037954339_0.10419317289397045","host":"s3://npm-registry-packages"}},"1.9.0-rc.3":{"name":"3box","version":"1.9.0-rc.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.9.0-rc.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"6a439d7bcb4c80c19284c87c8db4315c4cbe75ad","tarball":"https://registry.npmjs.org/3box/-/3box-1.9.0-rc.3.tgz","fileCount":65,"integrity":"sha512-8qOGc1lQ97Z6C+ywgKHhGrfF+lky8TbLFZu/xitLINF0naonUHuvcm19/Lh7+E1WgooxsBQO0FwddxCISuK03g==","signatures":[{"sig":"MEYCIQCMkMhrojnhiNja0Fg1EROYl5wtsxrkEniUbwR71Y7phQIhAOftKRGGE4coe2SjMCZuOWXwIw+i1qg+Mn8Gde9hSQWL","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10445096,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc/6uuCRA9TVsSAnZWagAAmvMP/jhJfTe6KB9okcDU7PbT\nB3ps9CS1KhcRo3Ea5RVks1Mg6hdnThNX8zDmFKCwdCZ1zmNozpK925KGlUNy\nM0VCd7ia/Q899mpsfA12uQrKtZrdb/i34wiLeesbcoSo+vcOWVmQSVZzoGQJ\nRw0BZ8uNgMd9WnyZQAG+7xhiu0rxZcpv/H9KpzZFWvRjVbupjrGpxPNazaNq\nMjBu7i1uXQb2zFQhL0OfgkFta9AWxs6EMxP9mq8ufk0cggJCMNJz+uE9EN9f\nv3AIve6a3WFnjoQsJpOxTtst66M5Tsyd/rF2j6ZbpzE//xeH6hMk2nVb9BoJ\n3rA1jaOuU7L0zhYxCi+4sEfj/RPwSnEAwbRzBJX13hgTFPOhfr7r3Fnr74rU\nPXNrsWcI2N5uoxMiFX9Msmbu91eyk6BL5RGBIBh+OfQUnSOmPHBaJEXEII0+\nn/zOp3BazTrTteJJgOfklggnxsDBVL7tLn7rVjVmnqpIwd0cf4ZdxOS6nqvI\nVP03062dfQqb0AvHqbKnXGqfbS06punRu8CKlh/TtJC+/PwEpIocUZh3opBv\nDaYYBTLCLDpPaQRqvMpVwUQRtTbinPfe7NDECGfTGlSRA7o11fRO+K1fOU+U\nklldeM4VgzNxqmqOiiBxkF3S7yXdMxbwOTSmYfMD1oNPmdzlv4yOhs4M1NdD\nPVTk\r\n=IyOg\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n**WARNING: this is an experimental feature, the API will likely change in the future!**\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object.\n```js\nconst posts = await Box.getThread(spaceName, threadName)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAccount(type)](#Box+linkAccount)\n        * [.isAccountLinked(type)](#Box+isAccountLinked)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAccount\"></a>\n\n#### box.linkAccount(type)\nCreates a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default 'ethereum') |\n\n<a name=\"Box+isAccountLinked\"></a>\n\n#### box.isAccountLinked(type)\nChecks if there is a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default ethereum) |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","orbit-db":"^0.21.2","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.9.0-rc.3_1560259501569_0.691670483156674","host":"s3://npm-registry-packages"}},"1.9.0-rc.4":{"name":"3box","version":"1.9.0-rc.4","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.9.0-rc.4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"91b7c831a5f200d7270cd44562bfe468560da990","tarball":"https://registry.npmjs.org/3box/-/3box-1.9.0-rc.4.tgz","fileCount":64,"integrity":"sha512-YWWjlv5G0QkMPD7xXnBr2JlzhbF9huhBTbmwrY2Mqrp99asBJbuYnVVz9btBPG/U/XTDJ1AdvFs09HYSV8yAWw==","signatures":[{"sig":"MEQCIE8MpyjtwrvyLnz9dHn7xrhUO/NYpcHngpbuNR0S1eOMAiAwppNGGZIsyfwQxFkbK51y7ujaRy+AI1u9sjpAivbN2w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9790382,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJc/+bGCRA9TVsSAnZWagAAJV8P/jJXvNJAxg0mdNYd22y+\nfxyIHcaUSEvT28wCQsLPbqna/h0KBbU4aaopAmEixrHPowW0AMNIMLJ3zcKw\n2rIXRbH/LcFsywXKrySSLqH29ZTkUFu/MVkoVnnBkMtqYHtQEoIgN3nhPGIq\nVy9V6HhyRHvwesrCsU4Trxy6ewTeeROfl0krQWfeSHyE9xpEViJaMvnVm8Ke\nVhsrPYj3j89HF/IMaUEx3FP1jYPc15UISVBS0X4UqA/IdF1FaEoZIjdeBbF4\n7vsT+qAQmFB5kAK9JnYhO7Vh4r/kij8XHvZ4mZTpwHLdnO34EnwsQ2V5+Lxr\nHWtmJCBzzbCBPuSQIiuxbqWWNdwjtsLOO/g9ntqQi+aZzqQ04TW8VwbEeHSj\nNUc809atqnFxEsG2zlg5ulQt5uDxaVlGp43tg2+ZmsQarngJmb6vGGmO/tXR\nauvmyLd2qBlOV+BKoAPPNk8zTUCbwEA4mAMNOMinkjptQhQXqBJ2QU/By96H\n5VVmGBKElaucjoCzWYUH2m/D8vl6dFuX/UCNswnpWs9HYByN/eK+fXGdXZWe\nwn8ylO6Ft9LX2QgeWDlPONZG42rbXvx8F5d9kIC/9qOha+DocWgRbkCPdNpe\ncqGT4xqPMZjTpQ9cp7EfmofS7W+1gM4a0zjatC7HEU17w/CYwqwYjMVnGdxh\n3eyl\r\n=P3Ca\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'someones3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n\n\n\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onNewPost(myCallbackFunction)\n```\n\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAccount(type)](#Box+linkAccount)\n        * [.isAccountLinked(type)](#Box+isAccountLinked)\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAccount\"></a>\n\n#### box.linkAccount(type)\nCreates a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default 'ethereum') |\n\n<a name=\"Box+isAccountLinked\"></a>\n\n#### box.isAccountLinked(type)\nChecks if there is a proof that links an external account to the 3Box account of the user.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| type | <code>String</code> | The type of link (default ethereum) |\n\n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"7815adb1ca93208d2ceb567557f7df1822ca92c3","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","orbit-db":"^0.21.2","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.9.0-rc.4_1560274629011_0.4699121138219984","host":"s3://npm-registry-packages"}},"1.9.0":{"name":"3box","version":"1.9.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.9.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"90a442e78e5780d496c45ce7591f3971c9ffaf5d","tarball":"https://registry.npmjs.org/3box/-/3box-1.9.0.tgz","fileCount":64,"integrity":"sha512-iQoE7GzeOGUrOzfmEAQp0GJcOP6mMcT9XyblW09dhHhGq4scFk91cDkkkocQfUWkt0+YSRvXfOjm+wlSpH18nw==","signatures":[{"sig":"MEYCIQD0wB8sBNe5j76vCUoTH5z++cqKkKQROz7oNZsvf0fpiAIhANOAoNNFgppjQE6ygiYqmZMGgM4Bg9u76ptXfrnW2iGl","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9791790,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdAAmNCRA9TVsSAnZWagAAMDUQAKR1gsISIfOdOj0iYOGn\ngLWo/wlKfYFCEi8n10I09SYJNpXuZxnv2WMpzdCwE2lvAkHk4GNwcqlrHN5K\nmJkeBqTFT6oVWr+FlYjkNSq44ulqdIies2fieJ+FSAqpqQdDztAZJ6QvF7Ba\n9AbRkM/0stbLxNMXy21pSzZuMAc3/iboprzzV5Fy0N/ZJG3AdGTkbNVJUHNJ\nniMG2mZhLKXQV2AUkVo12XMVLLVHBt002CBwVT1+/jsAjojBts0OwX1xti8K\nAsKD4RF26qhCfxf0o/rpsrVGGTCt5QIKzks25MCz86HbIL9uP3kvKqpXtJIL\nasFimb/UtvvnPnnOkeGJBTLbqFBgs5uwXN41p9LFMMGCH1hGR+2LE1NQ58HR\nkM6+VVOfWr4w+bS+kEcZ8tUhfEjjjX9/kBji5HftPXu/x+eOjxbvGfofIx/W\n7go/E8gLqdMm3uar9uEmHFz83DBOBzR7xRloBSVmuHKmp6l8yUuy+JxSOMoW\nuKVtUpsdMlG22d3blYffrbYBOeCDOoNr/BGddM1UWu60NxjuowhXMTYA0aYh\nfmuiP96I45RXyPNSyJgeUucuRxosEbESdo9MFvUcphA8qVLhoDCfV/xPIpCj\n61yFPKJt/YXyI76bVDbtVHcoC6mlBr0rCsKW0vCFfK7JOh3gsLGjIhuEWlqO\no+9j\r\n=55Du\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"1e464d27dd419224324bab084d313a2476311329","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","orbit-db":"^0.21.2","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.9.0_1560283532769_0.8957505700045627","host":"s3://npm-registry-packages"}},"1.9.1":{"name":"3box","version":"1.9.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.9.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"b8dc6032eb41a2796ecc572255a89cf5850bd7cf","tarball":"https://registry.npmjs.org/3box/-/3box-1.9.1.tgz","fileCount":65,"integrity":"sha512-DU7lyoFqgbreNV7As36UQPZKmEVCTlOlajJ9rY2ZKGOyBw5YrDXQk61WeqH7Pvn0NsdbU340aLaRQ0qKP2OmBA==","signatures":[{"sig":"MEYCIQCzKd30yG/JxuVXQotjiHTSFOfocp/bz8bUMU2NWPVMqQIhAPoYG2alBUwIbh3V3HAF378Z3mkWt4n31m5K3SmnrJ2R","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12717017,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdCupcCRA9TVsSAnZWagAAD0QP/1pv4P0K+HXlvnpmT3nR\n0Ca8jEF66sV3wNLPBu8Ks4fRlRNxjQTyCt7aEJLedM2aiEt71lQXiIZ31g4M\n3nFpDI6RUpm+OQDPqryUXJtFaFReT+ix3fBwXG+/jCJ7jxprziw/LdGvSe+3\na8MVAgDNZ+/gAkF02m32f8HHpXqrF7a7PwC8jbCd5qOLlaRF5WamQyiO3gtS\nCEG4NecEZ+kDtS/u5b0lSEyThAKbVdZZO+MlWwh6DGZzx5YPkKxDnVwLO8ak\naraUMgiB/yTISONrBeb+fq+pdIeJykdwjXs6NAS+iRrJD8PKrn1+BcS0SG8Q\nC2knSgxivHTlkiMCQms+5ty6y1vbS6zo2YNPkJIvARgo1I/e2aqZUfZCJVWK\nRtiBbBt+u20+H64lW09yYaaIRzV89PG+F94ZW8KGl/BegdaTbs4PHiZwm+18\nRxDll6BiynDa+5vnjqLbbsK+ROiobKBql5nfCvlN/6ATbp+5Ek7zY8zuQSfJ\nvfGa22nT4eN3L9XtnWSR/j68ZlqspL4OFBy2uEIZA4GR11+ADBh9XQIILWLw\nQSqrysrvyvSkZaDUMa/prTFQEIX7cvOAflxHue4dAlTFHoiGljwRmWqQYWxj\nNlKwJwYVq3fi0MP7H0JWE80UnXT8mfr/IqNulHCR0GnVF/BfhdPX+KX7gdAy\nQ6FP\r\n=aFNp\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"7c914c02b90da1ad989a0685c02351fc75bd71c4","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist; npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","orbit-db":"^0.21.2","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.9.1_1560996443032_0.9510216369838917","host":"s3://npm-registry-packages"}},"1.10.0":{"name":"3box","version":"1.10.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"77b3b60dcaa8d5f32816aac8b5377ed80b3fa857","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.0.tgz","fileCount":65,"integrity":"sha512-IDEqAqvkhKl9Pc6B5SqkBgObwC1tAYbVbnssSXbbUGjNHq5AI0FFjwLzzvXfQvp8fyv4A875O6XPbDYxp1fhuw==","signatures":[{"sig":"MEUCIQDKuG5FJjlCT1AA6FMwkOz6Z6XwG/jnXz3Qc42/lr5/3gIgEdHVMPhDThTm/WoJMn2PEfDl8D4SDsphEdLxlJw9kWQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9827245,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdLzPiCRA9TVsSAnZWagAADb8P/2vnpxvZ/s5yr6+4kidW\nf1BMkjEP/r0c9snw84ZjIG2JbOi8aolYUlthtipQ2asLw7MgB9lnVg+436ly\nRoIXQ7faqRYURA8K2x83TRywgrinbxD7Yz45Qu0eD9ROT4iUZkx+qDsU5NKD\noRRJxqVuurk63CsIFZ8xnKEOhg+rFBiT8dv0JhH2dqkBNutpTUOWT51Y3kEn\nsC9kSwKODqV5l5CUJi/8BVvqEzN8IzDY2JfvWyn6vJT8IDAq9wjH0IOB+ROt\nWJVnkcCfk7YtakZQjTa7VMyBfyvRQUJjIqnG/Sv+M+aLQdck0y5BxJAJBu5R\n249cgLyqZohnyheLM9Ot7Eqch9AlpoiHA6txzm9sI0quhoxWsYI3sIXM0iRV\nyGjzbyauIbnYb3tR1tB+4OiJQHhBvsb45Q/gATAvDp5u4AzLyQtYcqpx2AVP\nYc3xruMWO3SslzQz0dFd5LAz9ZImm8F3WoitbZ+9Lv4YdFHrnEku4vyGI82R\nm/wfhorkndYfJiqZwzs01wrvacivL4XHjhUdcvhUSZKi5gxRhibTlCC2DltS\n5xQzeCniJAETtI3Z2Mlp8pHybBK8ThnP0J7N7ox1CCOHEtEeiHqLEoaqNizC\nGZq23kTng6lJsrMRVebasGLeDROGiyqYn/rLZHXK/tzgCTYbbL1H4kB+cf+M\nsYUW\r\n=gcQH\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.1.3","orbit-db":"^0.21.2","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^12.0.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.0_1563374561364_0.5655436815046122","host":"s3://npm-registry-packages"}},"1.10.1":{"name":"3box","version":"1.10.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"645c8c9078f4c48b1f20456bb7c5434913a19d6c","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.1.tgz","fileCount":65,"integrity":"sha512-YJBMAg/hW/CdQrj6OIAKPp7yVPPq8he1vdoYTuf85TD9fthoTU3YbT8eas5j1a+dFLvQVslUkeZQ2bOcFPdrHg==","signatures":[{"sig":"MEUCIQCq7tLUDzhIa1VquDxTqQ9kakhisWLxa4LLfN+9AJFgQwIgYqY99rGlf7FynImo8nGzwasMoEnp5rw4zWyw91rhpx4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9552699,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOF/FCRA9TVsSAnZWagAAonoP/1T2PV/T5aQc4CdMgL8+\nLsOuTPhbDhGdjhXtp0UJ2MaV+zf/b4vv6V18hQx5Od7Pd1hT1OPDuXEk/Sd2\nwDZvfiWNNe+oaRl6CtsZXNucCqi5yWlCX/DTsO+PMlje/jsbpeqn/x95+INR\n0z1IReII/atEmzqSJ4sOyRGUBOLFXVcxE5XQ21Abat4Tcv56itsIn/BdWQFB\n371dMFcZj8op7L0eHDkPq9xFVwHMY8ME3ySnjl/gn1YQW6FeLZEck9ibv+cM\nS2/CBMMeX0AWiLGy7FcWOh05HyLin7mC+U0Uvz2mOBs5M+aalGbUUtbLZ0ev\nXLTNJs93z/dbkeN8Swfe0PThGZcaeCpC7WdNo9sDlPI/QJ6WWziuZMTz8GPR\nHZqyMrr7sCC3BiV7cRwYgNIikKVESDkzgiX+QB7sffRGA3tZDkUMcclRCR4u\noSwZimXtEdxABPUPOHBX9A3QbUwQiCqme4+v52U3JUPkOtMnTpAlEN6K8Dz0\nBNaCIyaZ29q9owQo2aiGW+3YImfW7+0fduJsCiba+iYGvfapl0rkQla8dZ6S\nO3XjNEL+vBZOkp0yTwa20zmQkwGFAvyAxLKmp3XLTVBP1Ri1kRXOPdtn9GuD\nIki8JKP0XPoL6UsbEH0uCxXP6qKY1HINBGD11rGsvuY4f/iPcRszu8sV/0xf\nFide\r\n=vtwU\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.1_1563975619922_0.4982317986616409","host":"s3://npm-registry-packages"}},"1.10.2":{"name":"3box","version":"1.10.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"ba0e230055101a29337ff0c91ba6c702ea176306","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.2.tgz","fileCount":65,"integrity":"sha512-p8HcBfensgKYI5nb0vPI1sLtVI1RPFI9Qrhlk2eLzhmOukhe/7ZnEBIMoWTptIO/vJYkeZNOOdafXq1SZzjPMA==","signatures":[{"sig":"MEUCIQCbJCxFXqM7GIsRT+PpPxtH296iWdPTJJMkdFGBkf7fhgIgQaRssB+HuAiQPbfRgLKJTNJ3v1n3EoRCzTXOI+PNRX0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9562220,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOczsCRA9TVsSAnZWagAA1JkQAI0EUln3uyPr+oKC9fVv\nGUJWjThC2w6o63XqiKTG6A8zjh1H7lt5OY5VwjDL/tXuVNkQ6utDspq6V+Fx\niFhAFGK/baMaz5qKFfeVQoOJTmO4PnkffvrBmrC6VIMjA1SzcM1btOa3ybb9\nfaFGiYHWCn2/yRnjP5HFpk4RALcRRXi/IjSMX8xd1L/3+ZLb5kmzPGjmxvyC\n/vggeyZr3EmNNgwRBehyRWHzqhwWsi7sXmDvIJHG/TWKfVNjFr7Ia/6CMVjr\nlFJ2eo1YB3riYj3IcTKtbWzvmvP+4M3gYkO+6okfCbznchu2LMeUVaYPYyBK\nZryWrzdGsiE+68lYGUbyampsUUi+YqmxWCA3QUPYIkQ6fFmjI3h3KT0PNst0\nhUPv73OHi1V/5ayjxnlPItFc7RnRA3RsPF0kqBLCkV5BHHnNWJ3GGWKn9hGs\nNlzYUPDqOGRuV3sySDQCa2DsG0BavEDI3V9CwqV1mX9LlEJpJrB8JKdCK5VG\nPYuNJaHg3sVlZhS2zV7zZtXT7OpPJGpVWhQTJmT0lAwg20E0mF9lQlP198D7\nPX8qVQcWsXX7ceCpHTQldXcG6nc1FpXlHPJIITAvW0kd5bbH5906IaV7059C\n1uC6Tb84mZ6+s0rR4kzNkHriM0+8AtZnJbkUrn4w/W10Bc9Gmj4ZcUYXf1cF\nbaRx\r\n=ApPI\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.2_1564069099640_0.9530164057299662","host":"s3://npm-registry-packages"}},"1.10.3":{"name":"3box","version":"1.10.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"2578c2936c20ac0ac4bac87881418c25fe1c000d","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.3.tgz","fileCount":65,"integrity":"sha512-216LCn+T5toRJIK+exEXC68V1gCtF3TVdTu/vpJGauxJD6u1jIkZ+5LN0JhOjaP5koW0G0kfUZDDm/PtI6vygA==","signatures":[{"sig":"MEUCIQDLosOPYsUyAmwEb7wh5eSZOIJPykpeAa58EB40L+mrzQIgLlAjaM79UMuPuVP+c/3zebHaCbQdwGAovetQbOMHnQw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9562379,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdOv6lCRA9TVsSAnZWagAAbPYQAKOQHhLtc8t25/TBnGgQ\nw1sQsn9M3vl3e/gUSd4PEgQtxdi6hgy9GZ+BibeF/kUBHhCeEdaJcaFS8O3I\nQZnXzLPyEBia1vaRCblwLm14pVC3vEe3Kos5tqWX9mi91NzevyU2N+RTAseN\n1XAPg36p/LjRC3eaxzAifuoI2Hu5PPiWFUKmhBuY0iVvPUWYsk3a7bn4rZGO\nW7IoNwKy3WiIt/w5D9CWsM9PlswhvXuGKRpTGgocLtyZIPuGeeItD6kBoQNa\ncjM24asCd60QrRwISuC/McHq93E5Ae/FGWcfCEuslHDCnqX9tLqeMmjxI2O9\nRCRvLYHweRMXqbqZbfFOCiB8U2+niVD2szRL/2b4VZ9degSsehSaPedcGo3Y\njPv/EaXQGSLXzh0hU08djzsqNuOjdpnTirqKj0qb4T+jXtHQQM1JFu6t18Ly\nPff6uhIYfAVs3StkyNTdA5fCtbo3AdP7Ms4z6IGIkGvTMKu6ryUnxIo3tJHW\nMWwoP9wf9m+0H34vCdPdYdEwforUqBeeDGQg8yeGoQy+Mul1MHQJB0MEsyC0\nOs/jEKeYTAXbLsR4HHC0/HE7q0asJU0oF9yr0oHRpr/gbnSZC5frggT/2eSF\nc1uqz/t0WyMLJpEICTfIlW2A8H5AmjZ2iK+S31+rsGJQIODCWXzLj45dYrMO\nX3sg\r\n=/R8z\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.3_1564147364100_0.3524945096467884","host":"s3://npm-registry-packages"}},"1.10.4":{"name":"3box","version":"1.10.4","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"f843e8563302dc89b2cf10860cc31e91baa44db6","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.4.tgz","fileCount":67,"integrity":"sha512-XoEgC/ikPTqe3dzzpDGPxnk0fF1F3490ltTtX+NFv55NA9xM2mJfkXk0HBB4MqyAgtvNYbR+HMHwZ5HUrucRzg==","signatures":[{"sig":"MEUCIHb3zLrShFnu7c7hOZkdbCWYtB74I3mIRprUWkRgE2RkAiEAkdw9Yg5uPLP+9/i4vtPBpJLL2mVr/SCbdd2RfhB/mIA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9582929,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQcYWCRA9TVsSAnZWagAAZBsQAIlTXFpPW5HBUKubm278\nXZb5qbEXybxiwDdRpy3rh7Z8V6ijSvpZhjdff9eAV/V87tGBjBoVyBs8jzTO\nZBi/G9U2K9HQRbHbTBW7kbIVE7tWR53jh0nbR0t6UH8BxaQ4yYPGuLebz9eE\nKweBpIKQUGNGnvUyQFZmqUV/P0CLAoPXuvDw/ywuCMYwEMaFIFlpB3gpdBw4\ng4vRuXYXNHh1mhG1/2n7yicVwcxUYaPkTmP5FYYyWx1zv/N2pEHgtjAEq6Ch\nSsc38jNLc3yErqjMMza/qqmx9OHTRPbQgSi8oL0CSlVsW1Iu7mhnZNNelmgf\nDRaPkep6DwFPFYnXaZZUCFeHjRaa5uK63fP3pLroWayJ/kpwr4jkPmuc7sXY\nB6OlmJ3UnZPXBu/vCw3vfE4ZE7anwcj7NButdctn1Cbjfny8KCxhI92z3KUE\nOH+YsuOromrCBKTg5HovrrXkM27ceBhyiaNnNfMcbvHKW6U5+kQL306V0/Nc\nMqhJcCxOQDqtACC+TtpU3JMhhTz91MMapflatgzZCnh928s6AznUrYpOTnk2\n7KI4ie8Rt7v1v3ZcM4dqO7nn17RpN+WBU33MU0wUJAek4ZvtzK9N9RqQaJOm\nWtMvb4TyQbZhBsuzP/3p0YQtPVziLjnI+s6as9y/DAYZhC5C96QXFQg/V6hX\ni2Ps\r\n=oAuK\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.4_1564591637788_0.4405351015097012","host":"s3://npm-registry-packages"}},"1.10.5-beta.1":{"name":"3box","version":"1.10.5-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.5-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"9c2dff8f0f3a729a6f8a7960e874497eb6083695","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.5-beta.1.tgz","fileCount":67,"integrity":"sha512-gAVcEGM0LZ5+A/1XCOPGCt17QNxE0q1SGQnJuGYSFV8nMp19rMu9KMKP7teeLTIwL0y1s8ipJag6YpxG9z9MUw==","signatures":[{"sig":"MEYCIQDPJagr9cDIl80OLgBMTX1cUWraDZZupWDgt6os/ivhLgIhANobqUFYerI2smFeiWGZbcRZRxNScBQ6K/EprKhTCfuV","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9586942,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQej+CRA9TVsSAnZWagAAAcoP/0/BxkhiN/MThdYhl6Dw\nyWeReeuocHyTSo00Xs7LVQlOuzY0hBsIiA7oZHvBw05ayFiSkYa9iLwSoOi+\nox0v4OFp7aBpA3IMH8+Ps4Lnkb8eKsO62Ag+W5O4f2F/L8sC6FLsDKQwMJAN\neNqMaz7fiOlyCN+CKK+Jev98v5GXkpIwhFvCjY3tPBrCbA7irp7SfJYk4cEb\nJtxnFjp8fdSec7h7RJHsLpKHSDuq0BJwXGrREQEmVR9UHAoJaLlLC6qghZRW\nsxLf67asIKxEqh/RPyJ56LjiUdsOmnkrppRYOkUKte9RjOtTI0sAz7lDRGn5\nU20LSrMIvGpLuqWoCd/Q66PYxiiI3D+gMQ95o+2Snu/HNqPM/6/5S7IvfrTE\nCvwGbvagr4UzA2L0t5xK2f6DJN7jXd8M4sWWLvN73T5bdZ1wL4U3Oy5Pg1eK\no8/K105x2xt6BqFl6vvkxKtzljjjXz9SqiDxMtBiuOwaNKjyGgnTsE8IKkep\n95MrUvHUKl7LDzxjtZOCIeXHHI6tLe/i9s7S+R0G4UYsYnXHSkkcNeOM7vdo\nl74ihN92080uqXs8MtT23A5A4MOuLnoTT0sezBx3FZzExfSZTppImbJpiOBQ\nGVcEPeR9tKhtRNinymw+hxyEE6qyQxC1WERt8CgLXz8t/mK7hJt0lMdjF/Rm\nA1qj\r\n=1byO\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.5-beta.1_1564600573743_0.6825121374722116","host":"s3://npm-registry-packages"}},"1.10.5-beta.2":{"name":"3box","version":"1.10.5-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.5-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"1f9ce86adc7def17e40fdca951bc1d4f8108faee","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.5-beta.2.tgz","fileCount":67,"integrity":"sha512-V5T9WgGPGg/jJYhDgIfKvGctv1Ld2mGnmGQt/SxHnf6AR08y2bd6Mloh0En8URJg+L/g/5K/5er3MZiIYaXyjA==","signatures":[{"sig":"MEUCIQDAm8UfvhPX6sivRStmZ/APeGB2eLBZw/8KanpqSlKunQIgFppfFadeA6NBoq/A+iN78516HeNXV4GJ2uhqJ2UG3CI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9588960,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdQqPlCRA9TVsSAnZWagAAd1IP/jgVIEt6n8YlkCOsrwZd\nK5VQ5Tz4VGaHFKPjOVWFy/eR+K2yQmXas9OwVN2cQcOY2aHRKu5poTbU1ago\n6jOgxJJo/xRfa066/ft6pOIJKXrCHkj6exC3TtsOtQ40JsWrxu8Vp23Ky7LB\nh02Dao006OP1L48w96MIGjfFYxp2s2jv6d1hr4haTEB1MSAerAGwCr+otT0g\ncitIzgBaELPW+rpqtPon8OxSqSICcXvoVOpuCZ2KYIsJaNEwjoFFBrt2H6kE\n1q9BzZQhv4M4w2HCc7uWsKge8eOhMy6FxJ5c1VRLhAi7Emrs4Pt1xybAKC88\n0UibhHG5Hy7Fukv04EZCEYRlQEm3sQHaN0qHSdTEFOd2oA8vJvi+RyJqOntG\nqrRSGyY9vXMA6ucUGUfmJ5CRR6tSnAKPNVYDVKEsthAsAN/dWynnJKo+qftx\n4o0i+g9Hl9Pc71QwiEpWTe/CMCw5Lu7cdqrsnvr9NBRlQ+4Z2XUyayCxOIEs\nDt4SQ21DyZlxyQkckcr2T9LdDv/DBp/aYj162BYQm12/fucwIxhgTjKVvU9w\nF2OmM0HPuBm1fq+BMqXeMS0xBEAPS8CT9AA9Gfh9CNwKruIsQuh0MWPcFU5w\nWBNveU9gtfiUId1YtqfJaoy3GvWWoxNo4hrC2sTruL4tXFYhQ3MyzPK1Z6Xm\nZfsa\r\n=UPrZ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isMuportDID(address)](#Box.idUtils.isMuportDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isMuportDID\"></a>\n\n##### idUtils.isMuportDID(address) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the address is a muport did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | A string containing a user profile address |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.5-beta.2_1564648420433_0.6366857017460426","host":"s3://npm-registry-packages"}},"1.10.5":{"name":"3box","version":"1.10.5","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.5","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"a984399684d6e155dd79350745aac8d3a5d61661","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.5.tgz","fileCount":64,"integrity":"sha512-bOOwVuMFFdLYcPIHHgZDxk1TkoKwMeZVFVj5aliJwOYFaM/ruSOtFkBDYN4LQCRw+1r8Sydht9IGTkJor+z/vw==","signatures":[{"sig":"MEQCIA8iu2CRaB4BZlnlGP6oTBveqsHtHi1anF+rmvVW84gwAiA6nh7rJVqa3S927RnQV01wdP4v+8y+IACqwu8u/L3b+w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9567628,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdRGwYCRA9TVsSAnZWagAA7PUP/0z4viCuTRUSpKBfBL9Y\nePVJWmatGJXdlbJNEMGMdtaSrXeeVUUM4IG1Mi5LcQv4+enseHM1KAgznGU4\n/hYjUMzgPgRIevmur+I1s8y4ngKIYQKZc6eNoN6F/mafGGOP0WZuF6sqT2pl\nca3JTQlVTqqygLbtK8x2zcA68wP+NniU+beIn+IxTr3fNliH7E7RrteiibzE\npxREsVrWG1ahX3LKs1V6zeIz6AsqbT6VvaG1bZgrisypuQL04TSzfJiCGIw3\nDEo+xxwvAOel5VV42vgBcwV+0mNPo8Nq+cyNI4j/gGTgjkQ8IUbRQ6j3m3LK\nsxcEoy8LsAtsC/4ZAliQn6RzaAtdc+4w7ij54hfXt3drInXeG5Es614faolt\n1R9vZympTVuAUQZHj/0vrQ5Of9k+V3XBxoPXKNMXuICJTmpNwFYvra41ai4S\n52rkcr/zixtb8y/kOWeDncmM4xVyN84cLeHzEeNrvjDLUPI7MDrbh/tU6YnD\nd7XSWZbZf/HELlQAZtPShP7gENvb+KpT+RSuZIGfko9B5g0eqOXomFXaIQOo\nMwJfi/i4wwBfR1WjaUxbdWsCnsreT2rFP1t9IUHinshXsclucEvAjWQf8a5K\nKnUxAJ2lrGjx7YEHyIDzFtnUQ+ZL6vJucB+mKB+IntwLmcKhYVhn6D4cr3ZG\nzT0E\r\n=DlEY\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.5_1564765207824_0.8798631765427378","host":"s3://npm-registry-packages"}},"1.10.6-beta.1":{"name":"3box","version":"1.10.6-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.6-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"d389e7ef78778886858a2899d189f8668f61cab5","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.6-beta.1.tgz","fileCount":64,"integrity":"sha512-XL2ny7EXHm2aWYZsEvYBP4HcS8tAvLMc7E65tzSkTjHlEw6wctd/1iEAUCQGQUByMjc52yI+VFKS7kmnrMb36g==","signatures":[{"sig":"MEUCIBy+tRIwPZQOyteQvR7uGiyw0iqP0zNZDsb7j39MkyGwAiEA8HncQcndgAyVWcfdg2kyNlWheD/igJXQCVHEfjCkCrg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9567670,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdUp75CRA9TVsSAnZWagAAGMwP/Ao3vOu8BaFa4Q6V1BAb\nuAMzfuCB/IcxocfAtlTgnUY9bbLLMLw8ZRNoq2Qso6baBVyAlsQxoZQwyLSM\nc/CEqFFcH7Kvfu9RMwW8gXSxBufwCt3Y7wlMOLZr58Zq82r+sjlfa0Kzm1Kn\nNpRT1BQ85GDNbVZAzE3MDsIGXGUrgbZ9t9SDDs3EA+ZnGhADIGvvvUvC+Ork\nfyiJgVrgs9+82yb4amGRQZhqtZnkQMBRw8HKKWrgCZB+HD0vA/H6kR2f00Hg\n0tSl3A2GW5Etf08kKI1P5iUmExPB5zygLV2oc5f+waeDIDTNEzTMoUdaTG1I\nsHMr9xy77uBuWieLaO4bChOUZfq/7sSEYfyiW4SVojckirN+KT6uMzj0aZCP\nLtJfbSgAPRoitRgXJA7I9eD8GjR94kP9ajwv3yzikXXU5chcxjYHBM50bnEy\nqYoZ7FJzn7kBabCcpfOKIId02RiHirJ847CUaK+QgMsfJwdWU0dBs43/F+bA\nGjgYE+Qus2DpDjdWmTQgjOU8Fj5WO/y7xrcHNfFgofz8m+RnXuOPtU/imKaT\nk/GwnYpp0zLNMEPqc5n3llL/9bESD6missdXCZBsDAh4ScY35ZQJijVga75Q\nYPZbjD6s1Eg6xl77JBtPGPSEQAX+VCESXAqzZKkGDx91lrbns2xNoncTcMfq\nK62C\r\n=MBxG\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone)\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone)\nSets the callback function that will be called once when the db is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.6-beta.1_1565695736399_0.06665822511781183","host":"s3://npm-registry-packages"}},"1.10.6":{"name":"3box","version":"1.10.6","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.6","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"00b75eb5b6fa08d780cecddba72c1616ea2d5393","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.6.tgz","fileCount":64,"integrity":"sha512-G5Tn1cP5a28kB9jK2xyTBVgVqxC+1W+J3+ime0RBHgdZQpC2Dy0kkieIzdD06syVY2lFIjm94TGXH4qswJVt+A==","signatures":[{"sig":"MEUCIQDuKxrG1GlLySpnO2iZPJobl6N5a+ayRS/SVGKknL0/lgIgUqxXeiNvg1b3XO909ntcfYcf+pV+v2KT4Gm1J23KntM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9568198,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdVR3ICRA9TVsSAnZWagAA+xwP/i8MHISZU3ctfesPqP27\njXHBwfP7pvOqfBZhRSlWccA9Sw8FJWPRRo/7L7Rx7qhv3YeeC2J5s2pbtR1o\nEY3NlvoyG7dKlkHEAalBjM/mxqinz3Mlgk3GkIRC7UTYX8EYXpH3YeOh6psS\nDNpax/WnAcXIZIOpMm6Z97Y+2AywtC+6lRFRHmt2agpc4v/FPXwAHRKa4D9I\nZKJoKi8TcXrOH53g3slugEkAC/qxPTtC6Za4X9YQKBStFOUf9eDXp7Kw2d1h\nDthNMmBdQPZOCvdgWHFHdMv3blqS+ZMagoq+4Fm8dg6IXkqzsHa1BGx9HM6t\nZzkZpScc6c58NrZfiBzQQvMsWirTCEMEd7ZESC6T0F8yXNfhZvlEOuOP5juP\nYwIkg+i8+4o7HPVeeBXQJZUFBx8is+cldC+BSIN8MPOrY5PSAGpTjjcRHSe+\ntAzSuyg204TwFrzwZ98M2OlR0L+sJewcXuoHKOBm58M3U5oxFfWbd80PQkcp\nRVqNzLF7o1o6i20JMq0YwvMzq1O3lYTzPNAMzNkhP4Da75KffYTFNwHA/Hs5\n0fU+Nuv3kLyUGEQmEpvAoeA27ZQZ44Y8ZjwG4b9EiSvfd3epb5bzo8jiToyr\nzOpFCyojQSvPpyoiKjVcwel9HIFXbqCG/0H0db0vvmkKjSfQxWLiSdsNouXK\nbRwp\r\n=X4nS\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.6_1565859271610_0.8753318254124693","host":"s3://npm-registry-packages"}},"1.11.0-beta.1":{"name":"3box","version":"1.11.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.11.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"e6c26c2d78d028137e74c4834883859c8ea7224a","tarball":"https://registry.npmjs.org/3box/-/3box-1.11.0-beta.1.tgz","fileCount":69,"integrity":"sha512-kt6zcvykR/b7LOC9ilg9WZLcHg2Yc7cud99IBbsO+ZsQrxZOJ5LR4kqSUqdBhpUAN1JB/snZ/0ZhcnOwkMdRyw==","signatures":[{"sig":"MEYCIQDN98aeX2Di8lvP+d7wu/IpxaHdbXpcldzfBtYKMytuggIhANTSMGFVu3MzHrOVL7jSPIIRM2MkFRbuoBNZ3hG98/LR","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9549712,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdVSJGCRA9TVsSAnZWagAArEkP/3Szsl7YmkfADXtcS2tU\nlhVJpWOn3ysHyOgrMWlYQ44ogbfdHzDN/5DaHPpPHsh3PnVlVG5zGcLmNBWz\nM3WbTdVTFjwecM338TwZDHQ1Ck0UWgIVQ3ljzboj984YOqrS+4H9FoGup3IN\n1YVwWBuAbqfcntBguJXFIGVQPp7RSh7NoKdXtQD7CwAuqHfQ+t2s+pH4jFNq\nPjrEwaFCQYeuN8Dv4GHCDCsXNxZsJgsbhfS7aRnAn5ElFfplWFoIU45dBfSt\nOuoBSrhkK5nQ8hvMEZp16BZBLdumLxKulG3WY6/+hRbyJ3AAxSRJBm7gwW8y\nvHxsZcMgG095rR2UyUb4y7YqT3wIQK+r67L+DE051/IBIvzNG6fltIoYtITL\nBrsLInzVRrugMFl5hub5BMsTO8wJWGqWDbYWiSBUPVurabgBs5OzI+Cw1w4j\nshcBliIeVrht0EQKoj0feUzZ2uxW0oGwOIVRCyEzkBEuRlfviGbPIPviZcnI\nW4n0E6F1Fk4SoxlfDbn3PoE2ylRdETvrATF5XH6pcogxAbQ3bfqNQonKFiUF\ntVsnKONDS7HrRgGbgTi6AlQItNkKFThiJReCPmOrmtQ1mWcz62AG9cEPpK7/\nUGoQKxqRwrjMXcQ9Tg9QynTe+C1BbDHZFKPAapxc7zbn90vdIQytQcJm6oAZ\ngGTO\r\n=/dZp\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore add a listener using the `onSyncDone` method. This will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once this callback is fired!\n```js\nbox.onSyncDone(yourCallbackFunction)\n```\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following command:\n\n```bash\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","identity-wallet":"0.1.0-beta.8","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.11.0-beta.1_1565860421525_0.5916788188937332","host":"s3://npm-registry-packages"}},"1.10.7":{"name":"3box","version":"1.10.7","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.7","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"f7911acc554b40f7f02b25334f03338fac3adf5a","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.7.tgz","fileCount":64,"integrity":"sha512-oQp12I5nydyjXB9SUGEMtI2bCcx80ZSLLLjp6zv50USz6kvnm+nGt75743grdIEwkluD7GADuZ9VA0jh5UaclQ==","signatures":[{"sig":"MEUCIQDMZTUtOc5ESxJRNpK8p7PkQVkpPLdKksQbKOLU8fpaAgIgd2B85puUbDsP+Zi6DMhO9v5cQ9fttmCfQJ3etrbD+/0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9569229,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdWpc+CRA9TVsSAnZWagAAs5oP/2sAVFv2TR80KE0S/pbh\nsIiiBa7AMN6YWuYIfuo45elwGMjnZPx3l3NA5+5wsjvMm7LyVBA5Fo4d0l4A\na/KN+mnqR6J3zLfddgfgDUYcV5TEIYHA/9HQkXeYalPiitZrP1J6IpGrQIBB\nxUQXfG6oWZMZin6thlY+m9W/U/ppoQeVfNtVrgpZQPOsJxzD0NgBPbP6QwY3\nsD4mwg8zym/JdClSkvNXN399SPE/AVT0xAtpAEbjhPuOaX1yhD2hGcWgYVDQ\nUEKDp9svIlQ70xYevCTftiXNxUMsmZ/EC3ngdqJIXVCkA2Uu+7ebvApWHptL\nk1arPagLQyn4R2zjZrFiEAA3oSUfmKBcyqR+yCjjTyBlSCtpeTbG0tWQv8Ox\nAv6wWFMeBiV/NpwHh5oHPUY/3T6DQueDPwCFBHbOYkfUUfzPszB+gDgBSV6p\nPDPltd1mBjdOCKEYVUITBev6KO5r5dWOr66MTzZQTNs1Hgk5EVs1mYYWiKbG\nylr47j0GrYn6np7X7Y2SX20WMPIDi0O7GJ8ORr9tORwORTOVZI09JqT0Ko3G\nNXsG9geCzjhYR/sefpE9yRDsLkzRk6HnGWOCMhSiiuCbUxNrw/t/I/yZJeCS\nV2DN95Aer7NaaTBbSrFlN57DaU8iMuqh0ZVS53HQpHefH1hsq0VkB91aSLAe\nmUBI\r\n=lR7c\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.7_1566218045432_0.6144418593342256","host":"s3://npm-registry-packages"}},"1.10.8":{"name":"3box","version":"1.10.8","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.8","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"b450d2d3518776d65d887dee24babb2044fa8a1d","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.8.tgz","fileCount":64,"integrity":"sha512-mlvFf0CPuu1KXQ+TvOjMw/a6TZ+1Fa8V2p7J4s/3yYlYfIi/51OISQjGkgpKQQYWeGgmsGi7JjetZDnPq2ukqg==","signatures":[{"sig":"MEQCIDHixuxCuYSCQxzgX1K74OR+cRfgibVq4/++jV5e/g9kAiBNBAL4oubgNX1rHVGaadQYgsca4czDTytfja0tbD829Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12492013,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdbU6WCRA9TVsSAnZWagAAS1AQAIcAzk47MqLwhokS9Bxk\nO3SfIIoxj3EImiTJjmLl1sLbSvJbniG5U02AeMTBKzT+bGnD5sKB3jLO2e4V\n2LZCJ4GHbC5FFpUcRK8YYlnFI2ks11GPwIt9EwB0SgDBHgYV0VbyK7NvegFj\n4hR/IouoSf8R9Zw0YHML8QWdLilq/VSiRWCNpmpKgiBvB17eIE7SW4sVgX49\n/UZ+UEjlPvN/SeBL0FbcrhZ4Q0G0D+ieuiYchq288HmGmIwLib/D457I7eJv\nICvTDosG5Bi0aZwAyAlnZAftbmdeKmQn119TU2MXXQlTzyNXlwbQ8jmmUaCo\nB2LfF0iK+nYLmfMEAnQcJLV6JA374bVT6DjqhYGzDhWEdESIKJkZFNX1uC8f\ntqvGLpPA8NIsHKRDy/jgGJNkFjp97uTsQPq4t0TqNF0Drvuo1ZIeYFzkCiSx\nZap1WFZnUI7zEZsa5vEdBzDZyDVjZESWf/CXXxXl3Nkwzkej9/JfL+vi5xGc\nuIFScXEZTqA55blLeVbebVcL0QrxUx+ke+eNwt71wKjpvmNp+NlpZb2f8mt5\nGDtLmT6xP1EUweZ8Getz3aD5BvM6ZVqoHEy/YmLpq2rfWcROQzL2dCGfWzCm\nonw9MdGaCtaO1mf7Gu81MfGoHYQIr2KNegpduA1jGQ36OtupjVrGSOzJoMXk\nmBaD\r\n=rclK\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"b83247c326f10b39e2c4f041ef83f21383a7e39a","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.36.3","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.8_1567444629649_0.6970779149778896","host":"s3://npm-registry-packages"}},"1.10.9":{"name":"3box","version":"1.10.9","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.9","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"4138fe00353a4293eba5a08256d942e1fafa2cd2","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.9.tgz","fileCount":64,"integrity":"sha512-t7jrTb60STks/u45sZqsW5ZQUeLAVlujsffrLNdUOaj/gt3qN2tGFddkwhmbObCKGYP8HPYmpz8r3sXQ3dOgjw==","signatures":[{"sig":"MEQCICRETY0r0F7ba8Q4/ZOOrL/OPGUaYpQYwcH8ExnHXGdgAiAb8Ex+i5+a7D2jIBylsMviHZIePBVbcSDATWjv6I8tzQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12486200,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdd9IjCRA9TVsSAnZWagAASkUP/jng633aNPu3yMjzd99k\nfzwOou0QaZEjCMAd40UeXeFHDqLC3H9h9pv+kMTiYCqbcl2Fmiwbu6tyq+8T\nLmfhaRZE+5jmqLDe4iZcBfYrLV8NSRmKyBtNwQ9rRmmuRj96h1bW773UwOFB\nsWM8a18IXGoBe0hP9Pj9er0x83SjAuvDcZz+lWeVxy4ambNymiFg9qWE8/xX\nZH7VnWau0a9DXE0NIN8ZX7+y0FU5XyF4FW9LQBPmvF5Ex9T1ScqrS80VOu0V\nzEiy6APMtV+WN8EeioBuWw69MK6han6HwdQUXbKNlCuYDK+Oj+rfKfa4R21P\nSxKimmbBC10Ppba7noKKIkbdQ0EgfC/BqnNwPKW+fhbF8BZO6WUIzfgxodq/\nnvIvdbDnJ0pL3N5PWHYbVcaM4teOVJ5ebmB74E5y3yQEsRkFsCV0KFRmoHYt\nhsqtxmfnqL5lFH4qR1N3uwK/LZdGubmr2fAw7YG8UCXZ/lKVJCQQMV3JQIc+\nQdmIm4Nxo7yIIKm0kMTVFDTDEOECRmhOzRTTAQXa6Nmb/8dMvsxlNiNJzgPo\n7vo+w9GFBCgrJi61Bbgdf/KH+eQvTUSNWT0gvN7+cFdRA0/nmFHpO1gGVhXp\nam9lzGg5FwffaZQtog+fvxBpxBT3NYco9BQFLk6AVtV3ACJhVM3aZOAUetyz\nXO3X\r\n=6xAH\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"2cf854a8aef9476d60e4fadd9e281f79dc562ef7","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.9_1568133665929_0.09960755362947893","host":"s3://npm-registry-packages"}},"1.10.10":{"name":"3box","version":"1.10.10","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.10.10","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"854dfcb093cd6d43e38bde19295ec512dea5789c","tarball":"https://registry.npmjs.org/3box/-/3box-1.10.10.tgz","fileCount":64,"integrity":"sha512-CsehrOK2gVbw6kPCbZOf3ZxekKcdnEwvzfidKbcs0E7fXa8jSeygGBRH1t+Fpcsv73PKd0mc1hqWMT4D4cC9Bg==","signatures":[{"sig":"MEYCIQDek8dKcYjosrbdU65pBWLmTbeKzLdX33Jq9CQjRg6fawIhAOO5Txu4B3KcSrW/0bWQVxlr0XkvSp7ZG25TrHj37/jD","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9577448,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdegW+CRA9TVsSAnZWagAAdpUP/1qEskmLYNlWh+5qKT7m\naNKAxTuw6yF5JCerpZvUxH0SgS00WcTJIvx4Eimk53es8jERJxtW6TPXGy+1\noK8Ek05s1sOgh5gvMhMzAFeKOlT/V758ElLBQJvAQf6lOZP9bkeZ6L3i9glQ\nvhFJ8yM+UdFpb5R8eh2wFcFxQeH8MLhWiG7izHrD/3x1RBpSuCffe3lDIcwP\noavXVTbTbdndFkJjJIZBGRdwB6H6vW2gqodfbhD/tSxRFGQpR5eawzzH3wwk\nD7+veuAhuWX/QWCn5EY8f7ApJWql7YcTHx59fQFSYEHXMdFDvEJkXx9NRNgn\nekUgFB4x2BLjSq0rhqxXDxR2iDON9op/mRBt0MpZnJZ68bYEAm1WBue02i92\no2gcJLgC3OsU7p9NsEJLLbiVCbyAGJ8zaNBjVY5s53QC7AuLXofCBhGJ3Hlp\n2+eiMc41qUDf8qX+vQnNu6XwMtFvrWMK4IibcMZa7HD0G2xaIA6wUo/0ARRx\n/knVlJ1bYP1f6x/HIm9zH6RdEwLa8GbWr77JfpJxe1R/fOxRjdDomPOo1Ill\nOhWSEYbpBr9onhMGsXgpfLfBNujaBAY3D+SHLuU0fbBHDVB6NkFrxfQVtlD5\nhLH8aJOzmVXKG8nTiQI/m+7kxn7npzMmUyyoxiMVGRss4/LvPVv3cuPZ2oT4\nvZA1\r\n=kuxZ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","test-update":"rm -rf ./tmp ; jest --forceExit --coverage --runInBand --testURL=\"http://localhost\" --updateSnapshot","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.10.10_1568277948942_0.8434001546647609","host":"s3://npm-registry-packages"}},"1.11.0":{"name":"3box","version":"1.11.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.11.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"11fb4ff878d462f4ea0436849e0097802e79c514","tarball":"https://registry.npmjs.org/3box/-/3box-1.11.0.tgz","fileCount":77,"integrity":"sha512-weOoYjZAVo5JgNMfeYykLnDsYx/UxEUQnoMImQ1Ua2+eFxsKa2wbV2s5hIrQlbxXzF6Qgexq3vtOBw9vgE6O7Q==","signatures":[{"sig":"MEYCIQCDoiU3UWPPg0ZLnNmhp/yQBte0TmynVqMkpexcSU5dxgIhAMeyrbMylMjDchgL4MspxpsN4GJzVoXXAHftljxHq8v/","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":9586867,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdjHlqCRA9TVsSAnZWagAAA6YP/1KfBYkuKBG5JPtF5vVb\n6GCS5RBeYRjzU/p1adFbp4CqDn0akdcjkzTnwJASb+fRMvfNpJYKkZL7MNDq\nUUroWif/9dHyTAB5wpmm29fBicJEtM79eQ+NvE3qNA7muXzFFYl1a/tlDyZw\nF8DehAkxSGZT9J1duAJ2LdQSF1OrXc4V9rYIFgWpsqxHiw9EjHixf5fB4Vew\njPt12Gp33FGp2kFk4c0d9DWSiYxe5rxCQhLc3l+zp/Z+2OPvt2M1yVvnsAoR\nIwQE91BjhhkQzXi3O/0J0hUA0gjgNZnIPqUyRqEc5WK8yjIH4UOglregUEZv\nmw0xx1wwkQsJW2uq1tcVTJj8HLrifvGVr+N89QYDkSIMUELdrQyz/lh9/hTX\nynnQ1XVk9FvJ7NIlKXN59OzTsydWoqY33VeZ+EfFzpvc9WegQDDmLPHgf09V\n7hzJmw04nWxh/FjkT0QwyVv/Er8fREM0o/q4PS2HAIPZINB2Y7FsM3sfRPB4\nkqV/fW23jTgIX9gvZQWoSJK0Fjwli1wgEhS8lMfqPLOdkyz5DxBX9vvY0dlQ\n22kA84W1W3iDnSkrRu7lHd9TFbcSPWG9O9USQZOZm4E3qGCbEdKykqVNe0Si\n0MdZM5ROc9dA7jSMIy3V/AZAeFx5Ztjo/bvGrtbFMu/QMlnm1BkA98DFS0ke\nZjHR\r\n=H9DK\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","identity-wallet":"0.1.0-beta.9","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^13.0.2","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.11.0_1569487208953_0.7025567237864718","host":"s3://npm-registry-packages"}},"1.12.0-beta.1":{"name":"3box","version":"1.12.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.12.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"2910ffa004c9957d3d5bac604b1ecf9a41ec86b5","tarball":"https://registry.npmjs.org/3box/-/3box-1.12.0-beta.1.tgz","fileCount":80,"integrity":"sha512-wMuFQkkKcZDC/t1iag+hMz+6sW+1gO35MOwh4ZymBNO1zDer5V2DROcn2ewWpyJ87AgUcOuucgRweDQTdRguPQ==","signatures":[{"sig":"MEUCIQCRUglmEYBTIdApt9uGQG8/jlhvkrbsJmMRs1Ik0T5siwIgHVMPOuusvbJTB7XTEcA+tS9/a55SHZAb+12HAjEIGiI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10510730,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdjhqZCRA9TVsSAnZWagAA1jgQAJaLP+yAP86s2tD2FYPY\n599Uk+HiNoBxtQ561Ji6fg1XaJ8M3Qo3leRuHwwtHC7jGalCdHNoWztg0V9e\nTzd13y+lckLF4zqvw8b9bsKEwBvMp7+4qmQYlSTs49zsTI/WVfOeBFPxXqPZ\nCxg4ZxDwN8RwM3Tkxy5XWt20KtUY2sWHu4z/Gp6eBy0QeMisB9j1DOcyH53V\nWGwIYduyWO5omwrXryTj6ilw/jUKH98NANJjqT1PIIj7fRBGotD5rujLG49Z\ni9A7NAERtvC4f+SFSKdgEZtNjVxEriHp+zWrabWBBFBQ8GmQXuno3oGyzv0K\nfha3NOwivPhKAQqzj17ciM03Ki2VI2vZM/hQfrzU7iV7fg/Yyye97HpeL/YA\nwaDjXv0D1V0+g5BhtDerGzvgNCdBWLTKDm6GkdRd2lslpce6gXw/Yw1gtJhg\nVLnLPtnXDhvwthhfUUm/LzNQZDOhLEScAYbhlbbYnBffR2LRmw7rCAkhbCTB\nY+bJPt+3oZgOIxH6/CZKsquH4DTKUiUL1WOMJRdDkcPAuL0ZuF8AvlyzadNk\nCdxKXG7hLvhWtJ0plor4QFyOmpot3RxGNCNCrZxWmn9kaK7JkhYSgc6Sm/wh\nPjpMh7PxnnxvvwPv6WApMyqqiogCBgeSPtvq38l0pAUYtiZL1PlZc8zyzz6g\nnCtq\r\n=sAS7\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(addrOrIdW, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(addrOrIdW, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| addrOrIdW | <code>String</code> \\| <code>IdentityWallet</code> | An ethereum address, or [IdentityWallet](https://github.com/3box/identity-wallet-js/) instance |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread (optional) |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.11.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","identity-wallet":"0.1.0-beta.9","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.12.0-beta.1_1569594008718_0.5014613154929106","host":"s3://npm-registry-packages"}},"1.12.0-beta.2":{"name":"3box","version":"1.12.0-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.12.0-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"bb76d0ab9a163750504841058af3f15ab80c0bc9","tarball":"https://registry.npmjs.org/3box/-/3box-1.12.0-beta.2.tgz","fileCount":79,"integrity":"sha512-EBgP2vq7IO2ubY8QyG3xv/3ee1zi2J5RoJNiEyeHkuFW3lZ14P3rhOspMSM2/s82j6+OOL2wD1Gqa0Gws5H5Dw==","signatures":[{"sig":"MEQCIFmsOFtn2MzvmONMGWHzcowtXoSPo6bh/Bjg1yR1BhJXAiBNECAFRXSeUtU6ZIH6E7q7B+vNuFYEqoLqjp2GO/WRPw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10448496,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdlwyDCRA9TVsSAnZWagAA0PcP/3UAQ719GlboBcQKYvep\ngg3Np5DkTZoyCXiHqpIxs2SUxcakSd2rIxiwkoF58VU7rET1CAfU4KRv5CQy\nuC8uAGFmu4OfoFatAs20q4zjqCJfkc3225RUeQfMsUbbKJJAQHSKgrOCDhJN\nQ+Ctt9St/V4Ofe/9PLVRFfpoIe6isGdO+VuvATXANTn1mbLfFj96dUFunNv7\nCtF5sBxkvaMkTZoBCl87esjnFkffMUzAxXyIYtupdEiRnUsQYVRNNUrwXQM5\noEbSqG3D7jdPSTbblLUhkzLOAfxk0rpVHA6zUdcCZFBv3n+4ZOk//HjcWjsH\nsEuT1CZmyKltwgVx9u7e4zkW9z0ZR0HSXUicdUEPRoCwaYj9ONmANAMe/uOE\n+InyTIMfHAT2zF4Y6+tGswjuFTsj2Oekm4TI2ylVCybf+ohL72sz57ii1kAO\ncoS/G8ITyGYhkX06NxSHKoavDjZS1TQ6NH/+vPzqQcFMKbicxqbAOM5qwmQ0\nzCUztABLInRCXL7BA6b98zZ3UXNyT6RkLIaW5Q5cydXl9MImToEctXf0KQtW\nATC4VWbiWDGvCyPYnC332HAGdCDW9rQBOQSFADuc1K6VoBRqNQw+SVzvGnZn\n1nJhXWAmHF5mAvYklyvnLsmNwyMCPpApnXQt/wX5RMHgblA19iqxL6S27jbL\n7q17\r\n=xaaF\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(addrOrIdW, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(addrOrIdW, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| addrOrIdW | <code>String</code> \\| <code>IdentityWallet</code> | An ethereum address, or [IdentityWallet](https://github.com/3box/identity-wallet-js/) instance |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"12.10.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.12.0-beta.2_1570180226376_0.5841853385563021","host":"s3://npm-registry-packages"}},"1.12.0":{"name":"3box","version":"1.12.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.12.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"20cce238cd537ce8c1c89c660ff2b3612c63ba70","tarball":"https://registry.npmjs.org/3box/-/3box-1.12.0.tgz","fileCount":79,"integrity":"sha512-vGEDC0MlxlsmgLLp8IYjSANGsvZFt8qVPRDBs/6jHwcuK72OZYWz7Symcb42h2JXek1tQeLMp+QMys5B+xRckQ==","signatures":[{"sig":"MEQCIDWlHPAf03TtP9avME7enRpzLMGu4Ab7SuEaiIxIeyyuAiAL+Mk00RU1vB0bbfg7dtsQDTnlqkU/by+FAriCd8BJ+g==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":10449069,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdl2G+CRA9TVsSAnZWagAA35EP/Ril6xlF/wmYXAPtxozs\n6l/mQ3rF5sXHkz1wKubA//3WbzkXToz4Vz1m/+TlzClXpxAY83k2gWMSi3WV\nMghydgS5b+gnywQoDjTpu9fCKSoj/pPzCEVBYWab5/SZXWbMw6ZH9HGS8iS5\nHogEjtPwvOeKPGItyBu1FI/vK+G28nb2V+s3h3hLgAtqWwKPJ4SHbpJvf8Ew\nOrO7OVFS7+vPdJB5ShkKXHD7ZqQJFDkgwzDlQw3or9pdNX1eiVitz9tZ5JAh\nNuPyc/UzReUYVar4xcQ/ruC1Z+V1C+Tyy03ifYP222gPSHP1VzsmYQ3sUQZV\nojdVkD4tmMxZfBF9OvnODiTDcDhDQ4sHO20RZmjjdhrW+ZLlbdOu1OJgFpHX\nyf/BtSQjC2xFl1dEf3TPfuMaE7w9pFR3uBoer9JzTQYO1wee4T2WLYngAsO0\nx2LnqDO/ZN/p1c/VHTI5cj98zI3hQ31qy8dJusPGtk/lZ/O4uNdkzQSToLGu\n3lkMz/nFQt8KcuZw5NiWXvvcmtCMr48LWR8Yf+S5RJwIDJbUEaARsNUo9OmO\nMlCcy6uhLmHdXHpu5wikwd+CMEemBxHn9RmLc4yr0gkvNH6cX1Dec4nDed/t\nqlVpTPVAI0GFUhs956mmUnEuRRjDF/xjj43fApilLv7UvlUsBsU5wQNTNcAB\nAN1M\r\n=sbzp\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"12.10.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.12.0_1570202045493_0.6400480561727759","host":"s3://npm-registry-packages"}},"1.13.0-beta.1":{"name":"3box","version":"1.13.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"c5f2a7c2e39c304a69ad0bfe52163d61bc0add21","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.0-beta.1.tgz","fileCount":87,"integrity":"sha512-2DB1q8xqfLBlV3dEop5qQazZljjZzSpqB7eUwaQLPMxWAZQMLB/1BQh3GmqCTtAY2dT/OFeDUcXP5jpH3CbuLA==","signatures":[{"sig":"MEUCIH7EW6PpsBvDp45VPCyyxXJrfHm22qQIgt8War/JjEvmAiEAwu+CwR2CxdcYM5O1RTRIBYdyi+ThuorqnKuPKbEWJRg=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12255301,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdmttjCRA9TVsSAnZWagAAKkAP/jHTuZ53iH+x085D+URG\n0MR5lfknZeR150pH+hrwFZdStz5yySzuIjeLr6+7al7YMGfJPCikUr01MoFa\n5oM0AYkltaAbLPeViAgC1u+PCAjyYp7pZQ+mWCn7CHJr5q/NbZ5rHkx13c0M\nZY/E0SD0/NnWZ0+oXaP5PJ3TGGeQCk5PXyXNED8jOmp5PJTKQPhwEe42hXD/\n2yGFGAEpCMq1dU1IOPWsEenvZ1Ei+AX6OmMYcyxkPnKfH9MykZ3aVX99HRIA\n6K+YdVsruskz9MIjEYKh5zwOsSi2Y/pwcP2H1Icjp9AFmIhYwt7sVr1z0nUY\n+rZNfelCNM2C0PEz8AiyYQ3+yiq2fxB2ThE5bF3XN4upEf0+KVpCRci4MPaR\nT3OfZw5YftD/Fp5YhWB+0vvCJgGfpDTace+yImlx62FwSi/t7LhSkjXmNU72\nAYSQwYnD7oP5sx607f2hC7XVKFkhDlG/pQbFWWOXRJXy0Mo8uHM6LU9GjWaJ\n0f7QkvOS7YwaYs/pBN11PtBqwy66SBCbkQdigurtDcgNIZpZzMofA8zhd0f1\n8WHPOmrFJeT0IdByZMFtuqWqclP5BioCSmdIRCU0CXEvVqv+aLd9Jiurs/7J\nerrLWt76a9CQHqBPKocvztmcjYaAyjHuDhvw4tMRw/XT2NDInx839Iw6e/lB\n1Nb6\r\n=s6LM\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(addrOrIdW, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(addrOrIdW, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| addrOrIdW | <code>String</code> \\| <code>IdentityWallet</code> | An ethereum address, or [IdentityWallet](https://github.com/3box/identity-wallet-js/) instance |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0-beta.2","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.0-beta.1_1570429794672_0.1494991146100495","host":"s3://npm-registry-packages"}},"1.13.0-beta.2":{"name":"3box","version":"1.13.0-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.0-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"fe98ea271544e40f91c46c789c232453eb964efa","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.0-beta.2.tgz","fileCount":87,"integrity":"sha512-IPCZMUUbT97d1nGc2zdZSHg8rtMMBdajKTRxaH3oBygkgKkL2UQ6dmPRpnS9DeJweTSf+DuFfXjTMUKgwxg/gg==","signatures":[{"sig":"MEUCIQC8j7bhdiV30dXd2sWd+IfGozfwC9jvwT11ypcpiSO6mgIgfyFKabjQTgDb0wadNNwpvXvl4m9p9RU+LuT17rMj2Ao=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12255054,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdmuLSCRA9TVsSAnZWagAAX9oP+QEH5tikD0YcALd6+wMa\nE1nW+3zbMnPvvvX8ZDjy7k4e+S07nfE4okzFxy27d8mHbMyFfzfmsHHFOIFj\nSiHPFv4+hJTXdpPmnkrLEvzpBwj/LkoZ/rvXm7UnwjE18ZrwyJ1NyiodxbiL\nOSZfpGABlkUisdJ1qSVAh5UhS59zAw12XdkR5NomRLmWmv2L/XTc954mDP1M\nRTLOuz36rlUbn7YSEZauza1lj9ZURLY/7PnFGMtc+wEeIYziAJlqm+lKljAM\nCK+1G6jZr/B1dujWN2/IaP9C166801J+7aMgFQJbk237NiigZ2BZGC7LzZtZ\nPfiDX8Hk0wtXn7tsHOUHxILvwGCJTiZTEiHeFDljlNjU3AcWwjSCsyc3sLo1\naQnYaetkS6Wms7SaXdF+D2xTbHUHerrGRyK9dfGHvtyK3yoIUZNobpvoq5wE\nqM9yvaPY4h2jBQ+ulZFuQFL4qqdFVC2cPKRoTE9C0CNGdKct7F8aaXk3ge//\nhRL+1rMDKo7w1buHCgitPgA7MnVhZDGibKsd+6E/jajmlMacd0HaoR1pNWXe\ntiU2VVGAPyCicMKAqiaGtDs1bKd5cgmp27iS6NkgKV5ymsi+CZHdWs2Yv+T9\nfJNaZiqmJGEXbc9/+1un42j40s6BH7mSjqIYqSEBQXPqDV0ly9mAYcp4JI+B\nit6M\r\n=GelO\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(addrOrIdW, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(addrOrIdW, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| addrOrIdW | <code>String</code> \\| <code>IdentityWallet</code> | An ethereum address, or [IdentityWallet](https://github.com/3box/identity-wallet-js/) instance |\n| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0-beta.2","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.0-beta.2_1570431697602_0.3285403576624075","host":"s3://npm-registry-packages"}},"1.13.0":{"name":"3box","version":"1.13.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"daa3aab8b2f73bcb4ccdff2c72e4916bb2307cba","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.0.tgz","fileCount":72,"integrity":"sha512-okvH+XS45EWBUIJS2nWfSf8v4VQw19/X3JJtStaVynntMMTDlcWX8IRzUhwSeHuXTEwNHp9G/prAklYnVYk3nQ==","signatures":[{"sig":"MEUCID1XZAsKdPfS65PR7XShjBQ1f7d3xuhN5pvkYATOiWjXAiEAhtPNHnd2EZwXoJrRR3n2kmXihwGazbMQQa0M/rZBYYA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12241798,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdqXp/CRA9TVsSAnZWagAA1jIP/1MW8C/H6Q5DwkZYTuK2\naNb4zFYzZ/+rL1MsT+Tw7N8IRa7Y1k3T+jHldHGUgnddd3y+oFhecHTswCLm\nXjegtKZyn9ROjqFeBnmySGYLP8yNzWEJqAodZXwLn+J9ZDyKx4vmhHbx7ILD\nQt4F171siTTYaW5YC3Bhl9WizWGGEM+BHiMj5GpA5B+ngaRBHsKXkhR8GmX2\n+LhAwOTcKkqbFxs8xWLVQxB21Vq7lvPxuBXpWFTlrhucgnWjGidJ0yCzHhqX\nbM/A4hPowdpw+PhSe2s/4/sIdPkxRxG8nmxcNSh92gVzIWMu9+ygcTUa3ILM\naripZmEyG4E1iNJgRDlwrafdm7GxkBJR4ESnZ0m3qG1NPVb5dmNc2pJA5Eax\nBM8u5YZZ6tzi4LyvrY1MxeG1wOoyvlvqJbGqhHSOzl5RENIS9PqACiUljff6\ntZfpp8vd7RpxF7KXk8MBZhNHb8LiwZOui/tUP7h9bnHfSrqW0ceHjbc02X1m\nFhreXbfYpBEEZ/zAiHtxYHSEDcf6+PHKO9uhHKHJ1ZyVDbtWBrnlcEeLCxle\n9MA/OwwHFNLACMPEoLEfRpTlyHYj1lqpsLz3shKL4NGRylH0YTIYDcpbe+Hn\nHLtLmc0o3YS9u/Me3lOxGHP23ZQA5q94Oqv8gP8Fw8FB/xrlpH7Z8dnI4IhW\nuJqs\r\n=5MjP\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","orbit-db-cache-postmsg-proxy":"^0.1.1"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","ipfsd-ctl":"^0.40.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","ganache-cli":"^6.4.3","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.0_1571388030148_0.7183391149591072","host":"s3://npm-registry-packages"}},"1.13.1-beta.1":{"name":"3box","version":"1.13.1-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.1-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"9763c6fab8cc1fee256327a4791ae09b97b9fe13","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.1-beta.1.tgz","fileCount":72,"integrity":"sha512-Wo2KCQuj4bynyMHZcjOBvyqqlYV9RfyXDE2UrpyXHDO7W1rO/HlZwbfmknmowU9YTNgROKu4rSi6vs9JtWuz1w==","signatures":[{"sig":"MEQCICkvkPpXexabBbXrKjqeYQdJZriJNURgAaUKz7G2EwiyAiBRC8y/0YfSETaXDDEjQbiN9+b08sqRELJplgbpOHt7MA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12241258,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdsFiSCRA9TVsSAnZWagAAKUYP/1J+hrv8Xu3jpUwCjHOv\nYDPeA53hf5PBYLxDhqckGo+ynF7UeINhyaKpq7XuyqFq4gvPuYY5N60XZuEW\nPUkIUvHgWr+8MY5847rNz484eFZbwNJFa0Xv1EaUZsDY7zoSkLM4aH3tXZ/W\nIoKZtqVzFkpvV/gnO0b9OTMQuIhjr7exi5HLsnZpoQQIk29oWLbBN33gZm3T\n4OGrjzhj1ueiY/eoNsy6WyystneVBt/2WvQ8Nbbfj5F3sIqlYR9oiaKfgeb4\nldFp1Xz7rIefh1hmcBD0aFwPlkqr5mUuxRWJYN2DPjsqu8gc71F1NCelrwtd\nedZkhowDDzk3R7Uq5dB5wWbm/MbrYFLNp22GNwOdPivtKZGFCNtsCLTVfGjl\n7GihEYYH0mtFTi8UMA7uFUAxp8ToEu34Sq4yO/7edPzS4XqNFOHYoljMIsu+\nMZsTn3GfILaCCrJpC5fsn8kVNqMD0v8xlsgw0LFG/EPqmvY2CmWh2pYbEmuV\nC2oQ8Z1w2KZlrTA0AujQPgezor5+irXNWtDfj9YNm6xi+BgGS1d8GhSUpaR7\nEm90cSBgO6EafWcZVey0G36VAwgAJe+C5K5sGcWOhbkQdQG3PQHUQ3IUTwdZ\nmZ0dO05JSXNeea35IbeJwOKPBiUbc/jtyvJkh6L/TGLbaLTRZ/dUi3PDSb7K\n+ItD\r\n=gtuV\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.1-beta.1_1571838097871_0.7521559013500028","host":"s3://npm-registry-packages"}},"1.13.1":{"name":"3box","version":"1.13.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"c270bf0d129836816ed334e3da74d0e59eab23dc","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.1.tgz","fileCount":72,"integrity":"sha512-/29oFzDcz8FyuHJPUlwMR9n29xb3ppaC1ftXg2iDKZfpu5YomRXt8siBuLKjVjEwk17se65o5bicejZIV6Q+mA==","signatures":[{"sig":"MEQCICGfpOE4uJ+CxtpfUraiH5jLm660C5g2RM43oKV4SfAjAiBsTJNQntT7mkOyF7e3+sO11qxzWPqlTLwKuqT/1VMs4Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12250130,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJds0rBCRA9TVsSAnZWagAAP4MP+wQXLX5DS74ejKQcaLlq\nDAiMHGJy0HNf/n47uHn89YzAEo+Zun031IGtqbGOtYsbkcxjBuuDU3RLTbga\nwdJKWz8d6vB1ocrx0jK1cNU2SSysfkJrCEqw5H7YgNYZ++PxUp2B8eK4xs31\nYoX1C7j6ptxgX6bm+OH+Bf+8Wei2kFj5Tf43gKvbBIKonUFACahZzWtxtmq0\nVMZL4t9PBZimSk6g7tbMWo+ax6kMMj7RG3XlZHxLbruMe9Oyf4huDXy1GaD5\ntkdfNyBE7XJH0R40h9bMvm5P1X+C17611EA+CZsIMnQBFMqVmae1MYiEjH2Q\nvETwkQsPNWO8OXNNEsfzt4cABCcgPMup6v7ex9fzKqRVSRI0wT5F9oHqdFTu\nte21tVv/2vYPoQGfeOlwYNLYVJzrxbgpUBKJ3Ap+y/FKdU3HsCUzB1mHddYS\n71MMdXWL5BXRqRw36IAF36HAoZ/vY6qiNTxG5ablqJr9fFF2dvX1Wyt87H63\nFP+e7wDF7bX8k8U86jWcKr3DT4pke0pDu+y0dSLR1YPzYSs94nowyjbuQtCv\nnHr1ft71wJE9UMhzFTj//z4H8aNa0RBe48JFa3+5C6SAkgYhjTmGF6Zzma2J\n2M9CRp3ZJnLQFnQ0umOb31eM8IyylS/r20P9dMeFQ0oj/q8QuGn5O7zWwuSq\nsVsk\r\n=pHdn\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.1_1572031168771_0.7247580861134719","host":"s3://npm-registry-packages"}},"1.13.2":{"name":"3box","version":"1.13.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"ef8c7830612c08b41970e70d309a417b4b2836ae","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.2.tgz","fileCount":72,"integrity":"sha512-8VvSdFXLUmdwCN8/J7tTQoIh0vBq+wZmiIRHA9uc/uEYo03IkBxEGPzX9fHpRe9WKdpMuf/oBYON26Gu/2iw3w==","signatures":[{"sig":"MEQCIC1BtxDtEBpbFOjyl+57nOKRFlRBZcMXDZubEQ3PqMBEAiB+Of7v3Pu63H2t2AipELuDRCBr5ARC2higC2EuXfo8zA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":13378481,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJdzdMHCRA9TVsSAnZWagAAD2QP/17VB5uMU2WArLzh6Cxf\nmSvW//7bKkMg4GXy/IYtVBql19rh6k739Zi0mitnVBFpMwDjpDMCBKrLrYOg\nDTbcq11JGmGs9uSbBOoop4rkDEuWySzEL/t7JjZ4Aky6mIuJIG8fmZfgX+FA\ny4QqDGONFSQEHljchjclQNU0zZM7hSsumFrKNgg5hmqmUzGqaNg3s3PGvgsl\n2AYsbJfva7OGWf30CgnBSJFaty6rsgKY02VV/RDzcKAHSXSIHAV7NaGMA7fr\nWMKj2I+qez1yPSDbZXmcsKpu1byMQ1v22ZH4hUOlGEb6rRe0N2TzrWej7oOU\n2VbJspvW0v7vMINr2filZF1fpoTdnLa7be2X8eVlObOZaKMAnImjYAnmXLYW\ntDAhcXTW1m7XaspIJCD2rWs1/VfDbtsNh4zFt/nCbAegACi8hQe4DuQtZSeu\npOSlQRFCXfAX9CcKtU5W26ah0Xnl7vwqGUnh68fuXM5cdU3/teoC8mD3Ms5k\n3PwakPtEWLJLePe69IycQjKP56NmhaERYTt2XmbDdXkmjlLgB9Kt0Q+PORlr\nkeuxLHUAemikBVdB01mEYeHK7YtzwUw6Sn1lwE1GMwLOWrU3Z4OmX2B6A9w5\nfvihbLJjN+USCpPAN6ayQ6o7mdBjg7DYPvXaMBZfRj4ipPA1DuEC0J04vq4j\nKUvE\r\n=ibMG\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"bbb311b2bd52582a6f30afa50a6a14876f754c66","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","ethers":"^4.0.28","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.2_1573769991088_0.46992602553015694","host":"s3://npm-registry-packages"}},"1.13.3-beta.1":{"name":"3box","version":"1.13.3-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.3-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"2864ec7f8fd2e05cf47529dc8de66594da1f75e4","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.3-beta.1.tgz","fileCount":73,"integrity":"sha512-H4zUIRtAjgIgpVIAZRUz94PxIKWupR4o2UWEkybVxnkLd+gwBtx3qpDiftuKALiM0WuNlNFElRfcYBXFxREmyw==","signatures":[{"sig":"MEYCIQCplaAGKLj7a1rDkrmU+E3YPq/i2fO2WcHfGzFzJr7FbwIhAKl/pLrNDsctC09BWj50m5rpiT5jY9vw8FUOLkjiZs03","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":11943820,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd0sW6CRA9TVsSAnZWagAAoAAP/12dBBm8SFdatMoUmKk3\nsdldY9fBxowr/8sGlfQjQPX8Bh1H8agGnj7a5vvwurqKNpv526eehQLWql00\nStQpzhihwevzCwG1o/MKZrYZONs8M/B3oTvw/eMWadJZCfcm1RbbAA5lJqxD\nK/UJRFECCBlTCMUcnRmj62CynqhQOe1UOkrANGraFv71DO+U/pbfmVywum/F\n10spfKPMnPfeoclGe64n9EzGmYOTHjBHrA+NWVD24XcM28C7qS4OEFadnSO6\n+ooLy1DFzI8gklvXHDQWii2VKDqC7Zn/PLRXejGcJlrCwhGBXC4I/Rx6KFwG\n1HGPe6vxolf6ZbMzhN1YSORafzUUHiVB9Yoq9pEEHCPOBK7G4t9ikFlnwZns\nUbuS9RSGSCRLG3hkkaXkdxrm0nIQd8uaGMVngP+F4Sg07Tx31Zc737KOtend\nKFHgE1k0qgc4Uvvf/G7w7PzlX832WfXKwjU0SF40WIakVBtICrKMUbmPgdhc\nuribECcLl88W0BlH6SzlkVtRGQQDovYM04jUA3beywAlhqCgBrPKAoo6/YUN\ntHU9Q/R+benie5gq1UbvMlga+grpt26bLK+eI1UNrGsbqXcGjoW7Ogmah6g0\nuM/p1ROB2lQCrDBMj65BIwVMw3KnzSkNwFpv5bytioO7O+/WdMJhY9FMn9Su\n0W3E\r\n=oAzN\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","@ethersproject/contracts":"^5.0.0-beta.140","@ethersproject/providers":"^5.0.0-beta.144"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.3-beta.1_1574094266038_0.2351486326258243","host":"s3://npm-registry-packages"}},"1.13.3-beta.2":{"name":"3box","version":"1.13.3-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.13.3-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"399c10c06a528879661c3f79890b0468397a1333","tarball":"https://registry.npmjs.org/3box/-/3box-1.13.3-beta.2.tgz","fileCount":73,"integrity":"sha512-wt8JW+rFnFQ9ZVqrE+8pROIT2/P0ge/5+zRlRBhbgLhSHhrzLtmCi2i/zSCPuw/q55+3WleRb+dbqUkJHEFcww==","signatures":[{"sig":"MEYCIQCtQO1MtqXGvUtt3e9ojBn/zL8FuLjjyTJdfVLRrofAZgIhANO8WaN1m0SCqtFCBpqxHRPJVgHkcUR+0POGUpaVWENG","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12764487,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd050OCRA9TVsSAnZWagAAY9IP/Rr93g21dv0eBqLqNyWt\n8jzBmU4JJK7BP1blY8xn7UbkY6w6avAAKdRghyjPzlfPIiLKwYxBJmIavzZm\nwmdMIWW/wvmfNUUAcoE6P0kcit+KmZIaHUPxh3a7ZD7XupE7/VgpSD2bjkMw\nDr7PkvwZ5Z/0kVW9wtQmsQw1g5NHRhEsB8LAo9wm/DlIexz5FXDFnpkenx4W\nQ0AxdpeYBq15f6jX+pR9pM4JPkgvtabVXHVze7BOKphVW9Hq/QdFpO10GBRy\nOIE67KCQgzHC9FPCN78MR04/K/ZtqU61kCew9CcBUEqd6DhOXhwgvZRaBvh1\nTchzwi6ZtJbXognyDQ7z0v+rMBvTh/H7pBaoeMRUwSX13bkVc/98Uj1TInxA\nNO2OOpK9nHUjkcBEYc/C3oBYfh9s4CB8M6ENUdQHwf3PDgYSUBcDvf01TPu2\nonfnxemZPY9GfdrziUoFO1Uc0ABOKf87mZhXIzf9/YeY07HMKUHwBQGa3PAW\n3+yvRUPhkptxUCEw7VG7DDwmtl/YxxfAB5TvxmJiKckjR6bUfQBGPgNI9Gpt\nXO1+txxSHCVBGfBD36hn991B6yjehYzS2/y8ffulQESeRi0ESnDyTSQHwnvo\nd7hrDu8YuTCeE7xNIsJVFrugyM4hphLTW2zpNLynkOD4lR4pLw0dtgO976EG\ng+o2\r\n=5/k0\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Default | Description |\n| --- | --- | --- | --- |\n| [link] | <code>Object</code> |  | Optional link object with type or proof |\n| [link.type] | <code>String</code> | <code>&#x27;ethereum-eoa&#x27;</code> | The type of link (default 'ethereum') |\n| [link.proof] | <code>Object</code> |  | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","@ethersproject/contracts":"^5.0.0-beta.140","@ethersproject/providers":"^5.0.0-beta.144"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^0.2.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.13.3-beta.2_1574149389958_0.03780327706367559","host":"s3://npm-registry-packages"}},"1.14.0":{"name":"3box","version":"1.14.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.14.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"2f468f8584ba38162b71b84aa9ec32b50e26d558","tarball":"https://registry.npmjs.org/3box/-/3box-1.14.0.tgz","fileCount":73,"integrity":"sha512-H+p7uKzyNHfWd4xCjw+sa2yZGQPUuX3x08kxQ9fmVeykNeF6g68fQuSen2SHcTs2Hf7PjAYysPZgX7egXtIgQw==","signatures":[{"sig":"MEUCIFpqWJSGyrxtT1ty6RHl0Iz6bFFx9ub5tFX3w5q/yXxMAiEAiLMUEXfeBs9+H4dXmBSQXzerkSepEaYjMDOS29PXFiY=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12656550,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd5WLtCRA9TVsSAnZWagAAZYYP/jUUsFiUELZhv2UR7IeA\n3ecr15UBNHU17vrSS0iK3yCE49ZfUdqqkA8WsxnnsyCoAPf7R8cA59tjqWxb\ndW4MU9yQ4GSP5oClyAnSnMoBXtLYjTi7RGBi1EQUyQkUVLmtWgf4x1mkWqMF\nMKufwhW8KHQ7823opFmeUoBv0DaWiCVjGN3755FsfGlYgnrLxZQpBVApl/xN\nF7i3qDtw5x6bLm0iJcALk8DaZ2t68X54/r6IdY+wvhPQD1+Uj0TFTTS4KuSC\nN6vFSETpa1D2V1o3iSZjjqNNUKKc3YqD3+7TVtl+kaLW6gfJk1BlL9AZ33DT\n4Tsp4uHLuo7OZHdRBHA/BoZqDBaNZUodIa31/9kDmfAi7pPSiEynYXAhLq3G\nBXuV/gA+miZK1qpTIsjiUYL6E/d6S0M15yuoPOpWXSHeZIDoCPUGBRQangCw\n3/WsLMpn4w6Ze8Q+MvjrU52gKyTJGtSHrXQrpcDN3XqwDxemqUPZcMev5fIz\ny8pgbeSvfIQ1QcZfk+WlCf7slxWlzYrY8hKofDCup5BM4AorAQXWqBQMQ187\nB9iAJbWnuX/98YkwA776WHQAlLdYeM4LijoYCjrDvpcchmLA27RXCX8Dp1CB\nQPyduW26j0MwHnpatzPEDAdQuGTC+3HAcfCFuRq8723ujJBMZWW9y90u9ynR\nf9mO\r\n=w0Mk\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.0.0-beta.2","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.14.0_1575314156589_0.7978822448522804","host":"s3://npm-registry-packages"}},"1.14.1-beta.1":{"name":"3box","version":"1.14.1-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.14.1-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"3f582e17d3824548b490fc560d4db0f1808142ec","tarball":"https://registry.npmjs.org/3box/-/3box-1.14.1-beta.1.tgz","fileCount":73,"integrity":"sha512-R+sM2GbDDFRLQkOar5YyACQky1P9M1s7FWrC7MuJb2y97QqbKJ2k+cR/MX1EwKfy56fAci305loQvg0fLo3KvQ==","signatures":[{"sig":"MEQCIDWTvbXhw4lONX0pXwjPzzeEmSWWuIQd0HySD+w/WNh4AiBWCkgn2EB6+49/3qoi15fyAj2D5xWAcgedUH6iYM8YfA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12657915,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd59CeCRA9TVsSAnZWagAAeOcP/2tWCRa+h7qROy3kF6+y\nWjHIIku9gZf2fFNIZhof1+I35y2TxKrO8BbEZVAVP/WK+rXHhRiXCd2Oi0zf\n7vKNqVs6hP42Ko6qqTPNfcBOWu7ZsGXTaqLR5smv5Q1OqpqujZWMtUx+jGol\n2pQc6p2Rm60/QKc4GOci84WSu6S/ch6mp2+AL5oacdq3fneO33eZBa9FUxqa\nkHt2PHLO3jjxgtlZKPpw59ffB6UpRn9+H8zVWjE5w2Jp3cE/Wc97IcLLTAc4\necUtckrx+agl9dfjuvrntWVt39NX8zx76wixxaGra7UsBWVksKBGsHVoG67N\n/8f+jlF4b+uRQ1o9kxCx0XXHHzih+/V6HGzybbm28++M4Ck0DGaxTZOuyMxg\ndROkRqzhStaZwLNV5TEx6ekxAnnG4dZ3MziBqCn5pg766yarpmyiJ7LWs7ub\nGsDxkw2Nr9iZguctyNafBIo5gGa0JILAylzl+Uk/5oQYe8xZBsYBmccZQL7J\n5AUKJcvE0Hsz7FQyvBrcKG0A8lw1dUtiSu8qbkWEkMAwQpuuYp8vIKkbBlKM\nqOfmNtyFylvEqAvjHnM4k+KPljCxttQ5pfMhpRIfaiRf/Z79xF5RciK3eXTM\n24OJUbxxi+HucjG0CuYlcNxo7eHBb5G6P7EpbfmBzgRuUiPB1aILGxVRxCy8\nL1o0\r\n=A1qK\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first open the user's 3Box by calling the openBox method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Authenticate users to begin new 3Box session\nCalling the openBox method will open a new 3Box session. If the user's ethereum address already has a 3Box account, your application will gain access to it. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n```\n\n#### 2. Sync user's available 3Box data from the network\nWhen you first open the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box\n**Kind**: global class  \n\n* [Box](#Box)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.getProfile(address, opts)](#Box.getProfile) ⇒ <code>Object</code>\n        * [.getProfiles(address, opts)](#Box.getProfiles) ⇒ <code>Object</code>\n        * [.getSpace(address, name, opts)](#Box.getSpace) ⇒ <code>Object</code>\n        * [.getThread(space, name, firstModerator, members, opts)](#Box.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getThreadByAddress(address, opts)](#Box.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.getConfig(address, opts)](#Box.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n        * [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>\n        * [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>\n        * [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.getProfile\"></a>\n\n#### Box.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.useCacheService | <code>Boolean</code> | Use 3Box API and Cache Service to fetch profile instead of OrbitDB. Default true. |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getProfiles\"></a>\n\n#### Box.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getSpace\"></a>\n\n#### Box.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThread\"></a>\n\n#### Box.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getThreadByAddress\"></a>\n\n#### Box.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.getConfig\"></a>\n\n#### Box.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.listSpaces\"></a>\n\n#### Box.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"Box.profileGraphQL\"></a>\n\n#### Box.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"Box.getVerifiedAccounts\"></a>\n\n#### Box.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.DID](#Space+DID)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+DID\"></a>\n\n#### space.DID\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the did of the user in this space |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.0.0-beta.2","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.14.1-beta.1_1575473310042_0.2712204086746426","host":"s3://npm-registry-packages"}},"1.15.0":{"name":"3box","version":"1.15.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.15.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"41d60b5ce6b0ddc7a6b4f71fac06d8703875e368","tarball":"https://registry.npmjs.org/3box/-/3box-1.15.0.tgz","fileCount":73,"integrity":"sha512-tTN7ptyfkb++jLzxMjpWiyrYh+H7wh8ATfGRmQBKX9nPMs7DRREa52Y2uot85kxDZbkCsVRmza8nlXd9LY53mQ==","signatures":[{"sig":"MEYCIQCQlNg3U87dDuBiPN4GXCa0588uGyBgHOeKDv+EMDGFMAIhAOc2YldEAb8DgSTRkZE4D1orGN/blt853YzzUa2A4Yrb","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12683405,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJd84HqCRA9TVsSAnZWagAAwKgP/0v+JW9uS3FWsX5psWty\nejZ5kBAk+bqMNe7TTcEbo62OURVpev5VfpvJ5iyEgUUeRZPzsVU+R6seq0yw\nyLZqq1gn0RMfOX9we+MQo/76/WbnsYlPyEFmpIu0YZIYvigHQTCv1aef9NXO\ni6abnNaAFuR7qJfx9/aMYiLsLhrAYRz8rHwOXU+UmqKDZgdq65cHW+XkFQY3\n43gLzNLIbP1W9lMHZIaWuGkMAvt3IZlvbksptUtXcYhJBp/qtkq8EmstCsyI\n+PjnOSgLjGDe4hRCdwoPVcCIB1ZymOwPq0HLT73U8/T9HIm/o1VDuaOA7XxA\ncjVUAtkcbMwhUo/gF7HyD9GFpx6PWCvQUvIBuFIfdDkZwzaLLddPLRc60YPe\n2FJMt/m2x6Qs4g2ejfQ/I8pctSiYp+110b1a6+wfoVKMI+3qXTbK4acFjJjy\nK9PpsFj5n/gSF8ZPk6XMOuoDBr41UQ3GpnBC9bi1/6B/x3wA0AhEY0Hit+MW\nUdnEHg8xBrgjzG+zzpV/GRu4EHt9m9iBlFbTdRsgBxM/BqhnVcy0/YEh/+YC\nweNNwSsszbA2ox874FRyUObFzffMlbi+0yhDwKco7SI1FcqfekKsyw/rzUlk\nOTj3KWqgVL0tkwllSqFu72bbyYFIMwufe/5Jy7rwLgrIsxajr6wQ3eSNX+fU\nRj0I\r\n=5bGd\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"~0.21.4","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.0.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.15.0_1576239593820_0.5234958086586083","host":"s3://npm-registry-packages"}},"1.16.0-beta.1":{"name":"3box","version":"1.16.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"dc612cad264270a776495a94b359962c2c4aad85","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.0-beta.1.tgz","fileCount":73,"integrity":"sha512-ubtaXN/RoR1T8pCfhpo9CIOgGelVvPvkGHcmXDxxV5d7kDswSSTCf5DsEvZ2HWm/q2MEtC7PV4e6ANqK6u70qQ==","signatures":[{"sig":"MEYCIQD3z9IDpJD1p+DBuJ154a1BfK0xYkm9s8ctNIJZd0S0VAIhAJXpCuWPlIIXCLtfpfBXoiWJygKpdIRdVvaY6Wj5ehUm","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12738507,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeFEeGCRA9TVsSAnZWagAAS1IQAKRs0XJv2rFz6GQKsASc\n4Ez7Rm6TcI4iEIKr9AWl0A2IjtVUBotAIdbKKSaIGEAHlDFaItEaGu5rmglB\nePjKmfMyFH9Jy3FN30v0Y7kxUW6pKucVZq1nPZQbztn+v8leRjAiiLq0QyLI\nNVdI1rISALS/8e0fk8gzbP82diDrL+shVFDsqY0GPmCP84xG8/Yo3cPc9ot8\n4N36ux9SE9To3PHxjOA7kokCZqUudLEKVlmkVnfv9t9ECKhnPtbzksKwF5rE\npU5Cxt0rwIzzh1w9+nfH+3dauIwCBm/caJ2IWKqRx8kf2/zluX+IHN/syZy6\n3zlcjjWQrYZkKj9EF0z/wk1tGzXwqZnUmqBJAMol+VBc+7xlce8TyhL62hKu\n6BOGI1PCSdq//s8InNBqk6JU/n8e0QXW1toM1e49420wk+LrfFXll2vYCSz8\n3W5VVbxQkyyQUGph5Ofjdju2raXknuoVJjFaNouACPOfP0s80b13TbvoL7r3\nXDfKFfOdP09PA8+nljrmHhnsVMFUTIo53OgsLa62H1XwsVXWF2sPXWLOfQz0\nBZ3R2CxHRWqkMjNdkKeG9UojcJMgujyktcSr4FF4CQ8l8VXZo3IWBfpDeLJB\n/bVjYvw2GRROk801/ZC8bpwqjlh8bRIMCrouUpmUORfYbZO3d/yZ1bid+CxB\nvtKA\r\n=Qhfb\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to joinThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user to be able to post in the thread.\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.22.1","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0-beta.1","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.0-beta.1_1578387333925_0.9590954786320656","host":"s3://npm-registry-packages"}},"1.16.0-beta.2":{"name":"3box","version":"1.16.0-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.0-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"97de4e89d9a14636f387948556141d276cdd9812","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.0-beta.2.tgz","fileCount":74,"integrity":"sha512-DxYFphcl+0RX6pqvb9dGDZNbxBh4E6YhOkI7rTGXj6yPAEXxCPhVOe30raLbMIfCID/XpVlbcUeoM4e+H2SzSg==","signatures":[{"sig":"MEYCIQCOSdCeR46zOpHZX2h4FcAfNVyz3SXX8aLbYPSk4ZvQHwIhAJbhZ730+LjD/YKcgiITra4rLrNjBOQa4WDnCQ3k+CGn","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12924398,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeFyRcCRA9TVsSAnZWagAAKkQP/3xG+S19PAtyJ/50OkhX\nzy/mTB7laTE41mYEsVLvTw+0D1xN6tbIkQFz2RwZddECbMJt9Wf31LsJZy/r\n8oCJdWU5Dh29TJbq6obMx9Z8ESVBptqKytl1RKgnqw5cFqUUME/8R02G4f2V\nNz/yAm9yW1fQE+PW3OXuM5I1OrgBnAZxZuoZuW2sdHoqX11BF/C/rALFw1ky\nJ8aK6aAtr7QBZpcr0WxMtDra343/vWZXuvqy9u+NRf7uR7wSGKdgZS7AwWaK\nVe7Y8vtZN/6BxD7WQrzY+zL6gFSvd8gnrXEgEy8eClp36BxzyWo0w2rKLAeg\ndmFU578tItTy8c611j1G2yK+PGJaqJ8UNSLZFC8fALd+yEownucsFfu23N41\nE8zdC0oSEJngT2KJTYMQRqXdsEcf5n7DPxMguk1S/EyEkcrge03G2kfQfIGF\ncdWIHc8ANySvNDvaKYFNnPaDG4Cn6z6kYnPcgoL+u5j+K3L219mSyIDn+N/e\nRYXH+lQCtDNX5PhQXW1B7dWP0+KW75LURTsUh/v7sZDwC4hVf595GT7G0LZE\nqDzvzD4GneIOzsgezLNqpJLAIkL7glHaPHlIxty5tozuH4Ed/gqqJhK8+hTM\n4Aefd70SKZxOe4V3EJvPYQBqRy0AR8NT2MwWJN1cPTWMio0pRDKc0FKFKYKi\nnmsY\r\n=atOP\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to joinThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user to be able to post in the thread.\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.22.1","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.0-beta.2_1578574940306_0.08512221138908727","host":"s3://npm-registry-packages"}},"1.16.0-beta.3":{"name":"3box","version":"1.16.0-beta.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.0-beta.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"31dfae9a7259bb3cf11b8b91cdbb2d7a1b92e5c0","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.0-beta.3.tgz","fileCount":74,"integrity":"sha512-/DBok4/mU62iVr4bWeg1JICesKmkHrWlnSo9EGU+2X7QN7maRUPl4oEJRk0ZhQ12ihL9Ge4ObRzPr3qd5BTZmw==","signatures":[{"sig":"MEUCIFFKEICHvqalP0CYutBZw+4iDtIv4ylvmhv8OlYCxF6DAiEA3cKVHOVGFApNnmCC4Q3PNwaBYBd8758L4cr09gFfAGQ=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12927439,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeF1y0CRA9TVsSAnZWagAA7okP/3hueDVyMHOWiNwBRszv\niLKjLf2kYlRwc7YKq/ZdoniJXmrZS9GjJ6twp24Rf2t5riWZ3ke0DGTR0dTR\nAhdw8s7H10GM/0AMoU6+uJdTWirN7MmS7Nfjqhrr/3bQP3SUJxWO3OCmAJmk\nbPGVyplotPhshEFxp6/daOM7ivuIC/rB40WAO6knG03wovWAU27tfDnHvTHF\nCsTePEUCd5333MYKoxbHHCKC4iWOS43wI97HQQ3mI8fzcSfzcP878HPjat12\nBaUG0Namz+9uLQ9U786KYhWunO/UnUODj2ngHsouUmGe3bDwnNALFnhT+OpK\nrRoJ70/DpzsCEkwvCJ8Eur0bhyZurbN58QDy+S56Jlu8uG0AFQMrjYr/IaYS\nqjCRRR1Vowc966Zrc0s4dOIF0+XmhdWiZqwlHfzabhfX1xnlzTaPJ0vfmlQP\nhEJFTvQd998oncN83qYhb8f7ENb/K8ZvVMcAqc5SjWW91KLeYDK9V0v4ic/X\nx5vNS1RUQJZc96Qzes1XZUMPV3q4y2HcT7Q4gbuGw4EcYIEKaYLahqb/Ln96\n8ZHNT7HFd79+/0zSbiOtQwaWMoQBF8d4skeca53ZJyfZ9nYfwlwnV+/g/4y9\nmwmtqA2MTtL5PHK7HL6OcP+feNl0LOj3kN7x3UKA5uxfKAKxQAPiLfD4vVFN\nxKhE\r\n=6Tk9\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to joinThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished!\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user to be able to post in the thread.\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.22.1","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.0-beta.3_1578589363994_0.5798052344126656","host":"s3://npm-registry-packages"}},"1.16.0":{"name":"3box","version":"1.16.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"878084291d1b7c47e830d13f04e7aa0b5b34d0fd","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.0.tgz","fileCount":73,"integrity":"sha512-Y2/uJ0duqq6t21PPQ6L1lptQogo9UFhsoTS4GnoUev/iU66p3/JCWHLS01LNfH6NTlCUIv2M3+OddHwKgNYe3A==","signatures":[{"sig":"MEQCIAfcJuap/FpKWrZCNPFlsLHUL2mAYDZOG4UciShEUfK8AiBpElTAzsWdJVB2X4+bcWeYobt3+T4a2o3073hQPqvQaw==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12927995,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeGLMZCRA9TVsSAnZWagAAvFgP/1ZW9FCVAC5rF1mnFeMh\nYPeDc0k3sMhWZMuqKUrl1KRB1EKebtGlUbJ2xbMyMAeVu85QqeIr/n5lFDdt\nrU3q52Y0wrP6YSbjqAgukvjYa7NIsiliqNGNGcVLlj5BRTGuGg523YejdoeV\nsLrt3gSl2YmE7eoG/1ajr1g8hsac/mTw5KaEHGQXhFdyuOrsGqWVhDq7U08h\nINq2HfpzsLHL+KJVNNmpm1u2fnlriUhcEdTUy6hTCn5zFUBXvH4OB1YjVxLp\nGL9cfgcHQIly06FtC3IIKnUIwnvQU+zW8XoadUYXmAuqvkl5fN8JJR7oLLvD\nT4Ddb8mHh66SYLJzTIF5bJ0rZljQOfWBEGqZS4/POPipHAKSHFxH4Z7WjpLV\n1oGB9tb7mV5jGBHe+ZyTJhfQojaP+10ez31WQX/+5FJhz9KXZ8zGvNsqLhJe\nH1ilRJyVuHZavaCDM7kPmyg7sYcuQQ94kvQXq761kp1xM6EfA9yeQtrYR7kA\niRwGVlxhlG/zsbC/lOcis6xJoD6yCBclkvxolmL56qgTijEiTWALqxpFGVir\nNCyWGSto4JrEr107ZXimZjSTJb61BZ3W/UY11FGKDCpBtPfYve1SZMRkQhtS\nXX29c+YuAThUnPXVFqGQWEWM/pn5EyhJteAYQGWM3YdoSa28Cm82MVbctTax\nCaUU\r\n=cazT\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.22.1","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.0_1578677016382_0.10194678984252015","host":"s3://npm-registry-packages"}},"1.16.1":{"name":"3box","version":"1.16.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"ab1d5dcfd2b596c666dd8ef576f82647ad7e2cd1","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.1.tgz","fileCount":73,"integrity":"sha512-Ac0LbN+g7jsFymShe29kXooUER1r+0yXNQy705VWgcLc+T6PasasWULeqXcq4ZXxxUIWPWqGCxOYAOKzav5KdA==","signatures":[{"sig":"MEYCIQCtBEbRSGutfLURXV+CNJy/9Yaz582IkQqpi/rBhwl5agIhAJy6AtVXjAa9JOImzoOGF2l00XEsinlGumB7L4DPp0WZ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":11148057,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeHMt1CRA9TVsSAnZWagAAh7oP/0prgHtqlrgYyacXKsSk\nCijKm2raOagFQwts3n3ekoznn5DZv9ERA0ha1FrZStklm514LNv7YdzDqYw7\navbV6053XXIF9afqvnaq0ZEnkKgGhkJib6fNjtj4eXRd2RprHuwYLHkUlVL4\n4EzlTBQgdBmZRwZ8BiLQExPj/Fmu2752fHlCai3sBi3c+tdFMaRgUHeGJpIu\n7fUvN+JyG1hqWpeFCMzJVqdzdHGShzebcEf6rCkAPwDSbbppox4QGPfYbLS0\n5fAoH13pk6UUBKLIMRzGJDtQJra+eGeED0nwu8h9qKaIN5Gge0KT4wloErwE\niFI+OAa1k3sOv5vgpewywHlzjxbGvU3B0XzdHic7eztCIKFPPBOy62bQr/U1\nBYLDQ9+KR8w2n6bpWgeg5k+AJ8tM4RmIu6uzGI1mxJ4l295xkgfNS3TjksE0\nElM4/WULKfVdWor4bAMqlnnUvmAHMPmxGOJEb3HaxsoaMYtaw4UXtWE9pc1t\nBA04TYv4k6ZE2zsd8K4WlgK1F2jbMDIFdWr8bsRmdAybMwFvY3OkJ07h+zyX\n7TVG6a2DprW2BRHW/DMEK3/M4v5k/9zon7pllPoalWtZVAwXqV3WC5iwdv5A\n4CYSjLOdEJfd67ZRL9ZAQMEOjOH1xBNP6ION1DGOL/taKH2+mG+dhC8DWXoY\n+I+o\r\n=L2zB\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.22.1","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.1_1578945396590_0.9815565675967699","host":"s3://npm-registry-packages"}},"1.16.2-beta.1":{"name":"3box","version":"1.16.2-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.2-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"b1659c2f1a631621ab1a71b5ca787f14b878e0c6","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.2-beta.1.tgz","fileCount":72,"integrity":"sha512-qxeuIpw+ouOm/Z8rWDlLXhFZNzwoA4AWd+n22oypRGKiqUuPVpqaq9+leN+jBbDJ9UhvoM+JT/A7mAw9PGGifg==","signatures":[{"sig":"MEUCIQCjRJkT+F5Q6EkgVU1dWQStPinyPPUYRTNDFmDwyPkrWAIgSPKOA8In3mXFM7c1cDUclDFuUv2VsaSqo/3ojC7F8y0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14774989,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeMs+TCRA9TVsSAnZWagAA+ZkP/2mP8K4kYq0OysNFlja2\nPx/fi+SpR6n2ZrnuD7VT+ZeJhcU2WRg/ZoLdTpEnVTa1J6raHYBmnKto3k2q\nkQPh45arcCZlAnGAhdzOfqDtVKHbUB6FLEdxiOcv/uunEA2QpSYBBUWAVX8w\nhE5BNb153hG5ajD/6n11Ub6HAW5QyOymT20ffCm//VFA505QNZIq2QVwmiyP\njDA9/vdxHoRmTtjJ6SAaOGGJqQLUZvQRJN6jlHygUPwtkjCGDVxFMuuJOVNr\nEbd/1uVWHFWXSkE/cNfriE+CZ/c8U3tuCML2CyTtaRffCeZZ8RUHnozWnWLt\n8+QjxPggnbe8HOWwsGFbxNL2okoBBw8TPVdqNlj3hNZGtz6yPp0GSUE2dFIN\nD3d+oKboABkd0QJ8Mhp0J+TUpyG0iPTM+NL9luRN9B830K0n2E3tDP0i5NYr\nBIJxU8jjw8L2cCxjzKzcGQwwifRCGQID0/swJ/pi3UWy20zMJdfJwwXQIxEh\nxJgYDT7DG/z8tqDNOlxCbeCEOAm67bV3Qcq7bbv0EO7IgMfY5itWovZLO7IJ\nHLHxqJjjG5gsLitRLKchm8F8gI1NDXTTr8vMHUEBfcHXGr2ZPgrui4Hu4dma\nyc+t5ufSl8tCAAkerCDAYbKFSxCSovvn5V+YDhEYt6Re4sVT4iH8yr9uUFhY\n9/CS\r\n=KZi+\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"github:3box/3box-orbitdb-plugins#feat/orbit-23","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.2-beta.1_1580388241866_0.08494664109111794","host":"s3://npm-registry-packages"}},"1.16.2-beta.2":{"name":"3box","version":"1.16.2-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.2-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"dbe8fb740510a7a2f1a039b3fb5c34786f404fae","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.2-beta.2.tgz","fileCount":72,"integrity":"sha512-tcu2qJYn4jVmL0IFXKkoMipoZ7xq3ZY3mtHW5WoyQHmtQXGgoMwqQ8+h262vB7geD8yoZzn2hqlEUOdLjXrK9Q==","signatures":[{"sig":"MEQCICBdlnNdyt2oZojDjTE1DK7P6nTLImmWRSApCme8QIxNAiBDsA6MHZgTMuB5Hble8beZQN6ruzKQu93JB2zOoMAYcg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14775246,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeM+q2CRA9TVsSAnZWagAAc/AP/jLiBGDnsvVMQK2UKbXB\nIBKyL5awkq5GTehcrzbRoNAZ0OmpHeO7Sfo0ro5m5wU9LZR1f0jWDNLIUHIC\nt5JyFO02QhJLW2BpUnKM1EepqugD/H/EXW9z3AaHcinZONWub5c0SIiP1SXY\ngpRASeyD/Gjt36izzheI89et5qtLQnzNqae4wETlqeo8P+5yrmNDncgmPinK\nYuxhm/XvHu+6K795kKE1VBdUTLzNQwEikfVUaCpDcYP+r7JpokezMp/VZ7ZX\nNEWj5AS6/lnIQxC3CFu+I4yIiISHKeXVPtga9A9cjqolcw3JQOHQpqEKrRI8\nl7Bq8Lj3fMlWMknmG+q6KTYnE3NbmpiIxcVUKRqNi/9BmBydZV1OraR8qsYj\n4hcZMq5ne0QFlGyNPnwRnLLwaGsjyRosxOOzj35QhLplvjfMsqwC+YUYmVy2\nBvEhnKCWkoTKMiGTBo4grrjL5JEL4q4s8M8iim+xe2750U1CO1WJ5A/CTUtc\nwWSR3UVYAXYV3EBH4nIz+CalV7AFl+NAOURh2ezO9fb9ubY0fD4GcAPcT5X+\nVrtd9rr5XNt4V8O9YBIL+tRZdsE0GiY13QvJ88B+Q5WNZXOLWmlODlJJl5x0\nS+D/lCBKH8oodiA0rnCVr51iLbYnZ9sFp3zqwtMK0A/2dv4ywWzHr16RK0r6\nEip1\r\n=BQCg\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"github:3box/3box-orbitdb-plugins#feat/orbit-23","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.2-beta.2_1580460725025_0.0219540193777521","host":"s3://npm-registry-packages"}},"1.16.2-beta.3":{"name":"3box","version":"1.16.2-beta.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.2-beta.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"1320043440813a5a542c4d2e0a5130482e3a192f","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.2-beta.3.tgz","fileCount":72,"integrity":"sha512-TWK4czhWScUP4qkUxHI+407+dU1Iy/Q6lprtYFRc8Y2nI0vetYvEbemjPR9paQlkw8arjPB5zY8mm10ZvKfL/w==","signatures":[{"sig":"MEQCIDFrDv4+wApGalAjTge4YNSim8qiZ7Ei5ooM61VzksLTAiAOctXROiO0DqNKgnJPdXA1sXKT0HzOz83bEBbMXg6mAQ==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":11148289,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeM+8NCRA9TVsSAnZWagAA/VkP/15297zfGxXTkB2HbKFY\nIex0jixZabtqETnmPzcml5uDX6a77MgyJVObfJZmbwYuX2aGF76zlVcQfAJz\nk+wXlX/Zttqj357HO80smEnUKjDU7Fr+qPaMZeSkg291MI34Ea2cuW7jEHMs\nZtKxIPXF4vWhiRfQ+DS//V9nBtna7GR6fH7IfwUXbM7GjR0BhG4DF9HmDSWJ\nHY+I1GDbThpbJ07/K/0w7JtW98p/IpYKtALmudeDZKlqhp1IW0UAxDR+uoMF\nDaDGFP0LHdjcaEvMNCKgqYMELk3WpDO0Cm3idJYJ8XWjciFaJEP9o2s7w/W/\nxanUAByj6B3NZ2HhX43p5GRQbTX+XMuPTvPwN+b4ECfTBGGN0vmXPzc1aoqb\n1JlAXUCcttvqn3KfVlSeCAxACR7ALHHknj11hB+afApi7Zef5KQRIKBoLfG1\nckzFTEceTiPV8J3UW3dlpbYyYFGH88/ey/kgs+LRq7P8Ohi/jQlwY5kPU+NB\ndq907UA46w3I8iDAI1NmYitfy9+/GD83iLCimFlYlqNi5U5rVbZHnpJptXmW\nsq8PmUItYDouLB7Rda99NLNgEi+yZB8U4wRP8SMc3x9R6KLF7h4zf9gZnmOp\npGN8CInaPHCSp8j8ixvSksCP7FaXjuauzGpUXWgK28MXhPWQJfy+hi67/zDb\nZIN3\r\n=LPK+\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.36.4","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","orbit-db":"^0.22.1","ipfs-mini":"^1.1.5","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.0.5","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.2-beta.3_1580461836722_0.8308104694368199","host":"s3://npm-registry-packages"}},"1.16.2-beta.4":{"name":"3box","version":"1.16.2-beta.4","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.2-beta.4","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"cccb3a3ad9003a48e6b4bc2555cd74d41042ad5e","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.2-beta.4.tgz","fileCount":72,"integrity":"sha512-g16DPgWHRl4DKXUA7vlSqNf4w37ZeFUEtGIXXF3ZDyQAqYS64q+7qdBHpehpLu0hsZz5LhouPMRItKSyt20w0g==","signatures":[{"sig":"MEUCIQC4FXsEsljLssKoeRoPfLO7xdFLAq12rmQ+wMa/aiAKTQIgGknt18yR7/7m9qnnXSne8MnVifEppIoU4p3Jbn/NqjI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14775246,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeOBF4CRA9TVsSAnZWagAAwbkP/3nDwTiT/FoqEVwvk1qm\nXrAU5tH7Fn8MOru6+fQsvMFCWEjxrOGkEyRZlLe+2Esn0W7hz/XDGtBlZkHc\nVeMtLzrNEVaHJXhYtmJKfTFSooqFA/fiI3xxL3wMN6jtCZp+/3i0IgWYfVkl\nvS2677rKblUxsdLNTD/Pj1O8jQD7J9jpRunW1a/LfuxUlMDF12Vm2x3M1BKu\nxIVZW88QYypUyc9+VpQsoxMfdDjTehueUx7TSBV1UjwVF+udqIousa5qCfmX\nJ9meEscWWaqoOMT+QntqneIgIdqRp+Gey8oHu4k+HA9alD8FAUwHwIaqy7KL\n+l+NaZpGlp1GLes71ymW5948VZnqbgtOzBNMRTzHUHK+xpbyhF81rs/z2oPg\ncTmBljfDZ4lzKukQwLM/YPoT7pxIUdwKRI0G6X4nBhTiKp+d5GPdvC8yShYi\nrJo1OmQmcuIQnz5ifRW/Cv/F6eh6aM0F536DeN9q/k1GvKEMx+XT/fxltbK6\n9CKkkxqoWPFyus0q6mzmljBtOodKeANYGSJ/ldv3UvQm90mOtJ27k7qd1ddR\nZuwB8xZB9ZYP5cvis+SF559Yr31FyVbcCMk3FmpzTcRtw/ws7vuVKQxZTpep\nCRt4uzb9hr1flwpyBSbpgb30TttQ0NQYj8+iKhnov9Xjay4iavfCyVDfNMrY\nW/wE\r\n=FiBO\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"github:3box/3box-orbitdb-plugins#feat/orbit-23","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.2-beta.4_1580732791288_0.7572371368666269","host":"s3://npm-registry-packages"}},"1.16.2":{"name":"3box","version":"1.16.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"8107ae1cb0bc45b5a191e5fce5d67c86179c91b8","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.2.tgz","fileCount":72,"integrity":"sha512-I7LkFDJBuR59C61hNSJGWg7tGFfgCWDsSj5X934Tz+w1n3WaGu/nsp2GXUdZSUOFio2kEYxq1nYVwpH7mOwF/Q==","signatures":[{"sig":"MEUCIAVzuurL8NAm0yqYYQZ3TMrc8y/okRiwL0uDSpQ5mO6DAiEAxtQ41rpZ+UgCRI1X0VdMZyN/Z0wHLyt9JCV1A/K6zGI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14777451,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeOwYkCRA9TVsSAnZWagAAjkoP/illeq4NdV+9kOs4skga\ngRBdiVwfaPM8T5fyhZl+ScrpURBYSbre1VnhAkUf8xp8iolzher8WaLq4+DX\nVKexdakv5BJLnHZR1Sm2luuF9vP7gOhHoWMab2pu9tJY/HslIjWltOfQgfgL\nMkvxMw6pqV6h7FBDWWmFSzUEetFFaA/698WSMaKZTovuvPh3iDJ5ZgfrjW0X\nLhNuZyzRXZWeZqo+eJmfVhsZe+htZlYo1/NA3vT2njIrOYNvkPieues8OLed\nu7fVNmMXj0R9ECxR5COVuinxccHmid5EcKCz/dR13RhHlo3O5nN519yrUg5N\nW7EHKYsA+gQuPsCLsDG7rUcrovkoZ5JlL8aafYM2fBvkkiAoSRIBnE3/61QO\n8wcxKF2daM9l4+rosFBfzmnAmF5FqC1yI8LRrt8yifpR8ylioWVTsW11EnJy\n+ftYtcdvM8mU+V+PUDXvkWfEnA2XYJML7XRhOz1kwVVF4jxdTF7FeBil5NgJ\nsYHuqH5jxbxJSaQaWRUr2YAHBWJ7TT0n0T/63Lj3CPXLZ2RpLvGCc24SrjIv\nwx79b1bcEb3c96LQql2+G6/jmm+ymrUlo3DyKG/En2jNjNNtqmwyJutdJmUo\nLWWiAAc1Zmlhk71YmAle72iZeRFYEZ1I5AF7NHbzpBhv3jql2VASnIMlIAW6\nM9kL\r\n=TPIm\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"github:3box/3box-orbitdb-plugins#feat/orbit-23","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.2_1580926499226_0.8509114004022871","host":"s3://npm-registry-packages"}},"1.16.3-beta.1":{"name":"3box","version":"1.16.3-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.3-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"49695effb82ddb38fb03e1f834966cbbb103e16a","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.3-beta.1.tgz","fileCount":72,"integrity":"sha512-yKCrsUUzFjf6E7p2ZubDmrlw6oZbr7mmZq0FepXzY98IyI27vo1G8/uA7ZSuChwq6YrzAZQm2aH3OIkoH817mg==","signatures":[{"sig":"MEUCIQDuwliq7Pv+2WnzNkwUOiWAn0Gr1a02p7L1cuqX4QLK6wIgWlL1myQEXPUuxkyyyAEBxp8CBxjjunA2krqP9Oy7ymo=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14782312,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeRce+CRA9TVsSAnZWagAA5DkP/1o4HxcPsYrMglTGZVhg\n348gqYb5D5LGSmSo3BMYvXnIAh8WktD3fS+RmbJwJvxSzpYCSgt+DispL2VC\ntEwLMYa0BOB/vfVfpU7PtJbFJLsB2mRBKZ1RQMx+QvBPKlUEu5i/YxZcx/nf\n5NTSeW9/ksZwplVfe3xjUu9Le+iG2m3m1qRaxni5zVrrlkdZEgY6ab6cZrfz\nBxW5qSJOdcIGK8kJnwf2P7z/5J7t2VeautTwGYRx+oV+E7mqphG85FLCsQaj\n4Qjp2eKxtXrTfuHsll2mF64rTjUC8whCZFiR8WbWjQca1DtRTdWYjUZ/157/\n4W5ebk9dxdL/QPfSFyN7gO82Cb4wbi17pIJvHRjqcV+c67ffS5aTVNvf+D3b\noQ35kJsD4nVPny+RsnltL5Roes5Rt2S77zOYeGCIm1JpaVwgVNZUkbnVeAIk\nH5TFOHUDJy9ApmqyZcrG7MXq7SbQPWUjBvKYZyH3v68GhP3J0dUol8u0rr6H\n0f55b/UJLxqV8u3Doj6U1B7aSfWXQ+UXNwds85YTzgxQsUx/6x1xqPRq8sSF\nZw1h7Dt8pIJDmF68Eqr+WOa4kqq/9QOYPU67lw8+ULBRpiRyIPqP6T01c9fx\nXW6rQuvVnkd4FYmE2XNZNdcdm/unD5beKRV0s6LlhdQA2Ac8+zhjbwvbr4J7\nI825\r\n=HRtO\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, in the same space, and same moderation configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Thread\nYou can get all posts made in a thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality.\n\n#### Interacting with a Thread\n\n##### 1. Joining a thread\nTo post in a thread, a user must first join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nLastly a thread can be joined by its address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\n##### 2. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 3. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 4. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 5. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.13.4","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.18.1","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"github:3box/3box-orbitdb-plugins#feat/orbit-23","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.3-beta.1_1581631421782_0.7300819021880229","host":"s3://npm-registry-packages"}},"1.16.3":{"name":"3box","version":"1.16.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.16.3","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"8ac8c1627dc1664bb18df8841b01f9ee5b93f5ee","tarball":"https://registry.npmjs.org/3box/-/3box-1.16.3.tgz","fileCount":72,"integrity":"sha512-NfwET0uiqvNU09KUEmZWGLUi5fnJ069CkMtJjjGsM8wB6USayyA3DfHV0x/10OFrtqfrysU9UYA/zzsnkp6pWQ==","signatures":[{"sig":"MEUCIAMrQ3R0r66uG3oDEk/llVV0AUBlFPa9lHm8Cne/QFDHAiEAneHH3gM1qK51kqV3za8c5rRPsaE2fULRUwr4F9XOYV8=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14778951,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeRd3cCRA9TVsSAnZWagAAbBIP/jNrWIIL4JZm6vfLH9ZN\nBTzPuyGjEtLfos6w8ZH1fTawqb+m2/OrXy5EZn48E5VEfbIjGNPu8B/RpnVo\nwxFAdyz2EsQny+Tdstf7tUovlYwgeWGO7umY9a89G/XuAMHUkMUp+7vbxhjt\n42wUZXSZujbw4KRPz/7Bw2cIBkRxuVW3g0uDmqUX5K8phDHSMoj8pOUoTYru\nRNNK52E0yI4+bv4rJSgC/xG9smZiy4Wvg+CNyjdF/HQd3/yIlitlUZjleyeX\ncyVpexl/COG1yoxaNv51mnf4qzKN42/lFmMR22Rl69r9m7uX3aBKsweWJVGT\nXxIJ8+Pqo0DxmY9rsQZx+pWXcv4EM9Pwyu3xsBnAwQ/9Q53S3lssC//hzt4O\n4VUvxiwawQX2ducbzhYtqOc7q36kZgv9bdRFzzsU8jzyeEjymkpEfxhcAQLV\npDMADU0f6qH+pNai7odQBxm3TsRB+4daErycj4GU5Y+sD396KaKG2KWBVlvf\nhtGpUYtOlQCW8UxPNsQHC9khtzyFmDadOH42BFQ6YN4CYZgTpT89ZZdV00h+\nQS3KOFiPkoZ/dU6pj12soukmM7qVppLh212nXaUzD/PL9PEZ8/faW45TjhZS\nM0uoF1vI/VvdAMd6wy5Q/hP5JYPwwomqOD2TUa2oX9qqYAdS0LI3wCE58TBK\nmoBX\r\n=F67s\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.13.4","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.18.1","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"github:3box/3box-orbitdb-plugins#feat/orbit-23","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.16.3_1581637083159_0.5004085345875766","host":"s3://npm-registry-packages"}},"1.17.0":{"name":"3box","version":"1.17.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.17.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"a9a39e8de8c0841725e3173033698c882a5a2b24","tarball":"https://registry.npmjs.org/3box/-/3box-1.17.0.tgz","fileCount":75,"integrity":"sha512-rPTAtqiMrVhjFz1S+LUjUFmxZ70wm3Pd/IAf/BQlTvdxM7Du/3ui7VjhR673oMgR4W3CTJ/VbAli1BgaSQF6EQ==","signatures":[{"sig":"MEYCIQD12CsTcUStvCZHg5VayJMhI1vkkT/YW5XtyC9vluhbXwIhAJZ2fHit0mDmpQAjovWFwh9OxRC5BmgPjt53i+k2AJtn","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14843152,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeRfmMCRA9TVsSAnZWagAApacP/jAwih/Pq+ShkSqk8Dcl\nKxtJ/05UMfhNyKsxoycYiX8hgkm3y7i37FsHFL+Yt4ldCmjlszaddHcqBStk\n4sxmq+IWFQrkOZ6XQQD+7+uHmSSBqFMIPE3wupx1n0VMFxrEEMXzAMi01R36\nrb6jLXPsYAozuQ2Ob9cEQJOswOguiz3rcEuhKRxRrcsoC5RsTff0Ix6y8Faa\n3V95r1TBv9vIJbyMslmq3xdYlWk3dOiTHMqZH+cjnOryo0H0qzASRarmxhr0\nI33drV4JYk9cmU96crbKY+3W/30H1QuZb4BrBJYxQiPg6W6VQ0uWo+bXclLK\nMydTWC7z8nOH/K+uX9sRWEPrxPnGpepiBYnZ8rmVkekUYUmScnYFePC9nBJl\nUTTZqKkiMBXuNuXf2AssnlVDAip+znarb6XD/rDWGcUU8ZesutBOAPaKMrmI\nsWtq9DvydkBSTzWEKM9jYibHu4N5B+yAk16ZR/NaB12n0JlgpQqX5OraiOic\nhEDRwFoB2RFVsOI4cJx5HTjebfuUhX108/GceNKe//Wu8zuff9p/4j1dkjlO\nZ7CnXQxCr8Um4JKTZt3RCDyvpEgJsQPUZdtFjspluMTEC/jF40Y5FYbfeghF\njbFVhWhbXpriMNofViFhN/2pBVecoAK0a+1yoO7Dp6p596W7KA0SR0Brz95K\notO3\r\n=Kxoi\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.13.4","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.18.1","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.1.0","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.17.0_1581644171325_0.4971496974025087","host":"s3://npm-registry-packages"}},"1.17.1":{"name":"3box","version":"1.17.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.17.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"7060f4b81eeccb7c7308125af343f25a55df79ee","tarball":"https://registry.npmjs.org/3box/-/3box-1.17.1.tgz","fileCount":75,"integrity":"sha512-QDhW0V14P7auvCx+2WlPPJ6B/qji4PiVxVyVtr9sT4aRMx1AYVnCqik3u3uiVPFTTWj09eBXsE8NK+M4pCGfsQ==","signatures":[{"sig":"MEUCIBlk6Eqwx54OmOyr4kUDSNFyLyZD0RPQqRY2Dt04JeVNAiEA/3dxa73kYix6zdD9xSet+YzZAzVPow0oceisHKZ1t4s=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14843237,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeTrZqCRA9TVsSAnZWagAALLwQAKPTJQp4wkU8z8pkvSog\nuzZLsJd/LlrdN+VL30MSs7k7swvSHcbZVzfdsvRtNoC1r8PAOFVmMjzHHcPj\nDZCGZIcqYwe47AkqkaWwZQuiZWGuP0GP3byc3l7pq00dsO+FINh3GY4ST6lq\nzbMZw/5/xO8HR2MhTRWYSBZ3GVfse9vcL3QdmMQMwsQj3FVYGJlteS2VaBD5\nUQGfUjNC/pLlPt4p72sGKxo7LYoRaXlWSKH4BN/L2Twj2CVLfRdwHLFoQjmJ\nDRZ/iS8dNo2Ao1ovt3RDV377kU1/ogvIR3WbMLZKz0jAGSJIFTEDr9IpV5un\nbNo8B3Oiq3DVYTcYedG83yQANJeQpFAPxFXNnroQZ1yLPl5S1zBs3O0MSaC6\nQwUHVt7rr4WK0YpLxeiqSDRs4WIETlIM3HdKFo/l8PybF5XBJ2wKLnSUvQQG\nbZpx2MIgBcV2AEDR5ZATaNaK5s5uCW4fuEHcHdS+neUGmdAG90UhfVs5l85m\nydxWezAZqHFhmxdHBMNildHxah32I/AfAtRoKpN4Zyd+KBtSoxkRiYMl1Qmg\nfXLk+XDZ9CiAuWDZTgNc/DeImOfDAZ45M59/bi6v95/LCxwDsGqRnbxRe41E\nU4s8mb4WZEtN4DAOyjTNSu5CS/UgnXA7K1pCLkZkcd8i5OVwzwC4hJtfWS/T\n3pOg\r\n=RzLT\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.1.0","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.17.1_1582216809463_0.8114184255125039","host":"s3://npm-registry-packages"}},"1.17.2-beta.1":{"name":"3box","version":"1.17.2-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.17.2-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"ef10635cfdcb78274e383e79b6ee6a6b8e5effe5","tarball":"https://registry.npmjs.org/3box/-/3box-1.17.2-beta.1.tgz","fileCount":75,"integrity":"sha512-CX7JHiOr/V3duf7C70vGZOMKVDm3w1uBCSiC5bdkgL3Y48mLUU32Llq4ZrnzJufBME0eTf4QRuox39St+xPs5w==","signatures":[{"sig":"MEUCIQDy3Q8eU1XPuI17lIyt1G0iqiZZ3UNziJJvrk3vXgCd0wIgOCNV+ItLNL4XEZIYFkr75ZLlkvTB/zQ9e0WJWOHfSyM=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14843984,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeXlVmCRA9TVsSAnZWagAAlbMP/0OUoW6UO2b5bAIofREd\nrvyN2+KqOmXBW2x9JtNLhEl9/54ej6ux+NVffoZ18fqttSVJ5+0UIr4sJt8b\nByhqZGK3RRfEzb4NtNBc+JY9IwsfwjpbHyQN+mqL0wZSy7i1vbC7+A4RThCt\n30zncQY/TXapd+a2Sj+6mk+99BaMxb7tPtsPuOWB1JkMxx3BLcBdIt+dNO46\nbc6vu3FTFyc5BSPwNH9p4IZVPT5yVZvZkIDMRkO9z039yEdZdIPxFi9cBGeD\n43V4U9N1LqdTzvSajdNDFgCKE0dhyA2asq9jXkwvVv3SNwyhpE38pOASuCrg\nt61oL/ZrR3jS0v+SkUBVQMR9xAX9bXUbJWD0Jus4AB/CmVsshFmjamAwggrQ\nuUuRqoBBKA7f9vmdXKNRH6hrBzW3ziCotBJOO8AyFPBreD0xBVICQzPLmTSz\nRVPm6RB8uURA++DHGFuXe/GfdF1r/A5WSbc7ik32R21ApluhlrsxFXHBd8zJ\nGtNji+y1TDiDHopM3+1TSZXqgfXfjk0XKA3lsGRTm7NAHgC4SU3LpCzNP5NL\nbZPh9wx/7NqvE++NoBkDNCUzCUNlSLZlm7vu4hKT28HogDTdumZxAkkfZ1Jc\n12ZA11juBenN7XbVdhcR+N7qG4BHlEd15yGWOdkRHxdI6Y63Dskl3NKHaDww\n2JRZ\r\n=9Wtw\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.1.0","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.17.2-beta.1_1583240549479_0.380743460487196","host":"s3://npm-registry-packages"}},"1.17.2-beta.2":{"name":"3box","version":"1.17.2-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.17.2-beta.2","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"539073e3e50d0a6ac7af9ded4a3df50a6ca2182b","tarball":"https://registry.npmjs.org/3box/-/3box-1.17.2-beta.2.tgz","fileCount":75,"integrity":"sha512-GsueXhNQZgO5uHK434W0jHxFiGDvuoKT9ZVOzBzZB2MXNyAY5vVXzEKEUVAF96kvYFGSUJFkpFUUkjqHi5ua/A==","signatures":[{"sig":"MEUCIQD+N0WbrO6z4KZt8Z3jhysqE1MHZtD9jOjCXhRLzxlGQAIgK+ZKBSJCbzwlS30qWfpZYfh2VwsIMe0k4CdgtvD86e0=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14844112,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeXlYYCRA9TVsSAnZWagAAn9gP/0Hi9qG6gbETFXALB69T\nbgQ6NBCUGyAXK0NK2NsU83P6KlU93kZtIhK1Sb9hOpBa1DgCxwvhYVPl9Boo\nKCNLeSkG3eQ0sTuDRf+L1rKv6Vfll41X8jQrrovnwcSMG/HuXTE54gvMOVIL\nYvODhfrc/3Gbt/imlbXW3WeE139VRhPj+9hdOgDMTwiAdgAq9z1Vr7REz8Jp\n63MrqKS5fwB5s7HhjF5sN3sQsMl7VFFMoLm7/QIa+hOersYOrib6ZzV6qDTG\nC5g0XEfzUCgH+/Olj3u1ixdSgpV2sbi2GUwrS3cXpU5o/Ew5ZEvBSgXgrJW5\nIq3DpkX2xFNFCRzk1by7agObJR1h/IytvRSkyMSc72LYbZUztu22IiY2mEB1\nX3ehhJbU1vPukM4IWfwD5TwDh/2mOynvTTcgmrEbty2qh551MST2f7p2sF+h\n6lQtjat1Ogbn6ABOmjl8XWIUxFnE6PwFNtnKwL1KbPb8D0aV57kBuylRt2ym\nPWozYlIjx9hrZ1fg5ie+JosNnvDW1CkdFm1tdlp/WD/ztZZ0LBC2ky0y+lCe\nikA/Quh/QQDxq4l892lKLAjSuIiAPxRyqNXAkjr4X7ej6LnMbr0Dj/1gdEU6\n8z7aMsXz4du3TXzF2M2luI4SpnuZn6P6WUkA9zYOlWJkkxYUYd+28fD6h314\nh8ie\r\n=K3c7\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.16.3","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.4","orbit-db":"^0.23.1","ipfs-mini":"^1.1.5","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.1.0","3id-blockchain-utils":"^0.3.2","@ethersproject/hdnode":"^5.0.0-beta.133","@ethersproject/wallet":"^5.0.0-beta.133","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.0","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.17.2-beta.2_1583240727507_0.37917913139381687","host":"s3://npm-registry-packages"}},"1.18.0-beta.1":{"name":"3box","version":"1.18.0-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.18.0-beta.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"d01534d9460b225a7ab359dbf0d3b2d4b641e0f7","tarball":"https://registry.npmjs.org/3box/-/3box-1.18.0-beta.1.tgz","fileCount":76,"integrity":"sha512-vvPP2rsJ4rLFUbmkx8V7cS6vkwzqB76GDpaamftxb7/Wi9rjXdWRDdQQcq79RdL/ZVdep5grOnaJAKe7qVOcRw==","signatures":[{"sig":"MEQCIH8oG9yNNvQHJVYvpTFnc4ZyhWrmojoefxRbIatRDuf0AiAdYk7/zlBy4wcymn8KcQycJvExSrM59EIP0mi/w1njeA==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":14854791,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeleIgCRA9TVsSAnZWagAAEVoP/AtppfBqXP0UASeZYbyZ\ncAQDqn+22c0478NNO8aXxIh46n7rFMKrIiSfXCuEP8ZEFhniTulZvEkq7uk0\nKLI24yPWsofAt247MNEMnCgUrF2J19aXco3Dev6O5NcgOoxjIr6ot3GJ27UH\njM9OcEs1tETdpC0Qf3Ijf3fZ3p/tpbW/9gGozu51lb4U4pDt2VfKWr7vr/3C\nYBAjjiYH9zZ6EJGnerxDCuXPS6+c1KhPkFnujck9mLYBW6B9Fx/7to5sZRMT\nfcvP3/FQGZ2YNs/U/85YeD54uMizVb71SIf2RxEWLl3gp373skCBBvRsbpum\nkbUbv6KZ0xQ6KSBKrbH1txsuiL/i3TbC/T3wq5vFkhS5ao818LcBGeBNQG+x\nsiuECT5XNuX+bf7gVMa1WXr1PZ7h+2O6mNOaKRbL+ZNs8iW/1dJwmGl0ktkS\nV30+1993JVe1a7cxuKTkbcAFt06uilfr/cCZtvwRBFUGJzomi4okeCHgDK0w\n/JWs4Vw3cRWipxYI4ZIX/Rp/+ssf9+ZI8s26EFWQ57xdJlAVVnYbnmCIVHnP\noZiHCnFQvyIB/JbwRJ6NUDoFE+Hhc2SyQAgFzrPJs0wWLSeeSIPUz42frmQ6\nxOqQwBaai+07hxTCFWBzJIRq8QsevLc+lw/N7B0eM5m1B8E8FS0qNQBKrmMw\n/8LX\r\n=Hnfl\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)).\n```js\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.5","orbit-db":"^0.23.1","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"github:3box/3id-connect#develop","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.1.0","3id-blockchain-utils":"^0.3.3","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.18.0-beta.1_1586881056143_0.5463884966982795","host":"s3://npm-registry-packages"}},"1.18.0":{"name":"3box","version":"1.18.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.18.0","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"7ef4521f1cb9f5d97828fb098cf58846369b3f6b","tarball":"https://registry.npmjs.org/3box/-/3box-1.18.0.tgz","fileCount":76,"integrity":"sha512-GSclziSN7rr1zq9anwvzpBnS3hztxsghJg9cvj5GhrlyZS2F5YoNmPGIZhAgAGV+j6mdKQhXGGOcZMmc/Kr/xQ==","signatures":[{"sig":"MEYCIQDFRTGcwIgv6yZoX+s9GQ6XN1lXn0z859CsnyuwFNEQWQIhALHWWbSAoGCE+9YLXJkQO4Cg2+uwbjO/LBIeCINuYu7Y","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15327050,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJenvjYCRA9TVsSAnZWagAAyu4P+gKsv8rkLZaCfNeCc5Sg\nigHHUuiT/mLEfCUu3eZu5SaC2zIHhGwJYxvJ4f26UVAiTljA9wVGXb/T8y5w\nPZE1et4qsliY6dke3J8MZyz4e2eoECCTnRcreb0WGiOJm/FgwxTwIvy13MVv\nWnmHkEFaiKMo8gHremvJoB5bXhErG8DaOUevK2LKcVFkXVFwLe56Rop3uYJU\nH8kXB7MJhEt8Xox4U6cvGdLP7vUMHneq56/CVrXPW3/71gHlvuenrGxbiN5s\nanrXRc88pQsTpd7EmK/dEzlo8DrLbUwIYnf/Dcq7YCl5vBjOxhvylV6hgHaG\ngndurlt9P2/wFCtJw8lfheBuCtBl2m87i7qqiwfzVwmJz5erJ1IULSHpc5Gx\n1/Ra7MXNK8OS3qvwmY0z1DSpZ+9yBKLOlo3Y/PgKyBH6dR6fyPuzORu1nkU2\nutS0lzvV/Pl1NKr0gERpRuQFrmw7iz0I9Mrc2ZN+GYoFpjSlPNXYpwSrHMz5\nzVjo1TEORxUYbIw8Y2Wks2KyRAzBTqgTKRRdVrkcatbs6BAJljbjuIF/5d1o\nrwLEyX1XaPGuvYYYSSZu2IC4ve/IclM1cESZXUpC8jdRWhF67c6szfHKejIx\n3jY8j3c0uPni+72psNaoKoz14zYmIAZsET+dbQrzi+EWC/s7glwaGluQkIVg\n5f5O\r\n=ZFTc\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.5","orbit-db":"^0.23.1","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.0.1","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.1.0","3id-blockchain-utils":"^0.3.3","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.18.0_1587476695284_0.044216900694964645","host":"s3://npm-registry-packages"}},"1.18.1":{"name":"3box","version":"1.18.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.18.1","maintainers":[{"name":"ajunge","email":"ajunge@yaykuy.cl"},{"name":"castelo","email":"castillo85@gmail.com"},{"name":"oed","email":"oed3933@gmail.com"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"ed5c109af5e85bb5180a2942015075cafb8fbbd8","tarball":"https://registry.npmjs.org/3box/-/3box-1.18.1.tgz","fileCount":76,"integrity":"sha512-+6rngpKcarjuTlsQeAVC76lOUWf9d7LW1XJ0mFfkGCcq9ElcLW7DsPJFZBjTldTjafoMjv2Az4K+OHlZANSN/Q==","signatures":[{"sig":"MEQCICszR1glB4W784bqch8zPWw9Z/VpwUhGPFzf7PdLiC4mAiAY5QbAo0gK8pw8bXdsmV81yZITX63gmSBQsDSuMWQ/ug==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15327120,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJen2CBCRA9TVsSAnZWagAAMW0P/2gumH0bMUF0ddAFJWxg\nmL03ZPIUtIdpE6QY390KFQ++iSHLEmHUOYXqLm4SR4sSrSAosxjffGbOZJuo\nmGJhHs2otEXSJ/V2yCi9CHQ6SYRXJ6ZrXqFW3F7WW6cbsaYs3+X/rwrC5g5i\nAOLg4xc3lJymbVSYs74ZfxLG0+xxhPfYIw25Q1hqobrPEtrkTmsR6a0LKBj2\nUnzOaSGM2Kques3n1vNSjeJwa8T3Ov2QoQJ7UgeQzzkiMKW5uGXvNgfaL8vt\njRGqYZEclOBpaqMOJQyCpaAJyD9PW962cJ04n4DcAJeOQs6yfkISFUmYuATE\npaQsEizq2yBS2DXyEqn2I5KFExgnvSt5IcgEE7u9HkIn6rNQeJdNtln+unN9\n7rdxNmc8Xr4Pt7do1JXCYZ2LDiRJlgAaK/C4dbYImVfRyCiHO385ALHgtfLL\nJxaJGGPdaBMQDae1fgfvVu9DoIwSRNEYuNnpGLMAGw0GeWvEQYRRaf5Aqyc8\n7eVErBtKKwP3tadeZsMdnS8v1NJoRgCproaoVeQ6g5mjsDGdfpl3eFZJ7iZB\nH63XpcBL7ROiLyrPW9sz8Bfj+jMT/EkXOSuV6b0lTAb5Mub0MKacw6yFp0C0\nSEXP5v30t8ntpY2a2B+vT2gp59DBPwUv0HzDPJoeoxgkkNgR3GNJskttCOHs\n6KDi\r\n=JiMb\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^0.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.5","orbit-db":"^0.23.1","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.0.1","3id-resolver":"^0.0.5","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^0.1.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^0.3.0","3box-orbitdb-plugins":"^1.1.0","3id-blockchain-utils":"^0.3.3","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.18.1_1587503233179_0.7366570458565367","host":"s3://npm-registry-packages"}},"1.19.0-rc.1":{"name":"3box","version":"1.19.0-rc.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.19.0-rc.1","maintainers":[{"name":"msterle","email":"mike.sterle@gmail.com"},{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"f6f0f35d7abb12cf3e8340917c3f1b50d10a6664","tarball":"https://registry.npmjs.org/3box/-/3box-1.19.0-rc.1.tgz","fileCount":75,"integrity":"sha512-ruKTdsXndSk/RSVuBKett/nXU/tYEBpY4mnHkKs189KjmkIfMI50DaD2WSpVlnuUN5LiBArK17igDlMa7YUDWw==","signatures":[{"sig":"MEUCIC1EB+hNJjEEAojmYokaseOVETP/EVmm/z/RtuSVMMHNAiEA2wZXyy3cn+fC385KhrjERDYgL+sIm7lNYYV7T3vRU00=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":17422731,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeqp5ICRA9TVsSAnZWagAAalgP/Rz+KxXChnrH7rE9PBGO\nVWNszmBzCvO5glGAGRpSTkQ/7WJ2XnD3NRY+xEuMaLGhnqS1UKZEacp1yf+a\nrr8/gFMbjFUta+63v0oVV+AW0KHqjLAkqfcYuqpAlNqm8av3q/kDsKkG/w/y\nlx26taqK8sJirCWUPzOshsizU1eUze+E0KfjLYs5NMFhQpp8zdgPBah4//Po\nd36aiHQcko1mm2bCVuEwOpj3W8Uacvtfn5p511IUcA56viCbegH3463hnn5U\nSm+Ur5feKk0qi19gOf+vJlbj1O6g94t+B9ejTx7E2bkOFbImoTxgVHeH9R7e\nXuW3LXhuffvHrPGE+AEDDo+yUsZpqJWpemj8PYoY+PLirZyF30mUmi0hveWJ\nmLjedm54bJBqiNldXe7cgPQXiDb4l7TkZeWbmImVo4YFlyFMZYFgIpXNCNDp\nE6tkuOEWEI3irqIsMCHcmktffCdeCtcgVzbn7lxojs/RlWA2bglT0qXIHvMh\nyvms+cPebppqM+dmYZdnVKSkEdNxUYTRsI1O9lwc69yVVIChMko1R36uO1Dk\nCc2G1AI/anvTN/vJjfeptVxG8gVEpNCWEvow/TF8y8HNsqtWNusWwqdnZm9h\nRB7IKO6rzbierIPPvXVy0CrR3MUhntsdEL/zSFnKhOdKK6lM2U2FLnZSi3Od\n+nzc\r\n=jQiV\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). It is now suggested to use the 3ID Connect Provider, which is a 3ID provider that wraps available `ethereum providers` and will manage/permission 3ID keys, authentication and blockchain account links inside an iframe. This will become the default soon and will overide passed `ethereum providers`. You can get the 3ID Connect Provider as follows.\n\n```js\nconst provider = await Box.get3idConnectProvider()\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.get3idConnectProvider()](#Box.get3idConnectProvider) ⇒ <code>3IDProvider</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.get3idConnectProvider\"></a>\n\n#### Box.get3idConnectProvider() ⇒ <code>3IDProvider</code>\nReturns and 3ID Connect Provider to manage keys, authentication and account links. Becomes default in future.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>3IDProvider</code> - Promise that resolves to a 3ID Connect Provider  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"msterle","email":"mike.sterle@gmail.com"},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.11.3","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.17.0","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.5","orbit-db":"^0.23.1","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.0.1","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^1.0.1","3box-orbitdb-plugins":"^2.0.0","3id-blockchain-utils":"^0.3.3","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.19.0-rc.1_1588239944288_0.9679983179140925","host":"s3://npm-registry-packages"}},"1.19.0":{"name":"3box","version":"1.19.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.19.0","maintainers":[{"name":"msterle","email":"mike.sterle@gmail.com"},{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"6955177db2501dbc9d705c8fe627ef7dc4e1043b","tarball":"https://registry.npmjs.org/3box/-/3box-1.19.0.tgz","fileCount":75,"integrity":"sha512-A/Bk2IcPUCMypF6BGBEixwdMPm6IlbM+sW5tssZ541G45KFFMQU/wSMHUDCcv0GK+groGJW4hmOURmadnAYflg==","signatures":[{"sig":"MEYCIQCr8yAs/IuYc1nLMgnHKLIEGricUdtgrsfCn7daXHAruAIhAI3WrR8guJtrjGryYPi5AOvKLhd4mP2PsYNUD3TBazxZ","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15550424,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJeu6z7CRA9TVsSAnZWagAAxlgP/00g6rH9/O4/i8u3kJAi\nBjeaR0JKZGFqj6NRzn+xu+nIgxOAghQHPZYUXr7ml9MrpQhXMZpj01SFPzqX\nozkQcMbqsw6ks/x6pws5IXN6t5lCykmrBpNr/6UNUgzVT45xQrv1kOyeVZJX\nfYP/B4/UwCwYRr7vxT7I0fabWeCjHyKTRI6MPqUkbEBtn8lOoTLKbUc/9SHO\nZ6kecH/XAsFV4musVLykaXB4l2v1FcDpgY94WPV9ZfUkAIW6EtPPw87ExEue\n7cuQG9nvrIZIhF7OyjzxNanDq9qExWWYxnzdN7dYitNHEwufmoKDWfs2P8Mf\n5F9N0yO4v0EWq+RRx8MiU4zJhq8ukq41q9sGeP8tucZEKwVhlYyZhNg+gFx+\n+qpmH4MoJ0vTjAzZOfYSYXD2u2esHDRN4bRyDjNGu/S/R/z36eQzMV6yMOBC\n+jNs7QmGjGg8d9d2jr4VwzrKIQZQV6FbKJNql1Dh3op9wuUdmPN9e+68Fr2b\nWd1LGVcOVmbnLr/B2appB7QXfAFoZajWjXjAlcJRJwMhHoaFH1AmcZ/T/RrE\n9qM/3NTus7UMjH/D99AnZepAr0hTmhKpZlcAVZcgdUzL4+RB6N2LH6PtE6Lv\nZjkfsdpgNCE4e393gTpyqW4lhWX632t7gJpjD6USh5owEfSfrkMKqTN6QaI+\nxUpM\r\n=BzsS\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"msterle","email":"mike.sterle@gmail.com"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.12.0","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"12.13.0","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.5","orbit-db":"^0.23.1","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.0.2","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^1.0.1","3box-orbitdb-plugins":"^2.0.0","3id-blockchain-utils":"^0.3.3","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.19.0_1589357818753_0.4860040325456656","host":"s3://npm-registry-packages"}},"1.20.0-beta.0":{"name":"3box","version":"1.20.0-beta.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.0-beta.0","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"5fdad2512198cccab3f12d00b2520eb25bda9341","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.0-beta.0.tgz","fileCount":81,"integrity":"sha512-C6Dk9Yt3kYCegsW23VKzNrLwo8UenCRSDoETl/5C52IfHRnibK5G7Qt8YX31hL7gapN2h5cokR3G8r+LCBEjVw==","signatures":[{"sig":"MEYCIQDBeg5AH+6i30hBUD93DDT9bxpL/u5T19OGJuvzN1+XfAIhAL4++DC8ESztcapXK6JnzhoOFDQZJCVijnhs8S0iMxdN","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12343401,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe53OyCRA9TVsSAnZWagAAZCEP/R9L3nn1CvgzhoPTK0IH\neAFJ5M0P1Q/gxndJytnMYo3tRc2ky5PIbHUuKPSsGBgf5dLRzfFR6NcLHra5\noB5nvt3/UaSOMIxNECLj2IqdK3qJJSkgkFseTPUH0FFZ3vgh2t4zyqLofb2g\nKzkptONs8qYwMkjvBmv50e0cL1OJC78SCZBT3RHshrYSSL1C/xq0ghc2t9C0\nwmYMZGy6Q+seEoYJpr0c6q3hhVRbnAjInT5UEwepueOrGLPD/D4jrvkJOi14\nmHa0gFygAaROg120EXllufNj2/snrdiA0MR5xkBegOaiS1/faYd/SLsr7Dkc\nsFzZke9YGNrFwWQ7iz54Z7HTI9iVicH836k50v4KU4VHwJMkvorxV8t/uN0z\nZ3Ae3SW3L9Q8KtVj5OFJUh3tnyrzmKW6tFWwQwOF7/uhRwb+6xJTemRgBZaw\nDgUwfGKn2UBcaMi1khOa3N29b5AuXfGzy5na73wtmjE0tqsELXJfC/XoDkXY\nPJftA9z0KlFnzYHRSfakUZIZIs/CY9n6xrM8gObRfAYpIer26r840d3IDaHy\nnXj3/TzoP6cjnOcrRZZltRjAgmivkJrh11OHaT5X5Z95DH+Mfn7L4LpkChHX\necSmmaF94eUpiZoLULZmdhgcRb8Iy8GSOzF8tplnhmgrx54E9FKnjr78+M+N\nCjyA\r\n=Vphd\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. This is best to call on page load, so it can begin initializing and connecting services like IPFS in background.\n\n```js\nconst box = await Box.create()\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. A provider needs to be passed, this can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). If using an ethereum provider you need to pass an ethereum address to the `auth` method as well. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address, provider })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## Maintainers\n[@oed](https://github.com/oed)\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.supported()](#Box.supported) ⇒ <code>Boolean</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.provider | <code>String</code> | A 3ID provider, or ethereum provider |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.supportCheck | <code>String</code> | Gives browser alert if 3boxjs/ipfs not supported in browser env, defaults to true. You can also set to false to implement your own alert and call Box.support to check if supported. |\n\n<a name=\"Box.supported\"></a>\n\n#### Box.supported() ⇒ <code>Boolean</code>\nDetermines if this browser environment supports 3boxjs and ipfs.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"0.44.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^2.0.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.0-beta.0_1592226737587_0.3696428204138398","host":"s3://npm-registry-packages"}},"1.20.0":{"name":"3box","version":"1.20.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.0","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"b39052e347065512e987b38fa2276653a56f6742","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.0.tgz","fileCount":81,"integrity":"sha512-P2YN7y+rZXXXGw4VKZW9Y5YiPs7vRD4uYyd1tDyE6zFnY1oPWcZEx0A4tYJA2+qpywHstTVBFuNQcfg4HvH+sg==","signatures":[{"sig":"MEQCIFJ3tCMXU3ojq3yFx/FnpwsMGMdIK+tcw1Np1r/u1cIVAiA9dCkHMBnOUgoLCmkkL16SyWt/Qhc+kZhN+uHRC/nt/Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":12343377,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe6MocCRA9TVsSAnZWagAAG9IP+wSsGUoJ4KwafR6i6yBi\nOjuN1HcKqJVI092R6WOjNwLb5UEMkLKbdy0nTMUcSa8eTGFeQL+fEQwO3dMs\ngwXHs/6D0kLcya6Zy9zm6MeKBku5beGa3XVXTBMGGBYY0axGDf9YRSmwHxnu\nA4OqpDDNz+b+2TK+K4lcKw67udu6uktL1/GjscxUZWaAvHEN+9xi+FjbDrUA\nWZt1xrYvP++5/ChqQlOPTX+hbYWSwo8TeneLIIo26VzSkryXlgBSais860CG\n+BJEO3dnS+iHWgagKXFIRbRnMfIuDADGFYWxP/QMKOSvpwK804XKKrAu4fqQ\nfGyzZSmNKQuR6CzRM4/9AVAxgZI7Nti97WgW0U3l4oZtHN56ktBi7CYKY83k\nKLeJFyhhmWZDJ2YkOCa4eCVehRkKQPJ6cofuoxjCVtYmk2gw8GA4b9vfxink\nd4mk/icppFCAhwG/rDc69DoHcvdGSSgFMdnBJZ3T4PU2u92GoV7KyYVJ/z1+\nf0toSbea+nWLe8CVejENCuBvQcdRuKle9JMkguP+TBwbnoKbhwoJzuNS3Sxs\nCIg/BZy+mLi9a3J4RXIfN9BcNY190aC1+63tW0uMgkCmTJi/belbdDJpXOGD\nSj66maUpz4qrdye4ibFK+qs4rgK2xzVcAHccaXC6sqKOnSl6QWB+WbKOaAxx\n3O8s\r\n=FYfm\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"0.44.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^2.0.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","webrtcsupport":"^2.2.0","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.0_1592314396131_0.07315626982855927","host":"s3://npm-registry-packages"}},"1.20.1":{"name":"3box","version":"1.20.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.1","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"6bad15fdba67cf24ee4bb33cdac410432f4e0bad","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.1.tgz","fileCount":79,"integrity":"sha512-bV6w2iMBNC90fopu2kmdXb2fX/as50sFaLHH7LsXPVVxTl0fQiLayIAejFfXWvOk2bKlwVa0KfVISFGdCczRYg==","signatures":[{"sig":"MEQCIBFb8aRuvuTPeKLW37wZnxH6u/sNBIK21XVPg63T898ZAiAqVThXw6mO1sM1nw8CFx+gYalBttWApyXsvJjt/NIn2Q==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16395952,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe8k93CRA9TVsSAnZWagAAU1gP/1sOPd1Yjx+HNSpNZ87h\nmo/UZ/3G47IzFLdbpKoJXPSiZvEQD1AVDtGjYASx4Fjzz2doKsCRorz9uOqP\nC41KsUME63JStW2MEVg4lHQX61pcBSH4IEgVftXcOliwogFyZEJWY4oba3PY\nvC5aR63ric6dg+slB1OdnUrQFs5t/UzlK3yEjAMkAy31N2lbS6eAx99x3WIJ\nnA+v5vgSWR+iI7aZlHGh//YoId3m0ZBJq5L4Invq+iKgFjbQYpw1TgnB4GQf\nGhXdh7ns5zZRl73EH9p8HMJf0fzYfzuXeeeRozp3H3cuayVA3TZTFelYJ3Dc\nJldZwQsxmbooFbGoKqHifS48jRbhjP9OtdcbpUrvzbwY0rPb8EwiTXNO12hz\nPu48R661Z9U2hCHQ9NYXoYyuqb6kNxuSVvcUjCOZpP5qnewhZwP6IaUGdqt4\nNaBVro03A/GK1oWYEMV8Nas1O6gequ2BsvOAOBiNa5YDKYRvqClN/u9uBX2f\nygrpq9vE7tZVZu0poVHiITPrl+hd6e62UjocAX5+doJxFLPLEkmTEl0P3uiK\n9V9PfXP0xr/tuP1TVNZXE9bZAD5RCqeDFlwvaQrfd0OCnvmXaDd3cCebekG5\n2u9qh43r2epcyWXuSy3YM1smtl6f/a9RGRC6QrtFLE03SvPJeksRAQWNm2ro\nw/+P\r\n=8sxI\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"5e89a1970a34b4c94eeb57be14a8286e70a0cece","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"0.44.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^2.0.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.1_1592938358468_0.09667021182771207","host":"s3://npm-registry-packages"}},"1.20.2-beta.1":{"name":"3box","version":"1.20.2-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.2-beta.1","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"badb4765a1aa44c7990542803d68f0c2f3706315","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.2-beta.1.tgz","fileCount":78,"integrity":"sha512-8V7/Qxyo9VEkpZbdCAm9I3sCJKXsq67tKCFDSEY6cP4jajFAGqyv2keJ1MGz3UMbhrQn+j8f0OIl04LGzQKKCA==","signatures":[{"sig":"MEYCIQCYIjUsy+8vkC6faA/IxBnca3VOMfO9HEdoXC36eL+31QIhAMUjEOFhwGNn6AcVFbTW+G5Mi+q1CT29qCHSYrsdrtYP","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":13483498,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJe9G4iCRA9TVsSAnZWagAAHk8P/11iausavfFki9V+YsM0\nlH1dbFnhmay92tSqE0xexVxR+DqL7TExlBNaTuzUR6PLtsp1Z6+efC4saW4h\nQs/3p3NJdAMttJZdxDdfi5boTOHMJHM8XYhybMAjWhpLi7D/770rGRXZllws\nI6y1Bwzl/JDK6n0Ny5qMXXl2Ov/pSQmZ2YW4v7xKe5134kAP6U2Hxcu2wMH6\n7dWOoZiqNU+7jdQUNkuF+fhfiXoi4cqjYVFwbP3aqNmsTtXk4dwf+Mn93JkZ\n9ukBrl/4z3sle09/RYb+MJxANiRjYw7mEzHXdotWJudPpNg4DXorXGXewiB+\nfPpB6N5b8noRhpus7zJ8E9+wTkMzBLYcp0tGXlh158+xQkZcFFxdjvaSOlk4\nkrE2jlX+vwwish4zVxcJKQ2Vhedt88DnqslS/MdGrglMMM35CCiXAacqFw5h\navUQ/VzKa1L0mz/CsSWxAXQQUyD7YLWdxoBnTbNx0hfKsRuRd17K0IEV7PSj\nXGMbZcpwB3w/bkbMZD4QVVwdU7rf7DcNOnt8z751+vMJp6Du+NjMIAq4/yyy\nYS0PXk3ZtDizDmDEsORR79a5gYM9FV/m+EKdJnoG7NrmPwFdNJIkkr4Rf3N+\nXaoFH7K+SQhKN2UChb2HboIiuXH6qsdiHJeLkNgXn39cQXiuAgto42Hjx1If\nPD6z\r\n=TOv1\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. This is best to call on page load, so it can begin initializing and connecting services like IPFS in background.\n\n```js\nconst box = await Box.create()\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. A provider needs to be passed, this can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). If using an ethereum provider you need to pass an ethereum address to the `auth` method as well. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address, provider })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## Maintainers\n[@oed](https://github.com/oed)\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.supported()](#Box.supported) ⇒ <code>Boolean</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.provider | <code>String</code> | A 3ID provider, or ethereum provider |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.supportCheck | <code>String</code> | Gives browser alert if 3boxjs/ipfs not supported in browser env, defaults to true. You can also set to false to implement your own alert and call Box.support to check if supported. |\n\n<a name=\"Box.supported\"></a>\n\n#### Box.supported() ⇒ <code>Boolean</code>\nDetermines if this browser environment supports 3boxjs and ipfs.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"standard":{"ignore":["/src/modernizr.js"]},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.14.5","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"12.18.1","dependencies":{"ipfs":"0.44.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^2.0.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.2-beta.1_1593077281591_0.08066047581688007","host":"s3://npm-registry-packages"}},"1.20.2":{"name":"3box","version":"1.20.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.2","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"591e5384a8bdf19b28ef934ce75f911f1f34df0d","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.2.tgz","fileCount":79,"integrity":"sha512-/hCVU+XQlXyOFGmgdXKUh1c0y6jplSMFeyZcMg+Id3VNExKCgmkJyKuooyWXLyBBdgcB4ZJcS/1vwd5nua8pOQ==","signatures":[{"sig":"MEUCIQCwxpuQ0qwcZRDkAlu9qNYt5SytBR+65s+FZg1YdDhC2QIgH+vGdbeWP3JBdfnt5QzBTXRuLbImjseqwTGg8IswXQI=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16395922,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfB0sjCRA9TVsSAnZWagAAvOQQAJUctvIJz++bMTq5j+7q\nPzFhfVgzRVe4bX/7xSv5MgC6QeHjEDhE4LNF2DjPGs9KIis/261jFvPmVCBK\nUveuVzncRmY94CctnYPoMxQPDWr/K9Y79/oTQb/SRm/XdYiZnWTUgLVWkDFi\nlBtngaaHrIFXtdlCF7VoBk2Nh1DNziA5G/wcQwlo1Y91uEshtQtjfRR0rDsa\nMBXReoZogi0wTWcvD9dqNxGkjQYgId23jgCo6gJzASpb7ONktG0Ol/JzaiXD\niJSWWSkk0ujoc026HUe22awz7Ba9ctoE5E44zE9VyTSUalDwF2QA9yNmuZTo\nI6PmJCa3PQwHlvllyD2EeGHMyk6Q51aplnqG4gbUQduQ1PflbhttXFARC986\nhgaFryBiyka1env9gTGD4b14UBYve1mLytn5ol3PEWSUPVuNnzF54szlkoI2\nTG3jcJu5Txx1TOzN47SjhkcOmOSXFtpTJhX/o7rALmtofTJDl2dFo8oVxWEq\nU+XCE4jEOIOwwZyapKxBeBsIDEOEm6zwvOxwLGnR9jUNUHp0NTM0yvC3S1Lf\nzkWSTEKK1N0yQhHrnWTA9nBHiM+1NcBtXny85R4e4woiBmc1jdmtLlg5oB/4\n5N8vRJVZevvIjmKcLTXMHll0qQV1x3wYmgpo4SkEPIqsrwifS6R2DUvH0xx9\nlD9A\r\n=A6Pq\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"b50c8e4b9f4cdf1e401e0c10f4a0e0106bc2e73c","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"0.44.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^2.0.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.2_1594313506549_0.46949754611939754","host":"s3://npm-registry-packages"}},"1.20.3":{"name":"3box","version":"1.20.3","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.3","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"9e29329ab2e25a718723570f585b40525c2239e5","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.3.tgz","fileCount":79,"integrity":"sha512-aa8cJT4F/x75JL0prcFtdbhtaLslwzb8riqFXDHVitKeVXCsES9KSwyXkP9oo5wi93ACryhmwN1gkLzZ8FuCNg==","signatures":[{"sig":"MEUCIF3uFCZNfEk5+U55whHqzQkByzsSL+IcekfxmfBxGkC8AiEAoW6adeXxnM7YeAhb3a5yiP/srgFrPlB3kwMVMFSiTbc=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16068551,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfDM9kCRA9TVsSAnZWagAAb9cP/1yF/dB3aDARpknGwqfV\nGLlYiShv6w1MeSkXN6NjSQj/cw5FOldv+vEsVPPc6tGHVWRtC31QuKQQPDRT\nQ0zC1eGnXy4++KXTc6GzVfbQjWghM7MAYu6lPbHD5zr1xs45LmWXBZZvwg1R\nkhhB00J5NEl6rCxR7kHdZn0koxeYA8pTQPOZ/MmdjkYPyk25S1/apwWNRxg0\nqwfWovlag/3J/X5Iv+kMkVulg5QcwhLcJoVFwXPcAgYfbPXbP3MUFGJH5fvC\nkJqYpU3/C+E6/rf52Lwz52T6gI0bmkHwOQSKvX7NQTbDEkvCAff6Jz95IfT4\nmXkxI9fcmg/AvvNM2OYrge/AopP5YN246dk8vuQaCO5gUFAsUV4h66IhwVs1\nMZ5BExR6f/vJs+7net3wwrj1AR2yS3BHvDgf/hb33vij+XsgpFNDEIgOJfix\nNQMCG/XV7gyqtVldGb6S9wj+Oa5f9ovd3LZ6QnfyvWw0litfm9Jbi+kkBAlr\nXnmeexLlE66zKAhmJFD0LQ+w/12houq/T4+mSdEc5RZo7jsDy77N/PN3Bf4t\njQBaRksV0QK7mUOziZ2gZD/DtwiNd15GkkLdBzmBjvHpayDL4M7n963lx6JO\nCeX8GRexMGT5CZnmZL2dKfeCb2niH5kpDE8P8jTgi1x1XLMQDO5Y+8Hu1uPU\n1xL4\r\n=J4mg\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"4ba3c3be96178823f074254f9650841623fe0f61","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.3_1594675043494_0.7965646228115606","host":"s3://npm-registry-packages"}},"1.20.4-beta.1":{"name":"3box","version":"1.20.4-beta.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.4-beta.1","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"4dd2650d37b35111330c2d42a97a262598c69385","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.4-beta.1.tgz","fileCount":79,"integrity":"sha512-pOAZGVWNEmWwIS/EfLArnHnjVQJUGHSI3/7Rs+QnTqTjcYnYnDANbthimC+bGLOvSTTX0e/KVpG2NAL9woDYXg==","signatures":[{"sig":"MEQCIBxQInr1PzRps1vFZc6AdwC/W2J44hgkGiKu2yfU60rnAiAAtWAsJSm/O17wShOoL+wese43OBgtxxXvzu8qCV7f7w==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16069723,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfD12dCRA9TVsSAnZWagAA40wQAJc/0MONud0NghHqeQmn\nTYXfwJg3tbYAh58V6K2pxf2Ws3V+wAuU/TfqXXOQzKcdMWv6ihofexb7LndJ\nPIXlZ2nqzR64vvAnKEUG11V/sTBJaBVfZPrsixlH97hWjc/cySkHYuNOjMLz\nM7O5UeNfpOB5O4nbIvKVcdUcDpYQ3/hxF4ESqTO1lAqIpaszsKmjkTH9Yuan\nMtciBeqBgg1Q5E91hjxZQz/59xEnCdGSnxGh70WLEM2N2LCPfsOqvFosc+2H\nHDUP7XeWua7pTWtasil66fzC8+WkjYHliWmqDppj9yQsVMEfPMDpgM4r12XG\nW0JXOcnitkXVlWVvUfuAjU+13KrdHLTJllN1Vc6D0dia4BPoLIq+ro2ATz/C\niuCWJZrVy3ARSGdVvd7YRMZg16Yd3DzBnvlKivC7uVUtHiBUgKX5fqn6AFPW\nBJkq+yDFt5ilOXLqfzAY8B5jgDQy88J5Iz4/ymqbB7EBi6wVuEnY32UuByV+\nkjo5Mx+x8LbJTorsPX6VDVD8Ho/pYJQ91EeYEvIfn8liYP3BnYb+nQjPINIf\nQZvj1UZ5Rb4N87WlmMNdwBewQV38ajEiuVFJduAECF/00UgZrQrvf3JaGAd9\ni0Hlnin5WEel34wl3ppCbu+MGx8S6sdtS3XVfIdNVDvkjUw0CK4sNPitNULk\ngOs1\r\n=Lp9N\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. This is best to call on page load, so it can begin initializing and connecting services like IPFS in background.\n\n```js\nconst box = await Box.create()\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. A provider needs to be passed, this can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). If using an ethereum provider you need to pass an ethereum address to the `auth` method as well. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address, provider })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## Maintainers\n[@oed](https://github.com/oed)\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.supported()](#Box.supported) ⇒ <code>Boolean</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.provider | <code>String</code> | A 3ID provider, or ethereum provider |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.supportCheck | <code>String</code> | Gives browser alert if 3boxjs/ipfs not supported in browser env, defaults to true. You can also set to false to implement your own alert and call Box.support to check if supported. |\n\n<a name=\"Box.supported\"></a>\n\n#### Box.supported() ⇒ <code>Boolean</code>\nDetermines if this browser environment supports 3boxjs and ipfs.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.accessTimeout | <code>Number</code> | number of ms to load access control, until timeout and return |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.accessTimeout | <code>Number</code> | number of ms to load access control, until timeout and return |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"gitHead":"adb23b5e2ab1f0ab5cb4f9bfe71509d501b475c0","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.4-beta.1_1594842525228_0.574182462803924","host":"s3://npm-registry-packages"}},"1.20.4-beta.2":{"name":"3box","version":"1.20.4-beta.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.20.4-beta.2","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"54f0d9bdaa0d6eaee6bfb96d3f885625aa42c296","tarball":"https://registry.npmjs.org/3box/-/3box-1.20.4-beta.2.tgz","fileCount":78,"integrity":"sha512-018emkPEkukYt54FUGPisqcQ7gVqmGweGJoGYIVHDgHxAhbU8Yfi6TgzBSBh0vAFOOcMQw5hszDo5LutuiWAtA==","signatures":[{"sig":"MEYCIQCsSvQc5x1er60PaP174LF5SQJkxgP3TrYNQKzaEZrJSgIhAI/JK+bEbaHcxfVcctDl8f8e+0So8ejL9llKEPH0t6kk","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":13155962,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfFVUICRA9TVsSAnZWagAAiAgQAIiOmI8liU5szCFeVGSu\nqyyo1kklvAfjXl2JmxtmAahrHdzRjyCOceBQtg+JRzDAhlOJ80AJceCqtsn/\nJSNBngdG0r4377bgYa6Wh6J6PJOiSMgZPoY8GqVlo//4nP56HADE1ZdlqdHZ\n9YyLJSmmWd+9OOlLH02VZlaQMh9JPt022kN9Tmyp+cURyhrVdmUo+P2Dykvi\nh7PT65XCZsjUF6DJ2tQOBoSnpdXadwuGuapaoMTrJvCO9hpbdgR+JAf8lanq\n0OCwKV4wx5fIQJiaKpCKBqO6B92pDW9rqkRnaQOW/E+N5hmaUjEBSn5R2j1k\nqZVHe2Qe8RNtJXUcUlvZwre8Pa6we30N5nxuPsKWElRZDzLbWRmdPA9xc8ld\nXjitql+V68Cnu3guRvuijVp+SjSriYcH+3hiOI3lZElSqtIQWN6V6FkKPPAn\nAxeNxcluXfs/X8IiTh0Jsq7Nz8koXK5kWtUfEiMrGd2EmsAtGZNhsCFAuHT1\nz/78vZI7EH9jgd1O0ZZAdKWD7ocsvvTEohq2FCxP0OCg2lYjRKLZwbL9DZab\nN9gXGL6pavzz23/B3IM9MTY7Yclr0UlEfGh5EIZ5rvRieAIJe/MoQ2Aji6ab\nb+ZQzIOf17P6hzniuWrSSBeltQHQ59sKAMdOMuQDXHzaTDO4y1khh4oGQe6e\nEfNK\r\n=Ck2K\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. This is best to call on page load, so it can begin initializing and connecting services like IPFS in background.\n\n```js\nconst box = await Box.create()\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. A provider needs to be passed, this can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). If using an ethereum provider you need to pass an ethereum address to the `auth` method as well. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address, provider })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## Maintainers\n[@oed](https://github.com/oed)\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.supported()](#Box.supported) ⇒ <code>Boolean</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.provider | <code>String</code> | A 3ID provider, or ethereum provider |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.supportCheck | <code>String</code> | Gives browser alert if 3boxjs/ipfs not supported in browser env, defaults to true. You can also set to false to implement your own alert and call Box.support to check if supported. |\n\n<a name=\"Box.supported\"></a>\n\n#### Box.supported() ⇒ <code>Boolean</code>\nDetermines if this browser environment supports 3boxjs and ipfs.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"standard":{"ignore":["/src/modernizr.js"]},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.14.4","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"14.4.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","ipfs-log":"^4.6.1","orbit-db":"^0.24.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.0","3id-blockchain-utils":"^0.4.0","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.20.4-beta.2_1595233543685_0.6739583336366295","host":"s3://npm-registry-packages"}},"1.21.0":{"name":"3box","version":"1.21.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.21.0","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"paul_lecam","email":"paul@ulem.net"},{"name":"zachferland","email":"zachferland@gmail.com"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"c2620c318d50bc8152c009199860711dee3ddb22","tarball":"https://registry.npmjs.org/3box/-/3box-1.21.0.tgz","fileCount":78,"integrity":"sha512-4D8+VeRyXFF6ECaBgPdengxgKRRfA3nlllAVtsZupv8MKpAGkoc/c+5k+XBwWtbozbv3EFY0we/QWpS7Uf1GRA==","signatures":[{"sig":"MEUCIQCz5tGOhIJxovAwBWovpFl+/hKLTEDlIoSZ/FVyrgQRdgIgYTneqicG/XyTiTp6KJo+pEO1ygHGV6ghXP1Yy5dlaVA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":13611187,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfLE/VCRA9TVsSAnZWagAANtAQAICmi7u4ZqDw+YkaivKX\nPFgKQo53Zo+MrGBiZng3jjA+uUgY0z74RlvgxC2iQ0yknY2XovUDSv7YDTzx\n0b/a8IjvW4mBmqqQ9rM0mKggITJWR6JnKulh6yu6V755PnjJMQzleYUFcMuc\ntelniqiynyUduU9lR5/0Je3erjIKlVhA28/fP9gvxPd+HYXN6/0OH7u0nL5f\nf3q3rkykAeQw3YIefUToiicybNQpjT7NX4yziMvs5b85RzG/RP93iW8HhTKw\nk8SakF68nCuRrhirceHMh7u4EQNM/+he1tEzw4Xkg128bKUi1M+5nAG2rJRG\n4Ah/td21dz7wcCnV8E3Dl8d8D0lD/K3WJbz7yJ21uDzPmnKCBGVbh3XLsxQW\nXJFUPr499gC4ITqQZTjH9iTQFPPZePBhGGgpgG/Cr1vzSJQ9ms21tTumXK9p\ngGHx+j/1ZegCIYUKqqpJ2keZ2id8tRWglXUbuebwZ7uf+zSDqdpPdQGjhllB\nTNnO7YS3ujoEy0irnnrQ+aZQwKL5un+54l1fvr9vGzvIug5LHyZ6t0zZbZqT\nU/fdWZS57G0wf+HneQwk6COzpS0CBx8mnzAZiidrPn7ENa3+oUxI/lfhTC0G\ng3GKjmBurGJMnH/wpteVaPpsRf6wuG+EN0TEYVVj0akicuCt9KXmiQURKS4K\nMpTJ\r\n=nTd2\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"c4c4cc78e39562460cd84a551fedcb2268d75c72","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","levelup":"^4.4.0","ipfs-log":"^4.6.1","orbit-db":"^0.24.2","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","3box-shared-cache":"^1.1.0","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.2","3id-blockchain-utils":"^0.4.1","@ethersproject/hdnode":"5.0.2","@ethersproject/wallet":"5.0.2","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.21.0_1596739533444_0.17480538499421616","host":"s3://npm-registry-packages"}},"1.22.0":{"name":"3box","version":"1.22.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.22.0","maintainers":[{"name":"paul_lecam","email":"paul@ulem.net"},{"name":"zachferland","email":"zachferland@gmail.com"},{"name":"oed","email":"oed@3box.io"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"9df1704ef98af6bca812eed3561ec76801a3ecca","tarball":"https://registry.npmjs.org/3box/-/3box-1.22.0.tgz","fileCount":80,"integrity":"sha512-3SQ/5VFqsteelgA9EWbQubXPU1NLxXsy/oRCIBJyBVybTzq49toohal1CG6QTorEndy7OZ55fYzVsddFxjO/Kg==","signatures":[{"sig":"MEYCIQDy/9/GsG2pt5YajHMieFD4OrmFsoqpUT96fCOCnCfaWAIhAMVimYK/C8q22ZnYK5qXjS7vaESkb/lZFwiKGdY7fRhM","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16647372,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfYLmjCRA9TVsSAnZWagAA5XgP/iIGpzr3pO6ojFJI5IW1\ndmdz872QjHB5xJniMdzp2ZyBnuFkiCkZjds9+KsT8zhe+O7Bu64yyB4SEUfd\n4h96MtWdI71A1E/2lHaZUGYVUhWI57vqIVKkinkXZ0Ys8zQIKTAWlXBsmczX\nk4YGA9QN47FUkr7LnkPxvLhfoQNsQ7upjHCJZJo+7hdIzVCOmVDqfxAo5tK+\nLOYMBLQDRyjxs1dbNX0f08cV94g/p0gqD0sjyHKatYQMh7MgpdTlRGVrizFf\nk5q42qbjEMxoDik/kmcPPzH2fLTTlUR1ypGNr/p7djtonZo2xLiiG0JeOEdV\nYlAGDtuanTP3QrUTqBUwQ9aLr/tjQWHlT8Siz6kGejSkW6zxi0Ev2WWEDBob\n2m1j5oB8TO9FHfftIoYvOcy94ET2DVxUQRcnwy/+PDERzF2bKFdL8YBdJtGQ\nK4P9zIwMycGhvy3Rd/YM1XrZ1pBnju88HNahDFMkkzni32KSq6DFP0NFXQfJ\nmZdHW8xh45DjmMG5qgwyEYeaDZSHs5zhR15ayOpRXM4K3y9BrS4MJyO0an6Q\n4qeSkEgOrry2x4qB+jhfI6DGHqs3PS470VP74q3FzfCj4s3UOEFlIDTpHENP\nWiahy7uJpNjSCZufGQr1d00uk5A/Quvm8Uhap+l0eouXX0nzlkzL/PqeqqsU\n8rX2\r\n=znZ+\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"gitHead":"c3f36e65ec6c4d310dae5fe043b71933918804a3","scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"zachferland","email":"zachferland@gmail.com"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.4.1","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"10.12.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","levelup":"^4.4.0","ipfs-log":"^4.6.5","orbit-db":"^0.25.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","webrtcsupport":"^2.2.0","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","3box-shared-cache":"^1.1.0","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.2","3id-blockchain-utils":"^0.4.1","@ethersproject/hdnode":"5.0.2","@ethersproject/wallet":"5.0.2","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.22.0_1600174498409_0.6540441835106876","host":"s3://npm-registry-packages"}},"1.22.1-alpha.0":{"name":"3box","version":"1.22.1-alpha.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.22.1-alpha.0","maintainers":[{"name":"paul_lecam","email":"paul@ulem.net"},{"name":"zachferland","email":"zachferland@gmail.com"},{"name":"oed","email":"oed@3box.io"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"f027add0b49f9de41cd7b2eaaafdd37891ac31f3","tarball":"https://registry.npmjs.org/3box/-/3box-1.22.1-alpha.0.tgz","fileCount":78,"integrity":"sha512-ssNu+csw6dxUQ803UGcibsMWHTzZprXzPmIIjB+0XD1G9Z2qH3meZKBInTYPyGRPYFeTqVuYlKUyr+TnEvrQBg==","signatures":[{"sig":"MEUCIQDcsZqOGkV4HCNWjK95s475q0kBaXZ1p2kSVX63C2rLWwIgCe/Ul8TeXU47KZ29VcQFT08xtzIL4a0sCDoVrRvW7O4=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16249041,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.4\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfaJh8CRA9TVsSAnZWagAAHGIP/0GkJWr6OCgLK0WjoGxH\nU3DcZ3RGelMyVsxaB4nU7a2ov5OatNUAu/uDLYq2dgUYMT95MNEbQpZ4NeiU\nEvcXyy0GIDExphA8ILdTcN5hL892CjsxMGPnC+Y1tDgHG8LnRVALtuFSryEb\n3qRcRp4vXGZ0+Ak8kVVDSRxg2cC+pBaQt+L1J1DGkK8nQUWg1cQR7KB+wIu8\n8AY0nlt1CfGNaYbxZ2o7RIsV4j5AJ/r+8rwUjmQLR3C8ccTz7xGYO+3m/mFp\nhYN5cXNZaNaTRB4zKtXdBiRhsLji8WPTjxekSuc/3CHn0BH7lNJIMK9OLJmb\neK07RDzzMTkw2gjFBuyhDMI4gBgjYp+sBv9SU3cDMRC7+7Iwx+tKjqO1Zqkz\nJNrybQCCG7cUq7lzmtwRAxmw6OTbVAFqDbr0MTe3U7k+N0FCIRh4eNlKJMMr\nFNeibCrNNquy1BhbJh9Dftze3TsXAZ7nAF8/wqmDSPXyhAf0SsRDj6kAJW5k\nEOg/dFTajC6nmCkXthGi7oUWGaRAdN5FCcUxNNl9MevBZTlg04VYN1HsuKs6\nVFs9RxtzIm+EOc5HQiYiLv9I6jHPoGbglS7QG3GpzJBcVTQFvroGGWmI5joE\nQB49YxeGUVgJECBt56xj02TSnC8qDzeO5PWHh/RrzXghnnuGaTGxtESMzjyk\n9eSE\r\n=YU14\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. This is best to call on page load, so it can begin initializing and connecting services like IPFS in background.\n\n```js\nconst box = await Box.create()\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. A provider needs to be passed, this can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). If using an ethereum provider you need to pass an ethereum address to the `auth` method as well. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address, provider })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## Maintainers\n[@oed](https://github.com/oed)\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.supported()](#Box.supported) ⇒ <code>Boolean</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.provider | <code>String</code> | A 3ID provider, or ethereum provider |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.supportCheck | <code>String</code> | Gives browser alert if 3boxjs/ipfs not supported in browser env, defaults to true. You can also set to false to implement your own alert and call Box.support to check if supported. |\n| opts.iframeCache | <code>Boolean</code> | Enable iframe cache for ipfs/orbit, defaults to true |\n\n<a name=\"Box.supported\"></a>\n\n#### Box.supported() ⇒ <code>Boolean</code>\nDetermines if this browser environment supports 3boxjs and ipfs.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"standard":{"ignore":["/src/modernizr.js"]},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.14.4","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"14.4.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","levelup":"^4.4.0","ipfs-log":"^4.6.5","orbit-db":"^0.25.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","3box-shared-cache":"^1.1.0","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.2","3id-blockchain-utils":"^0.4.1","@ethersproject/hdnode":"5.0.2","@ethersproject/wallet":"5.0.2","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.22.1-alpha.0_1600690299357_0.2550033241778915","host":"s3://npm-registry-packages"}},"1.22.1":{"name":"3box","version":"1.22.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.22.1","maintainers":[{"name":"paul_lecam","email":"paul@ulem.net"},{"name":"zachferland","email":"zachferland@gmail.com"},{"name":"oed","email":"oed@3box.io"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"0f25ab021440650084397b70c64a1d78728e5804","tarball":"https://registry.npmjs.org/3box/-/3box-1.22.1.tgz","fileCount":78,"integrity":"sha512-W/WUlRf2KYT+2b00GHOz2xoSkO7frUGXzxvmyVId/34k0ONBOngImjQ+zOgeKfIhpEoAs1VgmHhG1yxyYI8BVA==","signatures":[{"sig":"MEQCIDtI8/N0GPOaVRDXWLN1ldB5IuZxnFq7a4wwqSchxZkFAiB2bF4NbD5qbZzK56vC1VNC64yD4zWJUT0YKjavFfTssg==","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16249033,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfaK7DCRA9TVsSAnZWagAARDUP/3n/4LahLByEPhIywBcA\nluar9qRxq/d8Axi7M2fiWJjhwfSSb3S7HWHz0Pi0AOkXtm5VEzqzbGRex3ey\nt0pRJRHnEW1ohIlnKJ4zhkBhAnmtX9ZDNOu1MwhJ7devIZ4Yh97LtT0ZQBZ3\nosKg+CwdoO/NATYKB7yav4eKVdcN3i2Ne2V3SWF9rdBBdC8kDMwZLUCYeECY\n/0uwBHpSR7Sx1cZ5A7Ql+ajjbJThxKnYnAWntqDeMwXZBwwGoLBvQnI+1UzL\nEMHhsEggHIhORhasj+NPvYEk2phuYYOcWv5O3CwLZmYcXzkb/bAnlYiQpIoL\nEcIQvYJr79wnE1CB9kKJjbE+czZ54jUzjszrd8FE+aYruHtJUL7KjphWai43\nFxttjGvStFOEH3QwBK3Xh/dT3LFt4mRI8OsCjxOmFkfXvTZ9gSnaT8w2bbvY\nopac4sS45g9SLhiNvK/zGT0D4v0q2VjLAaOvWkrqJRc8pbcSxTqyBdeFs0xz\nSxkFpi4/PkAFUwOMAuiiTqK2b6kEoKta8W0SpqTcOEkIjMMg2hjNtTYHOmzz\nwtmiim2hsZ4dQVGkHz5OzoVUd5ixzxmB6F+LuB93XplC1imUOqa2i3b14mhL\nuL2TpKcYtvLHYYYC3BPBmGbU1B0VGXaePleyYqRBX1ufshOE91HD860389TE\nqqK5\r\n=4Xk0\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.14.8","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"14.11.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","levelup":"^4.4.0","ipfs-log":"^4.6.5","orbit-db":"^0.25.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","3box-shared-cache":"^1.1.0","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.2","3id-blockchain-utils":"^0.4.1","@ethersproject/hdnode":"5.0.2","@ethersproject/wallet":"5.0.2","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.22.1_1600696002840_0.8882366519021616","host":"s3://npm-registry-packages"}},"1.22.2-beta.0":{"name":"3box","version":"1.22.2-beta.0","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.22.2-beta.0","maintainers":[{"name":"paul_lecam","email":"paul@ulem.net"},{"name":"zachferland","email":"zachferland@gmail.com"},{"name":"oed","email":"oed@3box.io"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"a6052608967be72ac4adeba76201f2b10de9c28b","tarball":"https://registry.npmjs.org/3box/-/3box-1.22.2-beta.0.tgz","fileCount":78,"integrity":"sha512-9ii7VRTtuctSnOCWntvztD4PijnfsG7X1u3l748w4TLyxiuMwLVXldeYKG0jqKuilKPVQ3Yak06poyaDN8GWbg==","signatures":[{"sig":"MEUCIBNe0TZ4OmZYaBQHyVZWFQ7VqAt+HhLWY4vTy9FZcbk8AiEA7CW9d5ROZYJ1UNo44YCCfHNMx73snUPUcKHW9J+4QHA=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16234637,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfcY/hCRA9TVsSAnZWagAAWoMP/2jGh4A4ebUNdOMB3ZhX\n/Zs12VPQqYb532rgiPnKBmMAKtb82SuB+ARgsTgtOiOnJgi+C6myDqQ5LD8l\ndEe2QgPWh+WhAHzRrmPYGVBsO68qNaM3m/Q610ZEWFIRE7xFot1tq0FiU2M3\nvzE8557Kwe8pBT0Qr0RKQS/sEiXcTEng2yIcC/p8fcAgSPAHwH7XCTNUIw8g\njqRYJP2TrnIER5HB9zs8Z4qgYdb+349dFfNlaSprt89lYdEmOdb+QoJU7jIE\nUmS4V30z2TiDs0pPOau1Sya54S5Zs5wzSrKlByQfATkbsS52HEmYTTfvJdfb\nzRSBOpV0UtlkknC2/X6y4CNfp2rvEqYVLS0mD3h4zwrlWGrHSjVkmU4ZVlFj\nYJyY8R1zaP511jbiztNFPTKCqy2lsbgTGepzarfjnmrnoQjL5mi8UQgWoLow\nOMw+vb/dgcdsii9ZVUxMo1bJ/EeylpnqyuD7o4OLWAoz5DRdQeobeOzHFLAO\nQhmZJTHKMeFaQBNvw5heatV5UBvLHPewr+SbqLJXSQczM/mjZBTIxndXh7So\nn3EmA3a2jI5wIHOeViVotCv1RIfHhN8djAVix+2rY+CCP0sEJG5e/C1I4dd5\n8EZGNz8j6jBRAn8cWXXeJZeU0hCFq50Wacv539Ip5UE7dROrZGC2oGLFsAe2\nq1Qd\r\n=6cNe\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. This is best to call on page load, so it can begin initializing and connecting services like IPFS in background.\n\n```js\nconst box = await Box.create()\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. A provider needs to be passed, this can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). If using an ethereum provider you need to pass an ethereum address to the `auth` method as well. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address, provider })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## Maintainers\n[@oed](https://github.com/oed)\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.supported()](#Box.supported) ⇒ <code>Boolean</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.provider | <code>String</code> | A 3ID provider, or ethereum provider |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.supportCheck | <code>String</code> | Gives browser alert if 3boxjs/ipfs not supported in browser env, defaults to true. You can also set to false to implement your own alert and call Box.support to check if supported. |\n| opts.iframeCache | <code>Boolean</code> | Enable iframe cache for ipfs/orbit, defaults to true |\n\n<a name=\"Box.supported\"></a>\n\n#### Box.supported() ⇒ <code>Boolean</code>\nDetermines if this browser environment supports 3boxjs and ipfs.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostPinbot | <code>String</code> | MultiAddress of a Ghost Pinbot node |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"standard":{"ignore":["/src/modernizr.js"]},"repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.14.8","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"14.11.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","levelup":"^4.4.0","ipfs-log":"^4.6.5","orbit-db":"^0.25.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","3box-shared-cache":"^1.1.0","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.2","3id-blockchain-utils":"^0.4.1","@ethersproject/hdnode":"5.0.2","@ethersproject/wallet":"5.0.2","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"readmeFilename":"README.md","devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.22.2-beta.0_1601277920748_0.4089384696452987","host":"s3://npm-registry-packages"}},"1.22.2":{"name":"3box","version":"1.22.2","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.22.2","maintainers":[{"name":"paul_lecam","email":"paul@ulem.net"},{"name":"zachferland","email":"zachferland@gmail.com"},{"name":"oed","email":"oed@3box.io"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"9b091129e3abb4528760ddf1bf58a26cf5c892fc","tarball":"https://registry.npmjs.org/3box/-/3box-1.22.2.tgz","fileCount":78,"integrity":"sha512-xgq7AF5UYHYdJCEUwZ+dISf7acSu2NPzNQle+0X+mQ6hxrzFeVnBEVOsaaHf1nQy84Sc++0+GdKlj2M8L5kNAw==","signatures":[{"sig":"MEYCIQC6XqaxYIFw8JOjRhKFJ1ToBLCVsJDi66p1co31ef8ibAIhAPUkqslSYpU4kzEbmc+PQct+4Bhp8ACTMZlBzd4YwcKT","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":16234630,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJfcZtgCRA9TVsSAnZWagAAtyMP/jcV8yexUK/Jq14dtbjm\nSg85Wq2tPGxQXrtW7ON6YGX6373jbYVAZ3kaN0OV+RwLoed/pjaWFo3Mm1FK\nNVju7a2kOWRkaVa9GOnmH2RFlZaI7Br0HieiKbSwURYcDQ5kGxydkMMjwF0n\nxuq/EBxN9RLCgBNJGu1/Iv1D+moffwhp2jpC6Uh/YaAzm5ja2R7kqHOncoXu\nfeAAx+Ig1je1s7AQG0i6zuHaMedk2tc8FykbN++Qv+00baKgMxYuoW2W90Rg\npo19wxI3+05uKFKwEWjK3oZej4kbRpwn0s5qpl/2Ww9pDXuNrSKbpsiLUG09\nuQ7QI2zZTclAbfoc/RSHPyHxaHsjObk3W5iSbKetxx2n3L7kw0i7dKFYmBqX\nHekhjI2rp+NxK3kAfReaDcmMjaCgGLx+bDB4qTZW91th5eQEVfuKNtjgnsp/\nlRPkVZ6m/P+Y50vuvdWsKFfN8DVLljnBcLcCGz7j1hzXF2sST1lGZHwFtnIK\nAzRD0I8wuyzv6IBRR355bhUkw7otvMf5laEKx/J/a/bl7ZNq6sWmZt+7+1kM\nnp69Yau0qRjkfPxcikNlR/F9HPGgW/ajP1DGxNG24Blt1jSy9E/FfSygkHGA\nWQdr1o6Uk6Kw32axSBRL3cwUNjbxUxIQ21UP1GrGQIvto/IK96c+TaUC4wFb\nRSMh\r\n=XExZ\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"jest-environment-uint8array","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist:example -- --watch & npm run build:dist:dev -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","build:dist:example":"webpack --config webpack.example.config.js --mode=development","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"standard":{"ignore":["/src/modernizr.js"]},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.14.8","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"14.11.0","dependencies":{"ipfs":"^0.46.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^1.0.3","levelup":"^4.4.0","ipfs-log":"^4.6.5","orbit-db":"^0.25.1","ipfs-repo":"^3.0.2","js-sha256":"^0.9.0","p-timeout":"^3.2.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.1.0","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","libp2p-pubsub":"^0.4.6","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^2.0.1","3box-shared-cache":"^1.1.0","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","muport-did-resolver":"^1.0.2","3box-orbitdb-plugins":"^2.1.2","3id-blockchain-utils":"^0.4.1","@ethersproject/hdnode":"5.0.2","@ethersproject/wallet":"5.0.2","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^26.0.1","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","authereum":"0.0.4-beta.155","fortmatic":"^2.0.6","web3modal":"^1.6.3","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","@portis/web3":"^2.0.0-beta.55","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","jest-environment-uint8array":"^1.0.0","@walletconnect/web3-provider":"^1.0.0-beta.47","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.22.2_1601280863675_0.5417896795128474","host":"s3://npm-registry-packages"}},"1.19.1":{"name":"3box","version":"1.19.1","author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","_id":"3box@1.19.1","maintainers":[{"name":"oed","email":"oed@3box.io"},{"name":"zachferland","email":"zachferland@gmail.com"},{"name":"paul_lecam","email":"paul@ulem.net"}],"homepage":"https://github.com/3box/3box-js#readme","bugs":{"url":"https://github.com/3box/3box-js/issues"},"dist":{"shasum":"b4d9d0e7fc7d158931df03e3bca2f9c6f23d80da","tarball":"https://registry.npmjs.org/3box/-/3box-1.19.1.tgz","fileCount":76,"integrity":"sha512-dYVfj+Mf0kvNuRT0Tr0tMVPAHip4IdfW3QqE8XpT3zyd+1p9Hgcynwg4ko3+Tu/WmEHxWCZk9QwZDWMwb1nmfA==","signatures":[{"sig":"MEUCIQCBXoKbdKOhPK4gqibJAL2++1klvZiVkWrYzQlLtHNxowIgHYC9ldMnMZdYLcEtvpy6ZF6Vxu2meuxqOsymrrRMqzw=","keyid":"SHA256:jl3bwswu80PjjokCgh0o2w5c2U4LhQAE57gj9cz1kzA"}],"unpackedSize":15543017,"npm-signature":"-----BEGIN PGP SIGNATURE-----\r\nVersion: OpenPGP.js v3.0.13\r\nComment: https://openpgpjs.org\r\n\r\nwsFcBAEBCAAQBQJgNT+vCRA9TVsSAnZWagAAm6MP/1QubdhG8XFWzAHeRW2S\nTyYUYRopmgVAy58gJA3TBH+2A1u9vk0J/mZVt/Qj/MOVlHmUlCppeaQN7O7i\nPgDggMNY94GWgacd6OAMIR2+CmWKN6FT9EDszICGToUXotfPRWxpqI1gS0bh\nM6tEFb/1S95DmZXogIf45R0UQ6EK+w7/1xBUdjsvX8w5hA6IQ7zaiwg3SSEq\nr7yaNjDrUh6DAoPaHhPxUblbvYkFdcRxL/x9AULI72LyTZNlginb1SnSbqNH\np49HJeJIn8uXI0G5h/olqtzmmigNjyiuU4j4IappiU+zAXjS/vwg+SHVMTmj\ngnDNTHH4vmZvJ6Hu8zaIf1djYzz8wQibet4NPmXn7o3cRdoufwapqlBqnZqZ\n2buKs4mUR3htKVbQ73hXOxCTo/qxmEItU6uSXY4JVAiAO7beWAIiteRaKvtf\nXhln+5cSAtjr3O8vErnfWmUFVEB7p/3pt5hsgFcqSu6LMoPtFHBSym/hFXzF\njGbjlfeK+Uh/mDpCT3JMjKpXNAWzQDn0TfB5n8h4zmnO9Z94djYbtbch+PPL\nMRlApbH521G8zbUa6BMVzGds38iHVfABe8QdHc99LdWO6QPhjCEop1F9GSsV\notVHXUZFOljDsU+mfdCql5IKcn5fJLOhlcRyNkfDObCC1fn2PLRJJAUrtqDJ\nTCKC\r\n=Luf3\r\n-----END PGP SIGNATURE-----\r\n"},"jest":{"testEnvironment":"node","testPathIgnorePatterns":["node_modules","lib","<rootDir>/src/__tests__/testUtils.js"]},"main":"lib/3box.js","browser":{"fs":false,"child_process":false},"scripts":{"lint":"standard --verbose src/**","test":"rm -rf ./tmp && jest --forceExit --coverage --runInBand --testURL=\"http://localhost\"","build":"npm run build:es5; npm run build:dist; npm run build:dist:prod; npm run build:dist:api","build:es5":"rm -rf ./lib; ./node_modules/.bin/babel src --out-dir lib --ignore=src/__tests__/,src/__mocks__/","build:dist":"webpack --config webpack.config.js --mode=development","example:start":"npm run build:dist -- --watch & npm run example-server:start","build:dist:api":"webpack --config webpack.api.config.js --mode=production","build:dist:dev":"webpack --config webpack.dev.config.js --mode=development","prepublishOnly":"npm run build; npm run generate-readme","build:dist:prod":"webpack --config webpack.config.js --mode=production --output-filename 3box.min.js","generate-readme":"cp readme-template.md README.md; ./node_modules/.bin/jsdoc2md -g none -d 3 'src/**/*.js' >> README.md","example-server:start":"node example/server.js"},"_npmUser":{"name":"oed","email":"oed@3box.io"},"deprecated":"Deprecated in favor of Ceramic: https://developers.ceramic.network","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"_npmVersion":"6.14.5","description":"Interact with user data","directories":{"lib":"lib"},"_nodeVersion":"12.18.1","dependencies":{"ipfs":"^0.40.0","store":"^2.0.12","events":"^3.0.0","did-jwt":"^4.2.0","is-ipfs":"^0.6.3","ipfs-log":"^4.5.5","orbit-db":"^0.23.1","ipfs-repo":"^0.30.1","js-sha256":"^0.9.0","tweetnacl":"^1.0.1","node-fetch":"^2.6.0","3id-connect":"0.0.2","3id-resolver":"^1.0.0","did-resolver":"^1.1.0","lodash.merge":"^4.6.2","@babel/runtime":"^7.4.5","orbit-db-cache":"^0.3.0","tweetnacl-util":"^0.15.0","graphql-request":"^1.8.2","ipfs-pubsub-room":"^1.4.1","ipfs-did-document":"^1.2.3","https-did-resolver":"^1.0.0","ipfs-postmsg-proxy":"^3.1.1","muport-did-resolver":"^1.0.1","3box-orbitdb-plugins":"^2.0.0","3id-blockchain-utils":"^0.3.3","@ethersproject/hdnode":"5.0.0-beta.137","@ethersproject/wallet":"5.0.0-beta.136","orbit-db-storage-adapter":"^0.5.3","orbit-db-identity-provider":"^0.3.0"},"_hasShrinkwrap":false,"devDependencies":{"jest":"^23.6.0","express":"^4.17.0","webpack":"^4.32.2","standard":"^14.3.1","@babel/cli":"^7.4.4","babel-core":"7.0.0-bridge.0","@babel/core":"^7.4.5","webpack-cli":"^3.3.2","babel-loader":"^8.0.6","identity-wallet":"^1.1.3","@babel/preset-env":"^7.4.5","jsdoc-to-markdown":"^5.0.0","@babel/preset-react":"^7.0.0","@babel/plugin-transform-runtime":"^7.4.4","@babel/plugin-transform-modules-commonjs":"^7.4.4","@babel/plugin-proposal-object-rest-spread":"^7.4.4"},"_npmOperationalInternal":{"tmp":"tmp/3box_1.19.1_1614102447256_0.519510557619562","host":"s3://npm-registry-packages"}}},"time":{"created":"2018-08-20T14:13:13.930Z","modified":"2024-10-23T15:43:10.052Z","0.0.1":"2018-08-20T14:13:14.031Z","0.0.2":"2018-09-05T11:57:34.640Z","0.0.3":"2018-09-07T04:36:26.452Z","0.0.4":"2018-09-07T05:35:56.542Z","0.0.5-beta-1":"2018-09-11T13:18:26.730Z","0.0.5-beta-2":"2018-09-11T13:19:17.790Z","1.0.0-beta-1":"2018-09-12T20:59:24.588Z","1.0.0-beta-2":"2018-09-13T15:48:54.371Z","1.0.0-beta-3":"2018-09-13T17:26:12.484Z","1.0.0-beta-4":"2018-10-02T09:28:33.478Z","1.0.0-beta-5":"2018-10-03T09:31:12.993Z","1.0.0-beta-6":"2018-10-04T18:33:36.835Z","1.0.0-beta-7":"2018-10-05T18:47:03.560Z","1.0.0-beta-8":"2018-10-10T13:36:43.822Z","1.0.0-beta-9":"2018-10-11T17:19:03.076Z","1.0.0-beta-10":"2018-10-17T08:52:37.644Z","1.0.0-beta-11":"2018-10-18T14:49:03.926Z","1.0.0-beta-12":"2018-10-19T12:22:27.732Z","1.0.0-beta-13":"2018-10-23T15:23:25.083Z","1.0.0":"2018-10-24T15:02:55.386Z","1.0.1":"2018-10-24T18:04:12.442Z","1.0.2":"2018-10-25T17:20:24.569Z","1.0.3":"2018-10-26T21:49:30.020Z","1.0.4":"2018-11-05T18:20:03.909Z","1.0.5":"2018-11-14T20:46:07.244Z","1.0.6":"2018-12-04T18:18:05.896Z","1.0.6-beta-1":"2018-12-05T17:23:41.887Z","1.0.7-beta-1":"2018-12-13T08:32:55.994Z","1.0.7-beta-2":"2018-12-18T19:36:14.657Z","1.1.0-beta-1":"2018-12-20T23:39:53.337Z","1.1.0":"2018-12-27T10:49:00.122Z","1.2.0-beta.1":"2018-12-28T14:56:47.953Z","1.2.0-beta.2":"2019-01-05T00:17:59.879Z","1.2.0-beta.3":"2019-01-05T12:42:49.469Z","1.2.0-beta.4":"2019-01-06T17:21:28.096Z","1.2.0-beta.5":"2019-01-08T15:05:04.503Z","1.2.0-beta.6":"2019-01-09T19:00:37.892Z","1.2.0":"2019-01-10T15:52:41.740Z","1.2.1":"2019-01-17T09:58:29.610Z","1.2.2":"2019-01-25T18:02:15.321Z","1.3.0-beta.1":"2019-02-01T17:15:04.323Z","1.3.0-beta.2":"2019-02-02T19:40:07.564Z","1.3.0":"2019-02-05T20:55:41.161Z","1.4.0-beta.1":"2019-02-21T20:37:02.469Z","1.4.0":"2019-02-21T21:02:51.428Z","1.5.0":"2019-03-12T14:54:56.530Z","1.5.1":"2019-03-20T15:53:53.789Z","1.6.0":"2019-03-28T15:19:11.512Z","1.6.1-beta.1":"2019-03-29T12:48:24.938Z","1.6.1":"2019-04-01T08:12:25.897Z","1.6.1-node-1":"2019-04-08T12:37:35.523Z","1.6.2":"2019-04-09T15:17:11.832Z","1.7.0-beta.1":"2019-04-11T15:50:47.002Z","1.7.0-beta.2":"2019-04-12T16:59:02.890Z","1.7.0":"2019-04-12T17:59:02.056Z","1.7.0-node-1":"2019-04-13T18:31:32.352Z","1.7.1":"2019-04-25T15:23:43.177Z","1.7.2-beta.1":"2019-04-29T11:27:14.885Z","1.7.2-beta.2":"2019-04-29T11:35:19.429Z","1.7.2-beta.3":"2019-04-29T11:46:43.848Z","1.7.2":"2019-04-30T15:46:45.094Z","1.8.0":"2019-05-09T12:45:25.312Z","1.8.1-beta.1":"2019-05-16T15:45:59.021Z","1.8.1":"2019-05-16T18:50:30.998Z","1.8.2":"2019-05-21T13:07:50.514Z","1.8.3":"2019-05-24T15:48:28.231Z","1.8.4-beta.1":"2019-05-30T10:23:32.083Z","1.8.4":"2019-05-30T12:43:56.597Z","1.8.5":"2019-05-30T14:13:37.162Z","1.9.0-beta.1":"2019-06-04T11:02:25.531Z","1.9.0-rc.1":"2019-06-04T15:01:36.057Z","1.9.0-rc.2":"2019-06-08T23:52:34.527Z","1.9.0-rc.3":"2019-06-11T13:25:01.782Z","1.9.0-rc.4":"2019-06-11T17:37:09.198Z","1.9.0":"2019-06-11T20:05:33.014Z","1.9.1":"2019-06-20T02:07:23.321Z","1.10.0":"2019-07-17T14:42:41.660Z","1.10.1":"2019-07-24T13:40:20.418Z","1.10.2":"2019-07-25T15:38:19.955Z","1.10.3":"2019-07-26T13:22:44.416Z","1.10.4":"2019-07-31T16:47:17.970Z","1.10.5-beta.1":"2019-07-31T19:16:13.950Z","1.10.5-beta.2":"2019-08-01T08:33:40.910Z","1.10.5":"2019-08-02T17:00:08.066Z","1.10.6-beta.1":"2019-08-13T11:28:56.697Z","1.10.6":"2019-08-15T08:54:31.857Z","1.11.0-beta.1":"2019-08-15T09:13:41.890Z","1.10.7":"2019-08-19T12:34:05.643Z","1.10.8":"2019-09-02T17:17:09.869Z","1.10.9":"2019-09-10T16:41:06.297Z","1.10.10":"2019-09-12T08:45:49.272Z","1.11.0":"2019-09-26T08:40:09.236Z","1.12.0-beta.1":"2019-09-27T14:20:08.961Z","1.12.0-beta.2":"2019-10-04T09:10:26.618Z","1.12.0":"2019-10-04T15:14:05.735Z","1.13.0-beta.1":"2019-10-07T06:29:55.053Z","1.13.0-beta.2":"2019-10-07T07:01:37.816Z","1.13.0":"2019-10-18T08:40:30.478Z","1.13.1-beta.1":"2019-10-23T13:41:38.154Z","1.13.1":"2019-10-25T19:19:29.144Z","1.13.2":"2019-11-14T22:19:51.430Z","1.13.3-beta.1":"2019-11-18T16:24:26.272Z","1.13.3-beta.2":"2019-11-19T07:43:10.247Z","1.14.0":"2019-12-02T19:15:57.182Z","1.14.1-beta.1":"2019-12-04T15:28:30.328Z","1.15.0":"2019-12-13T12:19:54.148Z","1.16.0-beta.1":"2020-01-07T08:55:34.242Z","1.16.0-beta.2":"2020-01-09T13:02:20.588Z","1.16.0-beta.3":"2020-01-09T17:02:44.299Z","1.16.0":"2020-01-10T17:23:36.653Z","1.16.1":"2020-01-13T19:56:37.118Z","1.16.2-beta.1":"2020-01-30T12:44:02.166Z","1.16.2-beta.2":"2020-01-31T08:52:05.341Z","1.16.2-beta.3":"2020-01-31T09:10:37.012Z","1.16.2-beta.4":"2020-02-03T12:26:31.541Z","1.16.2":"2020-02-05T18:14:59.942Z","1.16.3-beta.1":"2020-02-13T22:03:42.099Z","1.16.3":"2020-02-13T23:38:03.572Z","1.17.0":"2020-02-14T01:36:11.564Z","1.17.1":"2020-02-20T16:40:09.842Z","1.17.2-beta.1":"2020-03-03T13:02:29.974Z","1.17.2-beta.2":"2020-03-03T13:05:27.767Z","1.18.0-beta.1":"2020-04-14T16:17:36.483Z","1.18.0":"2020-04-21T13:44:55.702Z","1.18.1":"2020-04-21T21:07:13.521Z","1.19.0-rc.1":"2020-04-30T09:45:44.529Z","1.19.0":"2020-05-13T08:16:59.025Z","1.20.0-beta.0":"2020-06-15T13:12:17.837Z","1.20.0":"2020-06-16T13:33:16.336Z","1.20.1":"2020-06-23T18:52:38.636Z","1.20.2-beta.1":"2020-06-25T09:28:01.785Z","1.20.2":"2020-07-09T16:51:46.885Z","1.20.3":"2020-07-13T21:17:23.821Z","1.20.4-beta.1":"2020-07-15T19:48:45.568Z","1.20.4-beta.2":"2020-07-20T08:25:43.957Z","1.21.0":"2020-08-06T18:45:33.680Z","1.22.0":"2020-09-15T12:54:58.709Z","1.22.1-alpha.0":"2020-09-21T12:11:39.747Z","1.22.1":"2020-09-21T13:46:43.166Z","1.22.2-beta.0":"2020-09-28T07:25:21.063Z","1.22.2":"2020-09-28T08:14:23.964Z","1.19.1":"2021-02-23T17:47:27.516Z"},"bugs":{"url":"https://github.com/3box/3box-js/issues"},"author":{"name":"3box","email":"team@3box.io"},"license":"Apache-2.0","homepage":"https://github.com/3box/3box-js#readme","repository":{"url":"git+https://github.com/3box/3box-js.git","type":"git"},"description":"Interact with user data","maintainers":[{"email":"oed@3box.io","name":"oed"},{"email":"zachferland@gmail.com","name":"zachferland"}],"readme":"[![CircleCI](https://img.shields.io/circleci/project/github/3box/3box-js.svg?style=for-the-badge)](https://circleci.com/gh/3box/3box-js)\n[![Discord](https://img.shields.io/discord/484729862368526356.svg?style=for-the-badge)](https://discordapp.com/invite/Z3f3Cxy)\n[![npm](https://img.shields.io/npm/dt/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![npm](https://img.shields.io/npm/v/3box.svg?style=for-the-badge)](https://www.npmjs.com/package/3box)\n[![Codecov](https://img.shields.io/codecov/c/github/3box/3box-js.svg?style=for-the-badge)](https://codecov.io/gh/3box/3box-js)\n[![Twitter Follow](https://img.shields.io/twitter/follow/3boxdb.svg?style=for-the-badge&label=Twitter)](https://twitter.com/3boxdb)\n[![Greenkeeper badge](https://badges.greenkeeper.io/3box/3box-js.svg)](https://greenkeeper.io/)\n\n[Install](#install) | [Usage](#usage) | [Example](#example) | [Data Standards](#datastandards) | [API Docs](#api)\n\n# 3box-js\n\nThis is a library which allows you to set, get, and remove private and public data associated with an ethereum account. It can be used to store identity data, user settings, etc. by dapps that use a web3 enabled browser. The data will be retrievable as long as the user has access to the private key for the used ethereum account. The data is encrypted and can not be read by any third party that the user hasn't authorized. There is one shared space for data which all authorized dapps access by default, then there are spaces which dapps have to request explicit consent to access.\n\n## Getting Started\n### <a name=\"install\"></a>Installation\nInstall 3box in your npm project:\n```\n$ npm install 3box\n```\n\n### <a name=\"usage\"></a>Usage\n#### Import 3Box into your project\nImport the 3box module\n```js\nconst Box = require('3box')\n```\nImport using the dist build in your html code\n```js\n<script type=\"text/javascript\" src=\"../dist/3box.js\"></script>\n```\n\nOr optionally by loading remote copy from [unpkg](https://unpkg.com/) CDN.\n\n```html\n<!-- The most recent version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.js\"></script>\n<!-- The most recent minified version  -->\n<script src=\"https://unpkg.com/3box/dist/3box.min.js\"></script>\n<!-- Load specific versions by specifying the version as follows -->\n<script src=\"https://unpkg.com/3box@<version>/dist/3box.js\"></script>\n```\n\n## Profiles API\n### Get the existing public profile of an address (or DID)\n3Box allows users to create a public profile for their Ethereum address. In your dapp you might have multiple ethereum addresses that you would like to display a name, image, and other basic social metadata for. The `getProfile` method allows you to fetch the public profile of any ethereum address (if it has one). This is a *static* method so you can call it directly from the **Box** object.\n\n```js\nconst profile = await Box.getProfile('0x12345abcde')\nconsole.log(profile)\n```\n\n### Update (get, set, remove) public and private profile data\n3Box allows applications to create, read, update, and delete public and private data stored in a user's 3Box. To enable this functionality, applications must first authenticate the user's 3Box by calling the `auth` method. This method prompts the user to authenticate (sign-in) to your dapp and returns a promise with a threeBox instance. You can only update (set, get, remove) data for users that have authenticated to and are currently interacting with your dapp. Below `ethereumProvider` refers to the object that you would get from `web3.currentProvider`, or `window.ethereum`.\n\n#### 1. Create a 3Box instance\nTo create a 3Box session you call the `create` method. This creates an instance of the Box class which can be used to openThreads and authenticate the user in any order. In order to create a 3Box session a `provider` needs to be passed. This can be an `ethereum provider` (from `web3.currentProvider`, or `window.ethereum`) or a `3ID Provider` (from [IdentityWallet](https://github.com/3box/identity-wallet-js)). It is now suggested to use the 3ID Connect Provider, which is a 3ID provider that wraps available `ethereum providers` and will manage/permission 3ID keys, authentication and blockchain account links inside an iframe. This will become the default soon and will overide passed `ethereum providers`. You can get the 3ID Connect Provider as follows.\n\n```js\nconst provider = await Box.get3idConnectProvider()\nconst box = await Box.create(provider)\n```\n\n#### 2. Authenticate user\nCalling the `auth` method will authenticate the user. If you want to authenticate the user to one or multiple spaces you can specify this here. If when you created the 3Box session you used an ethereum provider you need to pass an ethereum address to the `auth` method. If the user does not have an existing 3Box account, this method will automatically create one for them in the background.\n```js\nconst address = '0x12345abcde'\nconst spaces = ['myDapp']\nawait box.auth(spaces, { address })\n```\n\n#### 3. Sync user's available 3Box data from the network\nWhen you first authenticate the box in your dapp all data might not be synced from the network yet. You should therefore wait for the data to be fully synced. To do this you can simply await the `box.syncDone` promise:\n```js\nawait box.syncDone\n```\nThis will allow you to know when all the user's data is available to you. We advise against *setting* any data before this sync has happened. However, reading data before the sync is complete is fine and encouraged - just remember to check for updates once the sync is finished! Please note, `box.syncDone` can only be called once the user has been authenticated, it is  not possible if only the `Box.create` method has been called.\n\nIf you prefer to not use promises you can add a callback using the `onSyncDone` method.\n\n#### 3. Interact with 3Box profile data\nYou can now use the `box` instance object to interact with public and private data stored in the user's profile. In both the public and the private data store you use a `key` to set a `value`.\n\n```js\n// use the public profile\n// get\nconst nickname = await box.public.get('name')\nconsole.log(nickname)\n// set\nawait box.public.set('name', 'oed')\n// remove\nawait box.public.remove('name')\n\n// use the private store\n// get\nconst email = await box.private.get('email')\nconsole.log(email)\n// set\nawait box.private.set('email', 'oed@email.service')\n// remove\nawait box.private.remove('email')\n```\n\n##### Set multiple fields at once:\n```js\nconst fields = ['name', 'website', 'employer']\nconst values = ['Jon Schwartz', 'openworklabs.com', 'Open Work Labs']\n\nawait box.public.setMultiple(fields, values)\n\nconst privateFields = ['age', 'coinBalance']\nconst privateValues = ['xxx', 'yyy']\n\nawait box.private.setMultiple(privateFields, privateValues)\n```\n\n##### Open a thread\nOnce you have created a 3Box session you can open a thread to view data in it. This can be done before you authenticate the user (required for them to post in the thread).\nWhen opening a thread the moderation options need to be given. You can pass `firstModerator`, a 3ID (or ethereum address) of the first moderator, and a `members` boolean which indicates if it is a members thread or not.\n```js\nconst thread = await box.openThread('myDapp', 'myThread', { firstModerator: 'did:3:bafy...', members: true })\n```\nOnce a thread has been opened you can call the `getPosts()` method to retrive the posts.\n\n\n<!-- commenting this out for now, not really needed when we're not using the iframe\n#### IPFS Configs\n\nTwo options are available if you want to pass additional IPFS config options to the IPFS object used in the library.\n\nFirst you can pass your own IPFS object, configured how you decide and then disable the iframe as well. This offers the most optionality but experiences a loss in performace without the iframe.\n\n```js\nconst IPFS_OPTIONS = {\n  EXPERIMENTAL: {\n    pubsub: true\n  },\n  ... // Add your additional options, pubsub is required\n}\n\nconst ipfs = new IPFS(IPFS_OPTIONS)\nconst box = await Box.openBox('0x12345abcde', ethereumProvider, { ipfs, iframeStore: false })\n```\n\nSecond you can access the already initialized default IPFS object and change the IPFS configurations available after initialization. For example you can add a pinning node as follows.\n\n```js\nconst box = await Box.openBox('0x12345abcde', ethereumProvider)\n\nbox._ipfs.swarm.connect(pinningNode, () => {\n  ...\n})\n```\n\nReference [ipfs-js](https://github.com/ipfs/js-ipfs) for additional options.\n-->\n\n## Spaces API (Storage)\n### Open a space\nA space is a named section of a users 3Box. Each space has both a public and a private store, and for every space you open the user has to grant explicit consent to view that space. This means that if your dapp uses a space that no other dapp uses, only your dapp is allowed to update the data and read the private store of that particular space. To open a space called `narwhal` you simply call:\n\n```js\nconst space = await box.openSpace('narwhal')\n```\n\n#### Sync user's available space data from the network\nSimilarly to how you need to wait for data to sync in a users main data storage, you may also do the same thing for a space:\n```js\nawait space.syncDone\n```\n\n#### Get, set, and remove space data\nInteracting with data in a space is done in the same way as interacting with `box.public` and `box.private` ([see here](#interact-with-3box-data)). For example:\n```js\nconst config = await space.private.get('dapp-config')\n```\n\n## Threads API (Messaging)\n### Add public and confidential message threads to your app\nThreads are a shared datastore that enable decentralized communication between users, by allowing one or more users to post messages in a sequence. This functionality is great for adding commenting, chat, messaging, feed, and stream features to your application. Threads are saved within a space and users that join a thread (with the same name, space, moderation configs, and access configs) will be able to communicate in that thread.\n\nFor the fully detailed spec, view the [documentation](https://github.com/3box/3box/blob/master/3IPs/3ip-2.md).\n\n#### Viewing a Public Thread\nYou can get all posts made in a public thread without opening a space. This is great for allowing visitors of your site view comments made by other users. This is achieved by calling the `getThread` method on the Box object. A thread can be referenced by all its configuration options or by its address.\n```js\nconst posts = await Box.getThread(spaceName, threadName, firstModerator, membersThread)\nconsole.log(posts)\n```\nThreads can also be viewed without opening space, or authenticating by calling the `getPosts()` method on the thread object returned from `openThread` (see Open a thread section above).\n\n```js\nconst posts = await Box.getThreadByAddress(threadAddress)\nconsole.log(posts)\n```\nHowever if applications want to add interactivity to the thread, such as allowing the user to post in a thread or follow updates in a thread, you will need to open their space to enable additional functionality. Same is true for a confidential thread, which requires you autheticate to get access to view the posts in a confidential thread.\n\n#### Interacting with a Thread\n\n##### 1.a Creating a Public Thread\n\nTo create and join a public thread, you can simply join the thread. This will implicitly use the moderation options where the current user is the `firstModerator` and `members` is false.\n\n```js\nconst thread = await space.joinThread('myThread')\n```\n\nA thread can also be given the moderation options when joining. You can pass `firstModerator`, a 3ID of the first moderator, and a `members` boolean which indicates if it is a members thread or not. Moderators can add other moderators, add members, and delete any posts in the thread. Members can post in member only threads.\n\n```js\nconst thread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\n##### 1.b Creating a Confidential Thread\n\nTo create and join a confidential thread.\n\n```js\nconst thread = await space.createConfidentialThread('myConfThread')\n```\n\nAt creation you will likely want to add other members so that they can read and write messages to the thread, as shown below.\n\n##### 2. Joining a Thread\n\nAn existing public or confidential thread can be joined by its address. Confidential threads are best referenced by their address.\n\n```js\nconst thread = await space.joinThreadByAddress('/orbitdb/zdpuAp5QpBKR4BBVTvqe3KXVcNgo4z8Rkp9C5eK38iuEZj3jq/3box.thread.testSpace.testThread')\n```\n\nWhile public threads can be joined by address or by passing known configs (same as above).\n\n```js\nconst publicThread = await space.joinThread('myThread', { firstModerator: 'some3ID', members: true })\n```\n\nAn address of a thread can be found as follows once joined.\n\n```js\nconst threadAddress = thread.address\n```\n\n##### 3. Posting to a thread\nThis allows the user to add a message to the thread. The author of the message will be the user's 3Box DID. When a user posts in a thread, they are automatically subscribed to the thread and it is saved in the space used by the application under the key `thread-threadName`.\n```js\nawait thread.post('hello world')\n```\n##### 4. Getting all posts in a thread\nThis allows applications to get the posts in a thread.\n```js\nconst posts = await thread.getPosts()\nconsole.log(posts)\n```\n##### 5. Listening for updates in thread\nThis allows applications to listen for new posts in the thread, and perform an action when this occurs, such as adding the new message to the application's UI.\n```js\nthread.onUpdate(myCallbackFunction)\n```\n\n##### 6. Handling moderation and capabilities\n\nAdd a moderator and list all existing moderators\n```js\nawait thread.addModerator('some3ID')\n\nconst mods = await thread.listModerators()\n```\n\nAdd a member and list all existing members, if a members only thread\n```js\nawait thread.addMember('some3ID')\n\nconst members = await thread.listMembers()\n```\n\nListen for when there has been moderators or member added.\n```js\nthread.onNewCapabilities(myCallbackFunction)\n```\n\n## <a name=\"example\"></a> Example Application\n\nYou can quickly run and interact with some code by looking at the files in the `/example` folder. You run the example with the following commands:\n\n```bash\n$ npm ci\n$ npm run example:start\n```\n\nThis runs a simple server at `http://localhost:3000/` that serves the static `example/index.html` file. This allows it easily interact with metamask. You can edit the `example/index.html` file to try differnt code.\n\n## Build\n\n### Optimize build for read-only 3Box API\n\nIf you only want to fetch profile data from 3Box's profile APIs you can optimize by importing only those functions or the API specific dist file. Since this includes minimal dependencies, file size is ~ 80kb vs 4+mb for the full build.\n\n```js\nconst { profileGraphQL, getProfile, getProfiles, getVerifiedAccounts } = require('3box/lib/api')\n```\n```html\n<script src=\"https://unpkg.com/3box/dist/3box.api.min.js\"></script>\n```\n\n### Resolving build size issues and out of memory errors\n\nSome platforms, tooling, or configs have caused the build process to throw out of memory errors. This is a combination of the size of our library (plus dependencies) and the specific configs you have for your build. It could be things like tooling running on dependencies and not just your source or dependencies be recursively resolved. You can attempt to build the library anyways by adding the follow environment variable to increase memory for the node process.\n\n```\nNODE_OPTIONS=--max_old_space_size=4096 npm run build\n```\n\n## <a name=\"datastandards\"></a> Data Standards\nDapps can store data about users that relate to only their dapp. However we encurage dapps to share data between them for a richer web3 experience. Therefore we have created [**Key Conventions**](https://github.com/3box/3box/blob/master/community/key-conventions.md) in order to facilitate this. Feel free to make a PR to this file to explain to the community how you use 3Box!\n\n## <a nam=\"idUtils\"></a> Validate claims\nUse the `idUtils` module to [validate claims](https://www.w3.org/TR/verifiable-claims-data-model/). See\nthe [did-jwt](https://github.com/uport-project/did-jwt) library for more details.\n\n```js\nconst { idUtils } = require('3box')\n\nconst claim = 'eyJ0eX...'\nidUtils.verifyClaim(claim)\n  .then(valid => console.info('details:', valid)\n  .catch(err => console.error('claim verification failed:', err)\n```\n\n## <a name=\"api\"></a> API Documentation\n<a name=\"Box\"></a>\n\n### Box ⇐ [<code>BoxApi</code>](#BoxApi)\n**Kind**: global class  \n**Extends**: [<code>BoxApi</code>](#BoxApi)  \n\n* [Box](#Box) ⇐ [<code>BoxApi</code>](#BoxApi)\n    * [new Box()](#new_Box_new)\n    * _instance_\n        * [.public](#Box+public)\n        * [.private](#Box+private)\n        * [.verified](#Box+verified)\n        * [.spaces](#Box+spaces)\n        * [.syncDone](#Box+syncDone)\n        * [.DID](#Box+DID)\n        * [.auth(spaces, opts)](#Box+auth)\n        * [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)\n        * [.openThread(space, name, opts)](#Box+openThread) ⇒ [<code>Thread</code>](#Thread)\n        * [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>\n        * [.linkAddress([link])](#Box+linkAddress)\n        * [.removeAddressLink(address)](#Box+removeAddressLink)\n        * [.isAddressLinked([query])](#Box+isAddressLinked)\n        * [.listAddressLinks()](#Box+listAddressLinks) ⇒ <code>Array</code>\n        * [.logout()](#Box+logout)\n    * _static_\n        * [.idUtils](#Box.idUtils)\n            * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n            * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n            * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n        * [.create(provider, opts)](#Box.create) ⇒ [<code>Box</code>](#Box)\n        * [.get3idConnectProvider()](#Box.get3idConnectProvider) ⇒ <code>3IDProvider</code>\n        * [.openBox(address, provider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)\n        * [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>\n        * [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>\n\n<a name=\"new_Box_new\"></a>\n\n#### new Box()\nPlease use the **openBox** method to instantiate a 3Box\n\n<a name=\"Box+public\"></a>\n\n#### box.public\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the users 3Box |\n\n<a name=\"Box+private\"></a>\n\n#### box.private\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the users 3Box |\n\n<a name=\"Box+verified\"></a>\n\n#### box.verified\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| verified | [<code>Verified</code>](#Verified) | check and create verifications |\n\n<a name=\"Box+spaces\"></a>\n\n#### box.spaces\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |\n\n<a name=\"Box+syncDone\"></a>\n\n#### box.syncDone\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |\n\n<a name=\"Box+DID\"></a>\n\n#### box.DID\n**Kind**: instance property of [<code>Box</code>](#Box)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"Box+auth\"></a>\n\n#### box.auth(spaces, opts)\nAuthenticate the user\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| spaces | <code>Array.&lt;String&gt;</code> | A list of spaces to authenticate (optional) |\n| opts | <code>Object</code> | Optional parameters |\n| opts.address | <code>String</code> | An ethereum address |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n\n<a name=\"Box+openSpace\"></a>\n\n#### box.openSpace(name, opts) ⇒ [<code>Space</code>](#Space)\nOpens the space with the given name in the users 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Space</code>](#Space) - the Space instance for the given space name  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the space |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.onSyncDone | <code>function</code> | A function that will be called when the space has finished syncing with the pinning node |\n\n<a name=\"Box+openThread\"></a>\n\n#### box.openThread(space, name, opts) ⇒ [<code>Thread</code>](#Thread)\nOpen a thread. Use this to start receiving updates\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space for this thread |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Box+onSyncDone\"></a>\n\n#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>\nSets the callback function that will be called once when the box is fully synced.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>function</code> | The function that will be called |\n\n<a name=\"Box+linkAddress\"></a>\n\n#### box.linkAddress([link])\nCreates a proof that links an ethereum address to the 3Box account of the user. If given proof, it will simply be added to the root store.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [link] | <code>Object</code> | Optional link object with type or proof |\n| [link.proof] | <code>Object</code> | Proof object, should follow [spec](https://github.com/3box/3box/blob/master/3IPs/3ip-5.md) |\n\n<a name=\"Box+removeAddressLink\"></a>\n\n#### box.removeAddressLink(address)\nRemove given address link, returns true if successful\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | address that is linked |\n\n<a name=\"Box+isAddressLinked\"></a>\n\n#### box.isAddressLinked([query])\nChecks if there is a proof that links an external account to the 3Box account of the user. If not params given and any link exists, returns true\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| [query] | <code>Object</code> | Optional object with address and/or type. |\n| [query.type] | <code>String</code> | Does the given type of link exist |\n| [query.address] | <code>String</code> | Is the given adressed linked |\n\n<a name=\"Box+listAddressLinks\"></a>\n\n#### box.listAddressLinks() ⇒ <code>Array</code>\nLists address links associated with this 3Box\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n**Returns**: <code>Array</code> - An array of link objects  \n<a name=\"Box+logout\"></a>\n\n#### box.logout()\nCloses the 3box instance and clears local cache. If you call this,\nusers will need to sign a consent message to log in the next time\nyou call openBox.\n\n**Kind**: instance method of [<code>Box</code>](#Box)  \n<a name=\"Box.idUtils\"></a>\n\n#### Box.idUtils\nA module to verify & validate claims\n\n**Kind**: static property of [<code>Box</code>](#Box)  \n\n* [.idUtils](#Box.idUtils)\n    * [.verifyClaim](#Box.idUtils.verifyClaim) ⇒ <code>Object</code>\n    * [.isSupportedDID(did)](#Box.idUtils.isSupportedDID) ⇒ <code>\\*</code> \\| <code>boolean</code>\n    * [.isClaim(claim, opts)](#Box.idUtils.isClaim) ⇒ <code>Promise.&lt;boolean&gt;</code>\n\n<a name=\"Box.idUtils.verifyClaim\"></a>\n\n##### idUtils.verifyClaim ⇒ <code>Object</code>\nVerify a claim and return its content.\nSee https://github.com/uport-project/did-jwt/ for more details.\n\n**Kind**: static property of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Object</code> - The validated claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the JWT's audience |\n\n<a name=\"Box.idUtils.isSupportedDID\"></a>\n\n##### idUtils.isSupportedDID(did) ⇒ <code>\\*</code> \\| <code>boolean</code>\nCheck whether a string is a muport did or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>\\*</code> \\| <code>boolean</code> - Whether the did is a supported did or not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| did | <code>String</code> | A string containing a user did |\n\n<a name=\"Box.idUtils.isClaim\"></a>\n\n##### idUtils.isClaim(claim, opts) ⇒ <code>Promise.&lt;boolean&gt;</code>\nCheck whether a string is a valid claim or not\n\n**Kind**: static method of [<code>idUtils</code>](#Box.idUtils)  \n**Returns**: <code>Promise.&lt;boolean&gt;</code> - whether the parameter is an actual claim  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> |  |\n| opts | <code>Object</code> | Optional parameters |\n| opts.audience | <code>string</code> | The DID of the audience of the JWT |\n\n<a name=\"Box.create\"></a>\n\n#### Box.create(provider, opts) ⇒ [<code>Box</code>](#Box)\nCreates an instance of 3Box\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box session instance  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| provider | <code>provider</code> | A 3ID provider, or ethereum provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n\n<a name=\"Box.get3idConnectProvider\"></a>\n\n#### Box.get3idConnectProvider() ⇒ <code>3IDProvider</code>\nReturns and 3ID Connect Provider to manage keys, authentication and account links. Becomes default in future.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>3IDProvider</code> - Promise that resolves to a 3ID Connect Provider  \n<a name=\"Box.openBox\"></a>\n\n#### Box.openBox(address, provider, opts) ⇒ [<code>Box</code>](#Box)\nOpens the 3Box associated with the given address\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| provider | <code>provider</code> | An ethereum or 3ID provider |\n| opts | <code>Object</code> | Optional parameters |\n| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |\n| opts.pinningNode | <code>String</code> | A string with an ipfs multi-address to a 3box pinning node |\n| opts.ipfs | <code>Object</code> | A js-ipfs ipfs object |\n| opts.addressServer | <code>String</code> | URL of the Address Server |\n| opts.contentSignature | <code>String</code> | A signature, provided by a client of 3box using the private keys associated with the given address, of the 3box consent message |\n\n<a name=\"Box.isLoggedIn\"></a>\n\n#### Box.isLoggedIn(address) ⇒ <code>Boolean</code>\nCheck if the given address is logged in\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>Boolean</code> - true if the user is logged in  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n\n<a name=\"Box.getIPFS\"></a>\n\n#### Box.getIPFS() ⇒ <code>IPFS</code>\nInstanciate ipfs used by 3Box without calling openBox.\n\n**Kind**: static method of [<code>Box</code>](#Box)  \n**Returns**: <code>IPFS</code> - the ipfs instance  \n<a name=\"BoxApi\"></a>\n\n### BoxApi\n**Kind**: global class  \n\n* [BoxApi](#BoxApi)\n    * [.listSpaces(address, opts)](#BoxApi.listSpaces) ⇒ <code>Object</code>\n    * [.getSpace(address, name, opts)](#BoxApi.getSpace) ⇒ <code>Object</code>\n    * [.getThread(space, name, firstModerator, members, opts)](#BoxApi.getThread) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getThreadByAddress(address, opts)](#BoxApi.getThreadByAddress) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getConfig(address, opts)](#BoxApi.getConfig) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.getProfile(address, opts)](#BoxApi.getProfile) ⇒ <code>Object</code>\n    * [.getProfiles(address, opts)](#BoxApi.getProfiles) ⇒ <code>Object</code>\n    * [.profileGraphQL(query, opts)](#BoxApi.profileGraphQL) ⇒ <code>Object</code>\n    * [.getVerifiedAccounts(profile)](#BoxApi.getVerifiedAccounts) ⇒ <code>Object</code>\n\n<a name=\"BoxApi.listSpaces\"></a>\n\n#### BoxApi.listSpaces(address, opts) ⇒ <code>Object</code>\nGet the names of all spaces a user has\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - an array with all spaces as strings  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getSpace\"></a>\n\n#### BoxApi.getSpace(address, name, opts) ⇒ <code>Object</code>\nGet the public data in a space of a given address with the given name\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the public space data  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| name | <code>String</code> | A space name |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThread\"></a>\n\n#### BoxApi.getThread(space, name, firstModerator, members, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| space | <code>String</code> | The name of the space the thread is in |\n| name | <code>String</code> | The name of the thread |\n| firstModerator | <code>String</code> | The DID (or ethereum address) of the first moderator |\n| members | <code>Boolean</code> | True if only members are allowed to post |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getThreadByAddress\"></a>\n\n#### BoxApi.getThreadByAddress(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet all posts that are made to a thread.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The orbitdb-address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getConfig\"></a>\n\n#### BoxApi.getConfig(address, opts) ⇒ <code>Array.&lt;Object&gt;</code>\nGet the configuration of a users 3Box\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - An array of posts  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfile\"></a>\n\n#### BoxApi.getProfile(address, opts) ⇒ <code>Object</code>\nGet the public profile of a given address\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with the profile for the given address  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | An ethereum address |\n| opts | <code>Object</code> | Optional parameters |\n| opts.blocklist | <code>function</code> | A function that takes an address and returns true if the user has been blocked |\n| opts.metadata | <code>String</code> | flag to retrieve metadata |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.getProfiles\"></a>\n\n#### BoxApi.getProfiles(address, opts) ⇒ <code>Object</code>\nGet a list of public profiles for given addresses. This relies on 3Box profile API.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>Array</code> | An array of ethereum addresses |\n| opts | <code>Object</code> | Optional parameters |\n| opts.profileServer | <code>String</code> | URL of Profile API server |\n\n<a name=\"BoxApi.profileGraphQL\"></a>\n\n#### BoxApi.profileGraphQL(query, opts) ⇒ <code>Object</code>\nGraphQL for 3Box profile API\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - a json object with each key an address and value the profile  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| query | <code>Object</code> | A graphQL query object. |\n| opts | <code>Object</code> | Optional parameters |\n| opts.graphqlServer | <code>String</code> | URL of graphQL 3Box profile service |\n\n<a name=\"BoxApi.getVerifiedAccounts\"></a>\n\n#### BoxApi.getVerifiedAccounts(profile) ⇒ <code>Object</code>\nVerifies the proofs of social accounts that is present in the profile.\n\n**Kind**: static method of [<code>BoxApi</code>](#BoxApi)  \n**Returns**: <code>Object</code> - An object containing the accounts that have been verified  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| profile | <code>Object</code> | A user profile object, received from the `getProfile` function |\n\n<a name=\"KeyValueStore\"></a>\n\n### KeyValueStore\n**Kind**: global class  \n\n* [KeyValueStore](#KeyValueStore)\n    * [new KeyValueStore()](#new_KeyValueStore_new)\n    * [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \\| <code>Object</code>\n    * [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>\n    * [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>\n    * [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>\n    * [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>\n    * [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\n    * [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>\n\n<a name=\"new_KeyValueStore_new\"></a>\n\n#### new KeyValueStore()\nPlease use **box.public** or **box.private** to get the instance of this class\n\n<a name=\"KeyValueStore+get\"></a>\n\n#### keyValueStore.get(key, opts) ⇒ <code>String</code> \\| <code>Object</code>\nGet the value and optionally metadata of the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>String</code> \\| <code>Object</code> - the value associated with the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both value and metadata |\n\n<a name=\"KeyValueStore+getMetadata\"></a>\n\n#### keyValueStore.getMetadata(key) ⇒ <code>Metadata</code>\nGet metadata for for a given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Metadata</code> - Metadata for the key, undefined if there's no such key  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+set\"></a>\n\n#### keyValueStore.set(key, value) ⇒ <code>Boolean</code>\nSet a value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n| value | <code>String</code> | the value |\n\n<a name=\"KeyValueStore+setMultiple\"></a>\n\n#### keyValueStore.setMultiple(keys, values) ⇒ <code>Boolean</code>\nSet multiple values for multiple keys\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful, throw error if not  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| keys | <code>Array.&lt;String&gt;</code> | the keys |\n| values | <code>Array.&lt;String&gt;</code> | the values |\n\n<a name=\"KeyValueStore+remove\"></a>\n\n#### keyValueStore.remove(key) ⇒ <code>Boolean</code>\nRemove the value for the given key\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Boolean</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| key | <code>String</code> | the key |\n\n<a name=\"KeyValueStore+all\"></a>\n\n#### keyValueStore.all(opts) ⇒ <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code>\nGet all values and optionally metadata\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;(String\\|{value: String, timestamp: Number})&gt;</code> - the values  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | optional parameters |\n| opts.metadata | <code>Boolean</code> | return both values and metadata |\n\n<a name=\"KeyValueStore+log\"></a>\n\n#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>\nReturns array of underlying log entries. In linearized order according to their Lamport clocks.\nUseful for generating a complete history of all operations on store.\n\n**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects  \n**Example**  \n```js\nconst log = store.log\n const entry = log[0]\n console.log(entry)\n // { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }\n```\n<a name=\"User\"></a>\n\n### User\nClass representing a user.\n\n**Kind**: global class  \n\n* [User](#User)\n    * [.DID](#User+DID)\n    * [.signClaim(payload, opts)](#User+signClaim) ⇒ <code>String</code>\n    * [.encrypt(message, opts, to)](#User+encrypt) ⇒ <code>Object</code>\n    * [.decrypt(encryptedObject)](#User+decrypt) ⇒ <code>String</code>\n\n<a name=\"User+DID\"></a>\n\n#### user.DID\n**Kind**: instance property of [<code>User</code>](#User)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| DID | <code>String</code> | the DID of the user |\n\n<a name=\"User+signClaim\"></a>\n\n#### user.signClaim(payload, opts) ⇒ <code>String</code>\nSign a JWT claim\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The signed JWT  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| payload | <code>Object</code> | The payload to sign |\n| opts | <code>Object</code> | Optional parameters |\n\n<a name=\"User+encrypt\"></a>\n\n#### user.encrypt(message, opts, to) ⇒ <code>Object</code>\nEncrypt a message. By default encrypts messages symmetrically\nwith the users private key. If the `to` parameter is used,\nthe message will be asymmetrically encrypted to the recipient.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>Object</code> - An object containing the encrypted payload  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>String</code> | The message to encrypt |\n| opts | <code>Object</code> | Optional parameters |\n| to | <code>String</code> | The receiver of the message, a DID or an ethereum address |\n\n<a name=\"User+decrypt\"></a>\n\n#### user.decrypt(encryptedObject) ⇒ <code>String</code>\nDecrypts a message if the user owns the correct key to decrypt it.\n\n**Kind**: instance method of [<code>User</code>](#User)  \n**Returns**: <code>String</code> - The clear text message  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| encryptedObject | <code>Object</code> | The encrypted message to decrypt (as encoded by the `encrypt` method |\n\n<a name=\"Space\"></a>\n\n### Space\n**Kind**: global class  \n\n* [Space](#Space)\n    * [new Space()](#new_Space_new)\n    * [.public](#Space+public)\n    * [.private](#Space+private)\n    * [.syncDone](#Space+syncDone)\n    * [.user](#Space+user)\n    * [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.createConfidentialThread(name)](#Space+createConfidentialThread) ⇒ [<code>Thread</code>](#Thread)\n    * [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)\n    * [.subscribeThread(address, config)](#Space+subscribeThread)\n    * [.unsubscribeThread(address)](#Space+unsubscribeThread)\n    * [.subscribedThreads()](#Space+subscribedThreads) ⇒ <code>Array.&lt;Objects&gt;</code>\n\n<a name=\"new_Space_new\"></a>\n\n#### new Space()\nPlease use **box.openSpace** to get the instance of this class\n\n<a name=\"Space+public\"></a>\n\n#### space.public\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| public | [<code>KeyValueStore</code>](#KeyValueStore) | access the profile store of the space |\n\n<a name=\"Space+private\"></a>\n\n#### space.private\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |\n\n<a name=\"Space+syncDone\"></a>\n\n#### space.syncDone\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| syncDone | <code>Promise</code> | A promise that is resolved when the space data is synced |\n\n<a name=\"Space+user\"></a>\n\n#### space.user\n**Kind**: instance property of [<code>Space</code>](#Space)  \n**Properties**\n\n| Name | Type | Description |\n| --- | --- | --- |\n| user | [<code>User</code>](#User) | access the user object to encrypt data and sign claims |\n\n<a name=\"Space+joinThread\"></a>\n\n#### space.joinThread(name, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.firstModerator | <code>String</code> | DID of first moderator of a thread, by default, user is first moderator |\n| opts.members | <code>Boolean</code> | join a members only thread, which only members can post in, defaults to open thread |\n| opts.confidential | <code>Boolean</code> | create a confidential thread with true or join existing confidential thread with an encKeyId string |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n| opts.ghost | <code>Boolean</code> | Enable ephemeral messaging via Ghost Thread |\n| opts.ghostBacklogLimit | <code>Number</code> | The number of posts to maintain in the ghost backlog |\n| opts.ghostFilters | <code>Array.&lt;function()&gt;</code> | Array of functions for filtering messages |\n\n<a name=\"Space+createConfidentialThread\"></a>\n\n#### space.createConfidentialThread(name) ⇒ [<code>Thread</code>](#Thread)\nCreate a confidential thread\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the created thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| name | <code>String</code> | The name of the thread |\n\n<a name=\"Space+joinThreadByAddress\"></a>\n\n#### space.joinThreadByAddress(address, opts) ⇒ [<code>Thread</code>](#Thread)\nJoin a thread by full thread address. Use this to start receiving updates from, and to post in threads\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: [<code>Thread</code>](#Thread) - An instance of the thread class for the joined thread  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The full address of the thread |\n| opts | <code>Object</code> | Optional parameters |\n| opts.noAutoSub | <code>Boolean</code> | Disable auto subscription to the thread when posting to it (default false) |\n\n<a name=\"Space+subscribeThread\"></a>\n\n#### space.subscribeThread(address, config)\nSubscribe to the given thread, if not already subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n| config | <code>Object</code> | configuration and thread meta data |\n| opts.name | <code>String</code> | Name of thread |\n| opts.firstModerator | <code>String</code> | DID of the first moderator |\n| opts.members | <code>String</code> | Boolean string, true if a members only thread |\n\n<a name=\"Space+unsubscribeThread\"></a>\n\n#### space.unsubscribeThread(address)\nUnsubscribe from the given thread, if subscribed\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| address | <code>String</code> | The address of the thread |\n\n<a name=\"Space+subscribedThreads\"></a>\n\n#### space.subscribedThreads() ⇒ <code>Array.&lt;Objects&gt;</code>\nGet a list of all the threads subscribed to in this space\n\n**Kind**: instance method of [<code>Space</code>](#Space)  \n**Returns**: <code>Array.&lt;Objects&gt;</code> - A list of thread objects as { address, firstModerator, members, name}  \n<a name=\"Thread\"></a>\n\n### Thread\n**Kind**: global class  \n\n* [Thread](#Thread)\n    * [new Thread()](#new_Thread_new)\n    * [.post(message)](#Thread+post) ⇒ <code>String</code>\n    * [.addModerator(id)](#Thread+addModerator)\n    * [.listModerators()](#Thread+listModerators) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.addMember(id)](#Thread+addMember)\n    * [.listMembers()](#Thread+listMembers) ⇒ <code>Array.&lt;String&gt;</code>\n    * [.deletePost(id)](#Thread+deletePost)\n    * [.getPosts(opts)](#Thread+getPosts) ⇒ <code>Array.&lt;Object&gt;</code>\n    * [.onUpdate(updateFn)](#Thread+onUpdate)\n    * [.onNewCapabilities(updateFn)](#Thread+onNewCapabilities)\n\n<a name=\"new_Thread_new\"></a>\n\n#### new Thread()\nPlease use **space.joinThread** to get the instance of this class\n\n<a name=\"Thread+post\"></a>\n\n#### thread.post(message) ⇒ <code>String</code>\nPost a message to the thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>String</code> - The postId of the new post  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| message | <code>Object</code> | The message |\n\n<a name=\"Thread+addModerator\"></a>\n\n#### thread.addModerator(id)\nAdd a moderator to this thread, throws error is user can not add a moderator\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+listModerators\"></a>\n\n#### thread.listModerators() ⇒ <code>Array.&lt;String&gt;</code>\nList moderators\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of moderator DIDs  \n<a name=\"Thread+addMember\"></a>\n\n#### thread.addMember(id)\nAdd a member to this thread, throws if user can not add member, throw is not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Member Id |\n\n<a name=\"Thread+listMembers\"></a>\n\n#### thread.listMembers() ⇒ <code>Array.&lt;String&gt;</code>\nList members, throws if not member thread\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;String&gt;</code> - Array of member DIDs  \n<a name=\"Thread+deletePost\"></a>\n\n#### thread.deletePost(id)\nDelete post\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| id | <code>String</code> | Moderator Id |\n\n<a name=\"Thread+getPosts\"></a>\n\n#### thread.getPosts(opts) ⇒ <code>Array.&lt;Object&gt;</code>\nReturns an array of posts, based on the options.\nIf hash not found when passing gt, gte, lt, or lte,\nthe iterator will return all items (respecting limit and reverse).\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n**Returns**: <code>Array.&lt;Object&gt;</code> - true if successful  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| opts | <code>Object</code> | Optional parameters |\n| opts.gt | <code>String</code> | Greater than, takes an postId |\n| opts.gte | <code>String</code> | Greater than or equal to, takes an postId |\n| opts.lt | <code>String</code> | Less than, takes an postId |\n| opts.lte | <code>String</code> | Less than or equal to, takes an postId |\n| opts.limit | <code>Integer</code> | Limiting the number of entries in result, defaults to -1 (no limit) |\n| opts.reverse | <code>Boolean</code> | If set to true will result in reversing the result |\n\n<a name=\"Thread+onUpdate\"></a>\n\n#### thread.onUpdate(updateFn)\nRegister a function to be called after new updates\nhave been received from the network or locally.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Thread+onNewCapabilities\"></a>\n\n#### thread.onNewCapabilities(updateFn)\nRegister a function to be called for every new\ncapability that is added to the thread access controller.\nThis inlcudes when a moderator or member is added.\nThe function takes one parameter, which is the capabilities obj, or\nyou can call listModerator / listMembers again instead.\n\n**Kind**: instance method of [<code>Thread</code>](#Thread)  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| updateFn | <code>function</code> | The function that will get called |\n\n<a name=\"Verified\"></a>\n\n### Verified\n**Kind**: global class  \n\n* [Verified](#Verified)\n    * [new Verified()](#new_Verified_new)\n    * [.DID()](#Verified+DID) ⇒ <code>String</code>\n    * [.github()](#Verified+github) ⇒ <code>Object</code>\n    * [.addGithub(gistUrl)](#Verified+addGithub) ⇒ <code>Object</code>\n    * [.twitter()](#Verified+twitter) ⇒ <code>Object</code>\n    * [.addTwitter(claim)](#Verified+addTwitter) ⇒ <code>Object</code>\n    * [.email()](#Verified+email) ⇒ <code>Object</code>\n    * [.addEmail(claim)](#Verified+addEmail) ⇒ <code>Object</code>\n\n<a name=\"new_Verified_new\"></a>\n\n#### new Verified()\nPlease use **box.verified** to get the instance of this class\n\n<a name=\"Verified+DID\"></a>\n\n#### verified.DID() ⇒ <code>String</code>\nReturns the verified DID of the user\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>String</code> - The DID of the user  \n<a name=\"Verified+github\"></a>\n\n#### verified.github() ⇒ <code>Object</code>\nVerifies that the user has a valid github account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n<a name=\"Verified+addGithub\"></a>\n\n#### verified.addGithub(gistUrl) ⇒ <code>Object</code>\nAdds a github verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, and proof  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| gistUrl | <code>Object</code> | URL of the proof |\n\n<a name=\"Verified+twitter\"></a>\n\n#### verified.twitter() ⇒ <code>Object</code>\nVerifies that the user has a valid twitter account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addTwitter\"></a>\n\n#### verified.addTwitter(claim) ⇒ <code>Object</code>\nAdds a twitter verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of a twitter username |\n\n<a name=\"Verified+email\"></a>\n\n#### verified.email() ⇒ <code>Object</code>\nVerifies that the user has a verified email account\nThrows an error otherwise.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n<a name=\"Verified+addEmail\"></a>\n\n#### verified.addEmail(claim) ⇒ <code>Object</code>\nAdds an email verification to the users profile\nThrows an error if the verification fails.\n\n**Kind**: instance method of [<code>Verified</code>](#Verified)  \n**Returns**: <code>Object</code> - Object containing username, proof, and the verifier  \n\n| Param | Type | Description |\n| --- | --- | --- |\n| claim | <code>String</code> | A did-JWT claim ownership of an email username |\n\n","readmeFilename":"README.md"}