Skip to content
This repository has been archived by the owner on Aug 9, 2021. It is now read-only.

Commit

Permalink
Merge pull request #605 from 3box/release/1.11.0
Browse files Browse the repository at this point in the history
Release/1.11.0
  • Loading branch information
oed authored Sep 26, 2019
2 parents a6af9ad + 66a5e7c commit cb2c477
Show file tree
Hide file tree
Showing 34 changed files with 3,134 additions and 2,511 deletions.
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ jobs:
name: install dependencies
command: |
sudo npm i -g codecov node-gyp
npm i
npm ci
- run:
name: test
Expand Down
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ coverage/
tmp/
.js-ipfs
yarn.lock
orbitdb
83 changes: 58 additions & 25 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,10 +60,13 @@ const box = await Box.openBox('0x12345abcde', ethereumProvider)
```

#### 2. Sync user's available 3Box data from the network
When 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!
When 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:
```js
box.onSyncDone(yourCallbackFunction)
await box.syncDone
```
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 the sync is finished!

If you prefer to not use promises you can add a callback using the `onSyncDone` method.

#### 3. Interact with 3Box profile data
You 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`.
Expand Down Expand Up @@ -141,6 +144,12 @@ A space is a named section of a users 3Box. Each space has both a public and a p
const space = await box.openSpace('narwhal')
```

#### Sync user's available space data from the network
Similarly 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:
```js
await space.syncDone
```

#### Get, set, and remove space data
Interacting 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:
```js
Expand Down Expand Up @@ -226,9 +235,10 @@ thread.onNewCapabilities(myCallbackFunction)

## <a name="example"></a> Example Application

You 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:
You 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:

```bash
$ npm ci
$ npm run example:start
```

Expand Down Expand Up @@ -284,9 +294,10 @@ idUtils.verifyClaim(claim)
* [.private](#Box+private)
* [.verified](#Box+verified)
* [.spaces](#Box+spaces)
* [.syncDone](#Box+syncDone)
* [.DID](#Box+DID)
* [.openSpace(name, opts)](#Box+openSpace) ⇒ [<code>Space</code>](#Space)
* [.onSyncDone(syncDone)](#Box+onSyncDone)
* [.onSyncDone(syncDone)](#Box+onSyncDone) ⇒ <code>Promise</code>
* [.linkAddress([link])](#Box+linkAddress)
* [.removeAddressLink(address)](#Box+removeAddressLink)
* [.isAddressLinked([query])](#Box+isAddressLinked)
Expand All @@ -306,7 +317,7 @@ idUtils.verifyClaim(claim)
* [.listSpaces(address, opts)](#Box.listSpaces) ⇒ <code>Object</code>
* [.profileGraphQL(query, opts)](#Box.profileGraphQL) ⇒ <code>Object</code>
* [.getVerifiedAccounts(profile)](#Box.getVerifiedAccounts) ⇒ <code>Object</code>
* [.openBox(address, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)
* [.openBox(addrOrIdW, ethereumProvider, opts)](#Box.openBox) ⇒ [<code>Box</code>](#Box)
* [.isLoggedIn(address)](#Box.isLoggedIn) ⇒ <code>Boolean</code>
* [.getIPFS()](#Box.getIPFS) ⇒ <code>IPFS</code>
Expand Down Expand Up @@ -355,6 +366,16 @@ Please use the **openBox** method to instantiate a 3Box
| --- | --- | --- |
| spaces | <code>Object</code> | an object containing all open spaces indexed by their name. |
<a name="Box+syncDone"></a>
#### box.syncDone
**Kind**: instance property of [<code>Box</code>](#Box)
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |
<a name="Box+DID"></a>
#### box.DID
Expand Down Expand Up @@ -382,10 +403,11 @@ Opens the space with the given name in the users 3Box
<a name="Box+onSyncDone"></a>
#### box.onSyncDone(syncDone)
Sets the callback function that will be called once when the db is fully synced.
#### box.onSyncDone(syncDone) ⇒ <code>Promise</code>
Sets the callback function that will be called once when the box is fully synced.
**Kind**: instance method of [<code>Box</code>](#Box)
**Returns**: <code>Promise</code> - A promise that is fulfilled when the box is syned
| Param | Type | Description |
| --- | --- | --- |
Expand Down Expand Up @@ -633,15 +655,15 @@ Verifies the proofs of social accounts that is present in the profile.
<a name="Box.openBox"></a>
#### Box.openBox(address, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)
#### Box.openBox(addrOrIdW, ethereumProvider, opts) ⇒ [<code>Box</code>](#Box)
Opens the 3Box associated with the given address
**Kind**: static method of [<code>Box</code>](#Box)
**Returns**: [<code>Box</code>](#Box) - the 3Box instance for the given address
| Param | Type | Description |
| --- | --- | --- |
| address | <code>String</code> | An ethereum address |
| addrOrIdW | <code>String</code> \| <code>IdentityWallet</code> | An ethereum address, or [IdentityWallet](https://github.com/3box/identity-wallet-js/) instance |
| ethereumProvider | <code>ethereumProvider</code> | An ethereum provider |
| opts | <code>Object</code> | Optional parameters |
| opts.consentCallback | <code>function</code> | A function that will be called when the user has consented to opening the box |
Expand Down Expand Up @@ -676,34 +698,19 @@ Instanciate ipfs used by 3Box without calling openBox.
* [KeyValueStore](#KeyValueStore)
* [new KeyValueStore()](#new_KeyValueStore_new)
* [.log](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>
* [.get(key, opts)](#KeyValueStore+get) ⇒ <code>String</code> \| <code>Object</code>
* [.getMetadata(key)](#KeyValueStore+getMetadata) ⇒ <code>Metadata</code>
* [.set(key, value)](#KeyValueStore+set) ⇒ <code>Boolean</code>
* [.setMultiple(keys, values)](#KeyValueStore+setMultiple) ⇒ <code>Boolean</code>
* [.remove(key)](#KeyValueStore+remove) ⇒ <code>Boolean</code>
* [.all(opts)](#KeyValueStore+all) ⇒ <code>Array.&lt;(String\|{value: String, timestamp: Number})&gt;</code>
* [.log()](#KeyValueStore+log) ⇒ <code>Array.&lt;Object&gt;</code>
<a name="new_KeyValueStore_new"></a>
#### new KeyValueStore()
Please use **box.public** or **box.private** to get the instance of this class
<a name="KeyValueStore+log"></a>
#### keyValueStore.log ⇒ <code>Array.&lt;Object&gt;</code>
Returns array of underlying log entries. In linearized order according to their Lamport clocks.
Useful for generating a complete history of all operations on store.
**Kind**: instance property of [<code>KeyValueStore</code>](#KeyValueStore)
**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects
**Example**
```js
const log = store.log
const entry = log[0]
console.log(entry)
// { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }
```
<a name="KeyValueStore+get"></a>
#### keyValueStore.get(key, opts) ⇒ <code>String</code> \| <code>Object</code>
Expand Down Expand Up @@ -781,6 +788,21 @@ Get all values and optionally metadata
| opts | <code>Object</code> | optional parameters |
| opts.metadata | <code>Boolean</code> | return both values and metadata |
<a name="KeyValueStore+log"></a>
#### keyValueStore.log() ⇒ <code>Array.&lt;Object&gt;</code>
Returns array of underlying log entries. In linearized order according to their Lamport clocks.
Useful for generating a complete history of all operations on store.
**Kind**: instance method of [<code>KeyValueStore</code>](#KeyValueStore)
**Returns**: <code>Array.&lt;Object&gt;</code> - Array of ordered log entry objects
**Example**
```js
const log = store.log
const entry = log[0]
console.log(entry)
// { op: 'PUT', key: 'Name', value: 'Botbot', timeStamp: '1538575416068' }
```
<a name="Space"></a>
### Space
Expand All @@ -790,6 +812,7 @@ Get all values and optionally metadata
* [new Space()](#new_Space_new)
* [.public](#Space+public)
* [.private](#Space+private)
* [.syncDone](#Space+syncDone)
* [.DID](#Space+DID)
* [.joinThread(name, opts)](#Space+joinThread) ⇒ [<code>Thread</code>](#Thread)
* [.joinThreadByAddress(address, opts)](#Space+joinThreadByAddress) ⇒ [<code>Thread</code>](#Thread)
Expand Down Expand Up @@ -822,6 +845,16 @@ Please use **box.openSpace** to get the instance of this class
| --- | --- | --- |
| private | [<code>KeyValueStore</code>](#KeyValueStore) | access the private store of the space |
<a name="Space+syncDone"></a>
#### space.syncDone
**Kind**: instance property of [<code>Space</code>](#Space)
**Properties**
| Name | Type | Description |
| --- | --- | --- |
| syncDone | <code>Promise</code> | A promise that is resolved when the box is synced |
<a name="Space+DID"></a>
#### space.DID
Expand Down
13 changes: 13 additions & 0 deletions RELEASE-NOTES.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
# Release Notes

## v1.11.0 - 2019-09-24
* feat: 3box instance can now be created with an instance of the IdentityWallet
* feat: smarter data syncing logic
* feat: support erc1271 address links (your contract wallet can now have a 3Box!)
* feat: verify link proofs added by the `linkAddress` method

* fix: sync rootstore before resolving promise from openBox

### Updated data sync api
To wait for the data to be fully synced from the network you can now simply await these publicly exposed promises:
* `await box.syncDone` - for the main data storage
* `await space.syncDone` - for data in the given space

## v1.10.10 - 2019-09-12
* feat: add method to get ipfs instance without openBox

Expand Down
19 changes: 19 additions & 0 deletions example/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,25 @@

<div id="controlls" style="display: none; padding: 5px 100px;">

<div style="padding: 0px 0px 25px 0px;">
<h2> Identity </h2>
<h5 style="padding: 20px 0px 10px 0px"> DID: </h5>
<p>
<span id="didInfo"></span>
</p>

<h3> Address Links </h3>
<p>
<span id="addressLinks"></span>
</p>

<h5> Current address linked? </h5>
<p>
<span id="addressLinked"></span>
</p>
<button id="linkAddress" type="button" class="btn btn-primary">Link address</button>
</div>

<!-- Public Store Div -->
<div style="padding: 0px 0px 25px 0px;">
<h2> Public Store </h2>
Expand Down
30 changes: 28 additions & 2 deletions example/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,11 @@ bopen.addEventListener('click', event => {

controlls.style.display = 'block'
updateProfileData(box)
updateLinksData(box, addresses[0])

linkAddress.addEventListener('click', () => {
box.linkAddress().then(() => { updateLinksData(box, addresses[0]) })
})

setProfile.addEventListener('click', () => {
box.public.set(prkey.value, prvalue.value).then(() => {
Expand Down Expand Up @@ -206,12 +211,13 @@ profileGraphQL.addEventListener('click', () => {
})

function updateProfileData(box) {
profileData.innerHTML = ''
box.public.all().then(profile => {
console.log(profile)
let tmpData = ''
Object.entries(profile).map(kv => {
profileData.innerHTML += kv[0] + ': ' + kv[1] + '<br />'
tmpData += kv[0] + ': ' + kv[1] + '<br />'
})
profileData.innerHTML = tmpData
})
updateGithubUser(box)
}
Expand All @@ -238,3 +244,23 @@ function updateGithubUser (box) {
githubUser.innerHTML = error
})
}

function updateLinksData (box, address) {
didInfo.innerHTML = box.DID

addressLinks.innerHTML = ''
box.listAddressLinks().then(links => {
links.forEach((link, index) => {
addressLinks.innerHTML += `<b>${index + 1})</b> ${new Date(link.timestamp * 1000).toLocaleString()}
<br><b>LinkID: </b>${link.linkId}
<br><b>Address: </b>${link.address}
<br><b>Type: </b>${link.type}
<br><br>`
})
})

box.isAddressLinked({ address }).then(result => {
addressLinked.innerHTML = result ? 'Yes' : 'No'
linkAddress.style.display = result ? 'none' : 'block'
})
}
Loading

0 comments on commit cb2c477

Please sign in to comment.