diff --git a/src/common/_includes/architecture.md b/src/common/_includes/architecture.md index 0239b6de..2d88f1c0 100644 --- a/src/common/_includes/architecture.md +++ b/src/common/_includes/architecture.md @@ -1,16 +1,15 @@ - ![Blockstack Architecture](/common/images/architecture.png) Blockchains require consensus among large numbers of people, so they can be slow. Additionally, a blockchain is not designed to hold a lot of data. This means using a blockchain for every bit of data a user might write and store is expensive. For example, imagine if an application were storing every tweet in the chain. -Blockstack addresses blockchain performance problems using a layered approach. The base layer consists of the Stacks blockchain and the Blockstack Naming System (BNS). The blockchain governs ownership of identities in the Blockstack network. Identities can be names such as domain names, usernames, or application names. +Blockstack addresses blockchain performance problems using a layered approach. The base layer consists of the Stacks blockchain and the Blockstack Naming System (BNS). The blockchain governs ownership of identities in the Blockstack network. Identities can be names such as domain names, usernames, or application names. -When an identity is created, its creation is recorded in the Stacks blockchain. Identities make up the primary data stored into the Stacks blockchain. These identities correspond to routing data in the OSI stack. The routing data is stored in the Atlas Peer Network, the second layer. Every core node that joins the Blockstack Network is able to obtain an entire copy of this routing data. Blockstack uses the routing data to associate identities (domain names, user names, and application names) with a particular storage location in the final layer, the Gaia Storage System. +When an identity is created, its creation is recorded in the Stacks blockchain. Identities make up the primary data stored into the Stacks blockchain. These identities correspond to routing data in the OSI stack. The routing data is stored in the Atlas Peer Network, the second layer. Every core node that joins the Blockstack Network is able to obtain an entire copy of this routing data. Blockstack uses the routing data to associate identities (domain names, user names, and application names) with a particular storage location in the final layer, the Gaia Storage System. -A Gaia Storage System consists of a _hub service_ and storage resource on a cloud software provider. The storage provider can be any commercial provider such as Azure, DigitalOcean, Amazon EC2, and so forth. Typically the compute resource and the storage resource reside same cloud vendor, though this is not a requirement. Gaia currently has driver support for S3 and Azure Blob Storage, but the driver model allows for other backend support as well. +A Gaia Storage System consists of a _hub service_ and storage resource on a cloud software provider. The storage provider can be any commercial provider such as Azure, DigitalOcean, Amazon EC2, and so forth. Typically the compute resource and the storage resource reside same cloud vendor, though this is not a requirement. Gaia currently has driver support for S3 and Azure Blob Storage, but the driver model allows for other backend support as well. -Gaia stores data as a simple key-value store. When an identity is created, a corresponding data store is associated with that identity on Gaia. When a user logs into a dApp, +Gaia stores data as a simple key-value store. When an identity is created, a corresponding data store is associated with that identity on Gaia. When a user logs into a dApp, the authentication process gives the application the URL of a Gaia hub, which then writes to storage on behalf of that user. -Within Blockstack, then, the Stacks blockchain stores only identity data. Data created by the actions of an identity is stored in a Gaia Storage System. Each user has profile data. When a user interacts with a decentralized dApp that application stores application data on behalf of the user. Because Gaia stores user and application data off the blockchain, a Blockstack DApp is typically more performant than DApps created on other blockchains. +Within Blockstack, then, the Stacks blockchain stores only identity data. Data created by the actions of an identity is stored in a Gaia Storage System. Each user has profile data. When a user interacts with a decentralized dApp that application stores application data on behalf of the user. Because Gaia stores user and application data off the blockchain, a Blockstack DApp is typically more performant than DApps created on other blockchains. diff --git a/src/common/_includes/commandline.md b/src/common/_includes/commandline.md index 75cd55df..c6707f74 100644 --- a/src/common/_includes/commandline.md +++ b/src/common/_includes/commandline.md @@ -1,31 +1,31 @@ - The command line is intended for developers only. Developers can use the command line to test and debug Blockstack applications in ways that the Blockstack Browser does not yet support. Using the command line, developers can: -* Generate and Broadcast all supported types of Blockstack transactions -* Load, store, and list data in Gaia hubs -* Generate owner, payment and application keys from a seed phrase -* Query Stacks Nodes -* Implement a minimum viable authentication flow +- Generate and Broadcast all supported types of Blockstack transactions +- Load, store, and list data in Gaia hubs +- Generate owner, payment and application keys from a seed phrase +- Query Stacks Nodes +- Implement a minimum viable authentication flow {% include warning.html content="Many of the commands operate on unencrypted private keys. For this reason, DO NOT use this tool for day-to-day tasks as you risk the security of your keys." %} You must install the command line before you -can use the commands. +can use the commands. ## List of commands + {:.no_toc} To see the usage and options for the command in general, enter `blockstack-cli` without any subcommands. To see a list of subcommands enter `blockstack-cli help`. Enter `blockstack-cli SUBCOMMAND_NAME help` to see a subcommand with its usage. The following are the available subcommands: -* TOC -{:toc} - +- TOC + {:toc} {% for entry in site.data.cliRef %} + ## {{ entry.command }} **Group**: {{ entry.group }} @@ -33,6 +33,7 @@ To see the usage and options for the command in general, enter `blockstack-cli` {{ entry.usage }} ### Arguments + {:.no_toc}
{{ arg.format }} |
- {% endfor %}
+{% endfor %}
+
Collection
type shares the same identifier as another type, it will lead to data corruption for the user. In the future, the Blockstack platform will enforce unique collection names. " %}
+ {% include warning.html content="While you must specify a unique identifier, the Blockstack platform does not currently enforce uniqueness. If your Collection
type shares the same identifier as another type, it will lead to data corruption for the user. In the future, the Blockstack platform will enforce unique collection names. " %}
5. Define a static `schema` constant.
This is your type's schema.
- ```js
- static schema = {
- identifier: String,
- firstName: String,
- lastName: String,
- blockstackID: String,
- email: String,
- website: String,
- address: String,
- telephone: String,
- organization: String
- }
- ```
+ ```js
+ static schema = {
+ identifier: String,
+ firstName: String,
+ lastName: String,
+ blockstackID: String,
+ email: String,
+ website: String,
+ address: String,
+ telephone: String,
+ organization: String
+ }
+ ```
6. Determine if you need to set the `singleFile` storage flag.
- By default, the `singleFile` flag is false. This setting causes every record in a collection to store in Gaia as a separate file. The default works well for larger types that describe data such as documents or photos. If your `Collection` type only has a few fields and is not expected to have a large number of records, set the `singleFile` data format flag to `true`.
+ By default, the `singleFile` flag is false. This setting causes every record in a collection to store in Gaia as a separate file. The default works well for larger types that describe data such as documents or photos. If your `Collection` type only has a few fields and is not expected to have a large number of records, set the `singleFile` data format flag to `true`.
- ```js
- static singleFile = true
- ```
+ ```js
+ static singleFile = true
+ ```
7. Define the `fromObject` and `fromData` serializaiton methods.
- These methods serialize and deserialize your `Collection` type. You can use any serialization method you want. Data encryption is handled automatically by the parent `Collection` class, so you *should not* perform any additional encryption.
+ These methods serialize and deserialize your `Collection` type. You can use any serialization method you want. Data encryption is handled automatically by the parent `Collection` class, so you _should not_ perform any additional encryption.
In the following example code, data is converted to JSON string for storage.
- ```js
- static fromObject(object: object) {
- // Create from plain Javascript object
- return new Contact(object)
- }
- static fromData(data: string) {
- // Deserialize JSON data
- return new Contact(JSON.parse(data))
- }
-
- serialize() {
- // Serialize to JSON string
- return JSON.stringify(this.attrs)
- }
- ```
+ ```js
+ static fromObject(object: object) {
+ // Create from plain Javascript object
+ return new Contact(object)
+ }
+ static fromData(data: string) {
+ // Deserialize JSON data
+ return new Contact(JSON.parse(data))
+ }
+
+ serialize() {
+ // Serialize to JSON string
+ return JSON.stringify(this.attrs)
+ }
+ ```
8. Test and iterate development of your type in your application.
9. Publish your type for others to use.
@@ -144,7 +144,7 @@ To perform additional processing of a collection, you can override the `get`, `s
## Publish your new type for others to use
-While you *can* use your collection exclusively in your application, the Collections feature is intended to enable data portability between DApps. So, you should publish your new type so other developers can make use of it.
+While you _can_ use your collection exclusively in your application, the Collections feature is intended to enable data portability between DApps. So, you should publish your new type so other developers can make use of it.
To publish your Collection type, do the following:
diff --git a/src/pages/develop/collections.md b/src/pages/develop/collections.md
index 9ded4333..c96c1a2b 100644
--- a/src/pages/develop/collections.md
+++ b/src/pages/develop/collections.md
@@ -1,8 +1,8 @@
---
-
-
---
+
# Work with Collections (Preview)
+
Collections is the feature designed to make data portable among Blockstack applications. Sharing is accomplished by storing a user's data in a standardized format at a known, Gaia storage location. Collections associate user data with a user's decentralized ID. When users move among apps, the same data is available to each application the user authorizes.
On this page, you learn what collections are and how to use them. You'll learn about the `Contact` collection in particular. The following topics are covered:
@@ -11,7 +11,7 @@ On this page, you learn what collections are and how to use them. You'll learn a
## Understand how collections work
-One of Blockstack's goals is to give users true data ownership by enabling *data portability*. Data portability allows users to login with their digital ID on any app and have access to the same data. For example, if a user adds a photo of a Hawaiian vacation in one app, that photo enters the user's data pool. Then, when the user opens a second app, that same photo is available to the second app because the user data, including the photo, is shared via the user's decentralized ID.
+One of Blockstack's goals is to give users true data ownership by enabling _data portability_. Data portability allows users to login with their digital ID on any app and have access to the same data. For example, if a user adds a photo of a Hawaiian vacation in one app, that photo enters the user's data pool. Then, when the user opens a second app, that same photo is available to the second app because the user data, including the photo, is shared via the user's decentralized ID.
How do collections work? Blockstack builds a library containing commonly used data schemes. Developers use these classes and objects instead of creating their own, unique data schemes. Using a class from the collections library guarantees class data is stored in Gaia in that format; And, when retrieved, guarantees the same format is returned. This pre-release provides the `Contact` collection. A contact schema produces this structure:
@@ -65,28 +65,28 @@ If you have `npm` installed, do the following to run the Contact Manager demo ap
7. Install the dependencies using `npm`.
- ```bash
- npm install
- ```
+ ```bash
+ npm install
+ ```
8. Start the application running.
- ```bash
- npm run start
- ```
+ ```bash
+ npm run start
+ ```
- The system starts the application and launches it in your browser at 127.0.0.1:3000
+ The system starts the application and launches it in your browser at 127.0.0.1:3000
9. Choose **Sign In with Blockstack**.
- The internet browser will display this pop-up
+ The internet browser will display this pop-up
- ![](images/contacts-manager.png)
+ ![](images/contacts-manager.png)
-10. Use the local browser by choosing **Open Blockstack.app**.
+10. Use the local browser by choosing **Open Blockstack.app**.
11. If you are not signed into an ID in the Blockstack Browser, choose **Create new ID** from the pop up.
- If you are already signed in, choose an ID to sign in to the Contacts Manager app with.
+ If you are already signed in, choose an ID to sign in to the Contacts Manager app with.
The system should return you to the Contact Manager demo application.
@@ -108,7 +108,6 @@ If you have `npm` installed, do the following to run the Contact Manager demo ap
![](images/test-contact.png)
-
## How to add the Contact collections to your DApp
In this section, you learn how to add `Contact` collection functionality to an existing application. Before beginning, make sure your application is using Blockstack auth and is storing data with Gaia. To start using the `Contact` collection in your Blockstack app, do the following:
@@ -116,35 +115,35 @@ In this section, you learn how to add `Contact` collection functionality to an e
1. Change to the root directory of your app project.
2. Install the preview branch of the `blockstack.js`.
- ```
- npm install blockstack@20.0.0-alpha.5
- ```
+ ```
+ npm install blockstack@20.0.0-alpha.5
+ ```
3. Add the ``blockstack-collections` package to your app.
- ```
- npm install blockstack-collections@0.1.8
- ```
+ ```
+ npm install blockstack-collections@0.1.8
+ ```
4. Edit your code to import the `Contact` collection type.
- ```
- import { Contact } from `blockstack-collections`
- ```
+ ```
+ import { Contact } from `blockstack-collections`
+ ```
5. Customize your sign in request to include the contacts collection scope `Contact.scope`.
- This scope grants your app permission to read and write to the user’s `Contact` collection.
+ This scope grants your app permission to read and write to the user’s `Contact` collection.
- ```javascript
- import { UserSession, AppConfig, makeAuthRequest } from 'blockstack'
- import { Contact } from '`blockstack-collections'
+ ```javascript
+ import { UserSession, AppConfig, makeAuthRequest } from 'blockstack';
+ import { Contact } from '`blockstack-collections';
- const scopes = ['store_write', 'publish_data', Contact.scope]
- const appConfig = new AppConfig(scopes)
- const userSession = new UserSession({appConfig: appConfig})
- userSession.redirectToSignIn()
- ```
+ const scopes = ['store_write', 'publish_data', Contact.scope];
+ const appConfig = new AppConfig(scopes);
+ const userSession = new UserSession({ appConfig: appConfig });
+ userSession.redirectToSignIn();
+ ```
## Collection storage operations
@@ -153,53 +152,50 @@ Collection storage was designed around an ORM-like interface. This approach ensu
### Example: Create and save a Contact object
```javascript
- const newContact = {
- lastName: 'Stackerson',
- firstName: 'Blocky',
- blockstackID: 'Blockstacker.id',
- email: 'blockstacker@blockstack.org',
- website: 'blockstack.org',
- telephone: '123123123'
- }
-
- var contact = new Contact(newContact)
- contact.save().then((contactID) => {
- // contact saved successfully
- })
+const newContact = {
+ lastName: 'Stackerson',
+ firstName: 'Blocky',
+ blockstackID: 'Blockstacker.id',
+ email: 'blockstacker@blockstack.org',
+ website: 'blockstack.org',
+ telephone: '123123123',
+};
+
+var contact = new Contact(newContact);
+contact.save().then(contactID => {
+ // contact saved successfully
+});
```
-
### Example: Read a Contact object
```javascript
- let contactID = 'Blocky Stackerson'
- Contact.get(contactID).then((contact) => {
- // Do something with the contact object
- console.log('Hello ${contact.firstName}')
- })
+let contactID = 'Blocky Stackerson';
+Contact.get(contactID).then(contact => {
+ // Do something with the contact object
+ console.log('Hello ${contact.firstName}');
+});
```
-
### Example: List Contact objects
```javascript
- let contacts = []
- Contact.list((contactID) => {
- // This callback is invoked for each contact identifier
- // To get the actual object you'll need to use Contact.get
- // Or you can add the IDs to an array for display
- contacts.push(contactID)
- // Return true to continue iterating, return false to stop
- return true
- })
+let contacts = [];
+Contact.list(contactID => {
+ // This callback is invoked for each contact identifier
+ // To get the actual object you'll need to use Contact.get
+ // Or you can add the IDs to an array for display
+ contacts.push(contactID);
+ // Return true to continue iterating, return false to stop
+ return true;
+});
```
-
### Example: Delete a Contact
```javascript
- var contact = new Contact(newContact)
- contact.delete().then(() => {
- // contact deleted successfully
- })
+var contact = new Contact(newContact);
+contact.delete().then(() => {
+ // contact deleted successfully
+});
```
diff --git a/src/pages/develop/connect/get-started.md b/src/pages/develop/connect/get-started.md
index 46f108e5..a7f266a0 100644
--- a/src/pages/develop/connect/get-started.md
+++ b/src/pages/develop/connect/get-started.md
@@ -1,4 +1,5 @@
# Guide to Blockstack Connect
+
## Installation
With yarn:
@@ -34,14 +35,13 @@ export interface AuthOptions {
}
```
-parameter | type | default | optional | description
----|---|---|---|---
-redirectTo | string | | false | The path in your app where users go after sign in.
-appDetails | object | | false | an object which includes `appName: string` and `appIcon: string`. This will speed up the process of loading your app's information during onboarding.
-finished | function | | false | A callback that can be invoked after authentication. This prevents having to do a whole page refresh in a new tab. One argument is passed to this callback, which is an object with `userSession` included. If included, then the `redirectTo` path is ignored, and the user will be logged in automatically.
-sendToSignIn | boolean | false | true | Whether the user should go straight to the 'sign in' flow (false) or be presented with the 'sign up' flow (true) instead.
-userSession | UserSession | | false | pass a `UserSession` instance to use for authentication. If it's not passed, `@blockstack/connect` will create one for you.
-
+| parameter | type | default | optional | description |
+| ------------ | ----------- | ------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| redirectTo | string | | false | The path in your app where users go after sign in. |
+| appDetails | object | | false | an object which includes `appName: string` and `appIcon: string`. This will speed up the process of loading your app's information during onboarding. |
+| finished | function | | false | A callback that can be invoked after authentication. This prevents having to do a whole page refresh in a new tab. One argument is passed to this callback, which is an object with `userSession` included. If included, then the `redirectTo` path is ignored, and the user will be logged in automatically. |
+| sendToSignIn | boolean | false | true | Whether the user should go straight to the 'sign in' flow (false) or be presented with the 'sign up' flow (true) instead. |
+| userSession | UserSession | | false | pass a `UserSession` instance to use for authentication. If it's not passed, `@blockstack/connect` will create one for you. |
### In React Apps
@@ -63,11 +63,7 @@ const authOptions = {
},
};
-const App = () => (
- UserGroup
class to build a collaborative group with Radiks. In this section, you learn about this class.
## Understand the UserGroup workflow
-The key model behind a collaborative group is `UserGroup`. By default, it only has one attribute, `name`, which is encrypted. You can subclass `UserGroup` with different attributes as needed.
+The key model behind a collaborative group is `UserGroup`. By default, it only has one attribute, `name`, which is encrypted. You can subclass `UserGroup` with different attributes as needed.
The general workflow for creating a collaborative group that can share and edit encrypted models is as follows:
1. The admin of the group creates a new `UserGroup`.
This group acts as the 'hub' and controls the logic around inviting and removing users.
2. The admin invites one or more other users to a group:
- * The admin specifies the username of the user they want to invite
- * Radiks looks up the user's public key
- * Radiks creates an 'invitation' that is encrypted with the user's public key, and contains information about the `UserGroup`
+ - The admin specifies the username of the user they want to invite
+ - Radiks looks up the user's public key
+ - Radiks creates an 'invitation' that is encrypted with the user's public key, and contains information about the `UserGroup`
3. When the invited user 'activates' an invitation, they create a `GroupMembership`.
They use this membership instance to reference information (such as private keys and signing keys) related to the group.
@@ -44,7 +44,6 @@ import { UserGroup } from 'radiks';
Calling `create` on a new `UserGroup` will create the group and activate an invitation for the group's creator.
-
```javascript
const group = new UserGroup({ name: 'My Group Name' });
await group.create();
@@ -52,7 +51,6 @@ await group.create();
A group's creator is also the group's admin.
-
### Invite users to become members
Use the `makeGroupMembership` method on a `UserGroup` instance to invite a user. The only argument passed to this method is the user's `username`.
@@ -70,21 +68,20 @@ console.log(invitation._id); // the ID used to later activate an invitation
You can also create a generic invitation that any user can activate, if they are provided with randomly generated secret key, which should be used to decrypt the invitation. The key is generated when the generic invitation is being created.
-~~~javascript
+```javascript
import { GenericGroupInvitation, UserGroup } from 'radiks';
const group = await UserGroup.findById(myGroupId);
// Creating generic invitation
const genericInvitation = await GenericGroupInvitation.makeGenericInvitation(group);
console.log(genericInvitation._id); // the ID used to later activate an invitation
console.log(genericInvitation.secretCode); // the secretCode used to later activate an invitation
-~~~
-
+```
### Accept an invitation
Use the `activate` method on a `GroupInvitation` instance to activate an invitation on behalf of a user:
-```javascript
+````javascript
import { GroupInvitation, GenericGroupInvitation } from 'radiks';
// For user-specific invitation
@@ -103,7 +100,7 @@ Call `UserGroup.myGroups` to fetch all groups that the current user is a member
import { UserGroup } from 'radiks';
const groups = await UserGroup.myGroups();
-```
+````
## Find a UserGroup
diff --git a/src/pages/develop/radiks-intro.md b/src/pages/develop/radiks-intro.md
index 4a54e4de..72591cab 100644
--- a/src/pages/develop/radiks-intro.md
+++ b/src/pages/develop/radiks-intro.md
@@ -1,21 +1,18 @@
---
-
-
---
+
# Radiks the data indexer
-The Blockstack Radiks feature enables Blockstack decentralized applications (DApps) to index and store across data belonging to multiple users. Radiks works with Blockstack's Gaia Storage System. Using Radiks, you can build multi-player DApps that:
+The Blockstack Radiks feature enables Blockstack decentralized applications (DApps) to index and store across data belonging to multiple users. Radiks works with Blockstack's Gaia Storage System. Using Radiks, you can build multi-player DApps that:
- index, store, and query application data
- query a user's publicly saved data
- display real-time updates that reflect in progress changes
- support collaboration among sets of users
-
-
## Why use Radiks?
-Many applications serve data that users create to share publicly with others. Facebook, Twitter, and Instagram are examples of such applications. Decentralized applications that want to create comparable multi-user experiences must ensure that anything a user creates for public sharing is still under control of the creator in the user's Gaia storage.
+Many applications serve data that users create to share publicly with others. Facebook, Twitter, and Instagram are examples of such applications. Decentralized applications that want to create comparable multi-user experiences must ensure that anything a user creates for public sharing is still under control of the creator in the user's Gaia storage.
For example, if Twitter wanted to be a decentralized application while still having many different users creating their own tweets, those tweets would be stored in each user's own Gaia storage. In such a situation, Twitter still needs a way to keep track of everyone's tweets, display those tweets in user timelines, and perform searches across the platform. Radiks exists to support these kinds of scenarios. It allows applications to query across multiple user data using complicated queries like text search, joins, and filters.
@@ -33,9 +30,9 @@ Radiks can store both public and sensitive, non-public data since all data is en
## How Radiks authorizes writes
-Radiks must ensure that the user is writing to their own data. To ensure this, Radiks creates and manages *signing keys*. These keys sign all writes that a user performs. Radiks server-validates all signatures before performing a write. This guarantees that a user is not able to overwrite another user's data.
+Radiks must ensure that the user is writing to their own data. To ensure this, Radiks creates and manages _signing keys_. These keys sign all writes that a user performs. Radiks server-validates all signatures before performing a write. This guarantees that a user is not able to overwrite another user's data.
-A Radiks server is also built to support writes in a collaborative but private situation. For example, consider a collaborative document editing application, where users can create organizations and invite users to that organization. All users in that organization should have read and write privileges to the organization data. Thus, these organizations will have a single shared key that is used to sign and encrypt data.
+A Radiks server is also built to support writes in a collaborative but private situation. For example, consider a collaborative document editing application, where users can create organizations and invite users to that organization. All users in that organization should have read and write privileges to the organization data. Thus, these organizations will have a single shared key that is used to sign and encrypt data.
When an organization administrator needs to remove a user from the group, they are expected to revoke the previous key and create a new one. Radiks is aware of these relationships, and will only support writes that are signed with the currently active key related to an organization.
@@ -65,5 +62,5 @@ Although Radiks applications rely on a centrally-hosted database, an application
-If you are not familiar with Gaia, see
+If you are not familiar with Gaia, see
[read the Gaia documentation](({{site.baseurl}}/storage/overview.html).
diff --git a/src/pages/develop/radiks-models.md b/src/pages/develop/radiks-models.md
index 0658add2..186d22c5 100644
--- a/src/pages/develop/radiks-models.md
+++ b/src/pages/develop/radiks-models.md
@@ -1,9 +1,9 @@
---
-
-
---
+
# Create and use models
-Radiks allows you to model your client data. You can then query this data and display it for a user in multi-player applications. A social application where users want to see the comments of other users is an example of a multi-player application. This page explains how to create a model in your distributed application using Radiks.
+
+Radiks allows you to model your client data. You can then query this data and display it for a user in multi-player applications. A social application where users want to see the comments of other users is an example of a multi-player application. This page explains how to create a model in your distributed application using Radiks.
## Overview of Model class extension
@@ -13,9 +13,9 @@ Blockstack provides a `Model` class you should extend to easily create, save, an
import { Model, User } from 'radiks';
```
- Then, create a class that extends this model, and provide a schema. Refer to the Model
class in the `radiks` repo to get an overview of the class functionality.
+Then, create a class that extends this model, and provide a schema. Refer to the Model
class in the `radiks` repo to get an overview of the class functionality.
-Your new class must define a static `className` property. This property is used when storing and querying information. If you fail to add a `className`, Radiks defaults to the actual model's class name (`foobar.ts`) and your application will behave unpredictably.
+Your new class must define a static `className` property. This property is used when storing and querying information. If you fail to add a `className`, Radiks defaults to the actual model's class name (`foobar.ts`) and your application will behave unpredictably.
The example class code extends `Model` to create a class named `Todo`:
@@ -24,11 +24,12 @@ import { Model, User } from 'radiks';
class Todo extends Model {
static className = 'Todo';
- static schema = { // all fields are encrypted by default
+ static schema = {
+ // all fields are encrypted by default
title: String,
completed: Boolean,
- }
-};
+ };
+}
// after authentication:
const todo = new Todo({ title: 'Use Radiks in an app' });
@@ -38,8 +39,9 @@ todo.update({
});
await todo.save();
-const incompleteTodos = await Todo.fetchOwnList({ // fetch todos that this user created
- completed: false
+const incompleteTodos = await Todo.fetchOwnList({
+ // fetch todos that this user created
+ completed: false,
});
console.log(incompleteTodos.length); // 0
```
@@ -55,14 +57,15 @@ Every class must have a static `schema` property which defines the attributes of
```javascript
class Todo extends Model {
static className = 'Todo';
- static schema = { // all fields are encrypted by default
+ static schema = {
+ // all fields are encrypted by default
title: String,
completed: Boolean,
- }
-};
+ };
+}
```
-The `key` in this object is the field name and the value, for example, `String`, `Boolean`, or `Number`. In this case, the `title` is a `String` field. Alternatively, you can pass options instead of a type.
+The `key` in this object is the field name and the value, for example, `String`, `Boolean`, or `Number`. In this case, the `title` is a `String` field. Alternatively, you can pass options instead of a type.
To define options, pass an object, with a mandatory `type` field. The only supported option right now is `decrypted`. This defaults to `false`, meaning the field is encrypted before the data is stored publicly. If you specify `true`, then the field is not encrypted.
@@ -86,13 +89,13 @@ class Person extends Model {
isHuman: Boolean,
likesDogs: {
type: Boolean,
- decrypted: true // all users will know if this record likes dogs!
- }
- }
+ decrypted: true, // all users will know if this record likes dogs!
+ },
+ };
static defaults = {
- likesDogs: true
- }
+ likesDogs: true,
+ };
}
```
@@ -123,12 +126,11 @@ The default `User` model defines a `username`, but you can add a `displayName` t
In this section, you learn how to use a model you have defined.
-### About the _id attribute
+### About the \_id attribute
All model instances have an `_id` attribute. An `_id` is used as a primary key when storing data and is used for fetching a model. Radiks also creates a `createdAt` and `updatedAt` property when creating and saving models.
-If, when constructing a model's instance, you don't pass an `_id`, Radiks creates an `_id` for you automatically. This automatically created id uses the [`uuid/v4`](https://github.com/kelektiv/node-uuid) format. This automatic `_id` is returned by the constructor.
-
+If, when constructing a model's instance, you don't pass an `_id`, Radiks creates an `_id` for you automatically. This automatically created id uses the [`uuid/v4`](https://github.com/kelektiv/node-uuid) format. This automatic `_id` is returned by the constructor.
### Construct a model instance
@@ -138,19 +140,18 @@ To create an instance, pass some attributes to the constructor of that class:
const person = new Person({
name: 'Hank',
isHuman: false,
- likesDogs: false // just an example, I love dogs!
-})
+ likesDogs: false, // just an example, I love dogs!
+});
```
### Fetch an instance
-To fetch an existing instance of an instance, you need the instance's `id` property. Then, call the `findById()` method or the `fetch()` method, which returns a promise.
+To fetch an existing instance of an instance, you need the instance's `id` property. Then, call the `findById()` method or the `fetch()` method, which returns a promise.
```javascript
const person = await Person.findById('404eab3a-6ddc-4ba6-afe8-1c3fff464d44');
```
-
After calling these methods, Radiks automatically decrypts all encrypted fields.
### Access attributes
@@ -169,9 +170,9 @@ To quickly update multiple attributes of an instance, pass those attributes to t
```javascript
const newAttributes = {
likesDogs: false,
- age: 30
-}
-person.update(newAttributes)
+ age: 30,
+};
+person.update(newAttributes);
```
Important, calling `update` does **not** save the instance.
@@ -217,14 +218,14 @@ class Task extends Model {
order: {
type: Number,
decrypted: true,
- }
- }
+ },
+ };
}
const tasks = await Task.fetchList({
completed: false,
- sort: '-order'
-})
+ sort: '-order',
+});
```
You can read the [`query-to-mongo`](https://github.com/pbatey/query-to-mongo) package documentation to learn how to do complex querying, sorting, limiting, and so forth.
@@ -244,7 +245,7 @@ Use the `fetchOwnList` method to find instances that were created by the current
```javascript
const tasks = await Task.fetchOwnList({
- completed: false
+ completed: false,
});
```
@@ -276,8 +277,8 @@ Whenever you save a task, you should save a reference to the project it's in:
```javascript
const task = new Task({
name: 'Improve radiks documentation',
- projectId: project._id
-})
+ projectId: project._id,
+});
await task.save();
```
@@ -286,7 +287,7 @@ Then, later you'll want to fetch all tasks for a certain project:
```javascript
const tasks = await Task.fetchList({
projectId: project._id,
-})
+});
```
Radiks lets you define an `afterFetch` method. Use this method to automatically fetch child records when you fetch the parent instance.
@@ -294,12 +295,12 @@ Radiks lets you define an `afterFetch` method. Use this method to automatically
```javascript
class Project extends Model {
static className = 'Project';
- static schema = { name: String }
+ static schema = { name: String };
async afterFetch() {
this.tasks = await Task.fetchList({
projectId: this.id,
- })
+ });
}
}
diff --git a/src/pages/develop/radiks-server-extras.md b/src/pages/develop/radiks-server-extras.md
index 369421fe..4ecd7ca5 100644
--- a/src/pages/develop/radiks-server-extras.md
+++ b/src/pages/develop/radiks-server-extras.md
@@ -1,8 +1,8 @@
---
-
-
---
+
# Radiks server tips and tricks
+
In this section, you'll find some tips and tricks you can use to work with a Radiks server.
## Access the MongoDB collection
@@ -17,7 +17,6 @@ const mongo = await getDB(MONGODB_URL);
[See the MongoDB Collection reference](https://mongodb.github.io/node-mongodb-native/3.1/api/Collection.html) for documentation about how you can interact with this collection.
-
## Run a custom Radiks-server
If you're using an [express.js](https://expressjs.com/) server to run your application, it's probably easiest to use the Radiks-server middleware. This way, you won't have to run a separate application server and Radiks server.
@@ -50,7 +49,6 @@ setup({
Currently, only the `mongoDBUrl` option is supported.
-
## Migrate from Firebase (or anywhere else)
Migrating data from Firebase to Radiks-server is simple and painless. You can create a script file to fetch all the Firebase data using their API. Then, you can use your `MONGOD_URI` config to use the `mongodb` npm package.
@@ -122,8 +120,8 @@ migrate()
Before you can implement the websocket function, you must configure your `Radiks-Server` with [express-ws](https://github.com/HenningM/express-ws)
```javascript
-const app = express()
-expressWS(app)
+const app = express();
+expressWS(app);
```
Here's an example for how to use the API:
@@ -131,7 +129,7 @@ Here's an example for how to use the API:
```javascript
import Task from './models/task';
-const streamCallback = (task) => {
+const streamCallback = task => {
// this callback will be called whenever a task is created or updated.
// `task` is an instance of `Task`, and all methods are defined on it.
// If the user has the necessary keys to decrypt encrypted fields on the model,
@@ -140,15 +138,15 @@ const streamCallback = (task) => {
if (task.projectId === myAppsCurrentProjectPageId) {
// update your view here with this task
}
-}
+};
-Task.addStreamListener(streamCallback)
+Task.addStreamListener(streamCallback);
// later on, you might want to remove the stream listener (if the
// user changes pages, for example). When calling `removeStreamListener`,
// you MUST provide the exact same callback that you used with `addStreamListener`.
-Task.removeStreamListener(streamCallback)
+Task.removeStreamListener(streamCallback);
```
## Saving centralized user-related data
diff --git a/src/pages/develop/radiks-setup.md b/src/pages/develop/radiks-setup.md
index 90e29673..8f8ee325 100644
--- a/src/pages/develop/radiks-setup.md
+++ b/src/pages/develop/radiks-setup.md
@@ -1,9 +1,9 @@
---
-
-
---
+
# Set-up Radiks for your DApp
-Using Radiks with your application requires a Radiks server and a client application constructed to use the server. In this article, you learn how to install, setup, and run a pre-packaged Radiks server that connects to MongoDB. You also learn how to establish your DApp application as a client for that server.
+
+Using Radiks with your application requires a Radiks server and a client application constructed to use the server. In this article, you learn how to install, setup, and run a pre-packaged Radiks server that connects to MongoDB. You also learn how to establish your DApp application as a client for that server.
## Task 1. Set up your Radiks server
@@ -17,7 +17,7 @@ In the future, Radiks-server will support various different databases, but right
1. Download and install MongoDB 3.6 or higher on your workstation.
- You can also install MongoDB using your favorite package manager; for example, Homebrew is recommended for macOS. If you are testing on a local workstation, you can use a `docker` image instead of installing locally.
+ You can also install MongoDB using your favorite package manager; for example, Homebrew is recommended for macOS. If you are testing on a local workstation, you can use a `docker` image instead of installing locally.
2. Start the MongoDB service and verify it is running.
@@ -27,34 +27,35 @@ In the future, Radiks-server will support various different databases, but right
4. Create a username/password combination with `root` privileges on your new database.
-
### Install and start the Radiks server
The easiest way to run `radiks-server` is to use the pre-packaged `node.js` server.
1. Install the `radiks-server` on a workstation or server.
- ```bash
- npm install -g radiks-server
- ```
- Or, if you prefer `yarn`:
+ ```bash
+ npm install -g radiks-server
+ ```
- ```bash
- yarn global add radiks-server
- ```
- The default port for Mongodb is `27017`; your instance may be configured differently. By default, Radiks-server will use `'mongodb://localhost:27017/radiks-server'` as the `MongoDB_URI` value. This is suitable for local testing, but in production, you'll want to change the hostname and possibly the database name.
+ Or, if you prefer `yarn`:
-3. Start the `radiks-server` in the command line to confirm your installation.
+ ```bash
+ yarn global add radiks-server
+ ```
+
+ The default port for Mongodb is `27017`; your instance may be configured differently. By default, Radiks-server will use `'mongodb://localhost:27017/radiks-server'` as the `MongoDB_URI` value. This is suitable for local testing, but in production, you'll want to change the hostname and possibly the database name.
+
+2. Start the `radiks-server` in the command line to confirm your installation.
```
$ radiks-server
(node:37750) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
- radiks-server is ready on http://localhost:1260
- ```
+ radiks-server is ready on http://localhost:1260
+ ```
- The `radiks-server` defaults to running on port `1260`. To change the default port, specify the `PORT` environment variable in your environment.
+ The `radiks-server` defaults to running on port `1260`. To change the default port, specify the `PORT` environment variable in your environment.
-4. By default, the server is running at `http://localhost:1260`
+3. By default, the server is running at `http://localhost:1260`
4. Stop the `radiks` server process after you confirm it runs, and your installation was a success.
@@ -88,42 +89,42 @@ If you are using `blockstack.js` version 18 or earlier, you must use the Radiks
1. Start the mongo shell application.
- ```
- $ mongo
- MongoDB shell version v4.2.0
- connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
- Implicit session: session { "id" : UUID("8d43cf80-490d-4cac-8bd6-40eec5c128de") }
- MongoDB server version: 4.2.0
- ....
-
- To enable free monitoring, run the following command: db.enableFreeMonitoring()
- To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
- >
- ```
-
- 2. Create a new database for your application.
-
- ```
- > show dbs
- admin 0.000GB
- config 0.000GB
- local 0.000GB
- > use test1
- switched to db test1
- > show dbs
- admin 0.000GB
- config 0.000GB
- local 0.000GB
- > db.createUser({user: "admin", pwd:"foobar1",roles: ["readWrite","dbAdmin"]});
- Successfully added user: { "user" : "admin", "roles" : [ "readWrite", "dbAdmin" ] }
- ```
+ ```
+ $ mongo
+ MongoDB shell version v4.2.0
+ connecting to: mongodb://127.0.0.1:27017/?compressors=disabled&gssapiServiceName=mongodb
+ Implicit session: session { "id" : UUID("8d43cf80-490d-4cac-8bd6-40eec5c128de") }
+ MongoDB server version: 4.2.0
+ ....
+
+ To enable free monitoring, run the following command: db.enableFreeMonitoring()
+ To permanently disable this reminder, run the following command: db.disableFreeMonitoring()
+ >
+ ```
+
+2. Create a new database for your application.
+
+ ```
+ > show dbs
+ admin 0.000GB
+ config 0.000GB
+ local 0.000GB
+ > use test1
+ switched to db test1
+ > show dbs
+ admin 0.000GB
+ config 0.000GB
+ local 0.000GB
+ > db.createUser({user: "admin", pwd:"foobar1",roles: ["readWrite","dbAdmin"]});
+ Successfully added user: { "user" : "admin", "roles" : [ "readWrite", "dbAdmin" ] }
+ ```
3. Add a user with administrative rights to the database.
- ```
- > db.createUser({user: "admin", pwd:"foobar1",roles: ["readWrite","dbAdmin"]});
- Successfully added user: { "user" : "admin", "roles" : [ "readWrite", "dbAdmin" ] }
- ```
+ ```
+ > db.createUser({user: "admin", pwd:"foobar1",roles: ["readWrite","dbAdmin"]});
+ Successfully added user: { "user" : "admin", "roles" : [ "readWrite", "dbAdmin" ] }
+ ```
4. Create an `MONGODB_URI` environment variable on the same machine where you are running the `radiks-server`.
@@ -133,7 +134,6 @@ If you are using `blockstack.js` version 18 or earlier, you must use the Radiks
export MONGODB_URI="mongodb://admin:foobar1@localhost:27017/test1"
```
-
## Task 3. Add startup code and build your application
To set up radiks.js, you only need to configure the URL that your Radiks-server instance is running on. If you're using the pre-built Radiks server, this will be `http://localhost:1260`. If you're in production or are using a custom Radiks server, you'll need to specify the exact URL where it's available.
@@ -146,48 +146,47 @@ To configure your application as a `radiks` client, do the following:
1. Start your application so that a `UserSession` allows the app to both write and publish data:
- ```js
- import { UserSession, AppConfig } from 'blockstack';
- import { configure } from 'radiks';
+ ```js
+ import { UserSession, AppConfig } from 'blockstack';
+ import { configure } from 'radiks';
- const userSession = new UserSession({
- appConfig: new AppConfig(['store_write', 'publish_data'])
- })
+ const userSession = new UserSession({
+ appConfig: new AppConfig(['store_write', 'publish_data']),
+ });
- configure({
- apiServer: 'http://localhost:1260',
- userSession
- });
- ```
+ configure({
+ apiServer: 'http://localhost:1260',
+ userSession,
+ });
+ ```
- 2. Add authentication to your application
+2. Add authentication to your application
- After your user logs in with Blockstack, you'll have some code to save the user's data in your applications `localStorage`. You'll want to use the same `UserSession` you configured with Radiks, which can be fetched from the `getConfig` method.
+ After your user logs in with Blockstack, you'll have some code to save the user's data in your applications `localStorage`. You'll want to use the same `UserSession` you configured with Radiks, which can be fetched from the `getConfig` method.
- ```js
- import { User, getConfig } from 'radiks';
+ ```js
+ import { User, getConfig } from 'radiks';
- const handleSignIn = () => {
- const { userSession } = getConfig();
- if (userSession.isSignInPending()) {
- await userSession.handlePendingSignIn();
- await User.createWithCurrentUser();
- }
- }
- ```
+ const handleSignIn = () => {
+ const { userSession } = getConfig();
+ if (userSession.isSignInPending()) {
+ await userSession.handlePendingSignIn();
+ await User.createWithCurrentUser();
+ }
+ }
+ ```
- Calling `User.createWithCurrentUser` does the following:
+ Calling `User.createWithCurrentUser` does the following:
- * Fetch user data that Blockstack.js stores in `localStorage`
- * Save the user's public data (including their public key) in Radiks-server
- * Find or create a signing key that is used to authorize writes on behalf of this user
- * Cache the user's signing key (and any group-related signing keys) to make signatures and decryption happen quickly later on
+ - Fetch user data that Blockstack.js stores in `localStorage`
+ - Save the user's public data (including their public key) in Radiks-server
+ - Find or create a signing key that is used to authorize writes on behalf of this user
+ - Cache the user's signing key (and any group-related signing keys) to make signatures and decryption happen quickly later on
### Build and run your application
After you have added Radiks to your application, build and run the application. Test the application by logging in with your Blockstack ID. Create some data using the application. If you inspect the MongoDB database, you should see the encrypted data stored in the database.
-
You can specify the `mongoDBUrl` or the `maxLimit` option when initiating the Radiks server in your application.
```javascript
@@ -201,7 +200,6 @@ setup({
The `mongoDBUrl` option is the MongoDB URL for the Radiks server
The `maxLimit` option is the maximum `limit` field used inside the mongo queries. The default is 1000.
-
## Where to go next
Creating models for your application's data is where radiks truly becomes helpful. To learn how to use models, see the [Create and use models](radiks-models.html) section.
diff --git a/src/pages/develop/storage.md b/src/pages/develop/storage.md
index 99eb3eb5..d09048e5 100644
--- a/src/pages/develop/storage.md
+++ b/src/pages/develop/storage.md
@@ -1,7 +1,6 @@
---
-
-
---
+
# Guide to Blockstack Storage
The Blockstack Platform stores application data in the Gaia Storage System. Transactional metadata is stored on the Blockstack blockchain and user application data is stored in Gaia storage. Storing data off of the blockchain ensures that Blockstack applications can provide users with high performance and high availability for data reads and writes without introducing central trust parties.
@@ -12,7 +11,6 @@ The Blockstack Platform stores application data in the Gaia Storage System. Tran
Gaia storage is a key-value store.
-
## Creating a file
You use the UserSession.putFile
@@ -82,6 +80,7 @@ var userSession = new UserSession()
```
## Reading another user's unencrypted file
+
In order for files to be publicly readable, the app must request
the `publish_data` scope during authentication.
@@ -103,7 +102,6 @@ userSession.putFile("/hello.txt", "hello world!", options)
You use the UserSession.deleteFile from the application's data store.
-
```JavaScript
var userSession = new UserSession()
@@ -115,4 +113,5 @@ var userSession = new UserSession()
```
## Related Information
+
To learn more about the guarantees provided by Gaia, see [Storage write and read]({{ site.baseurl }}/storage/write-to-read.html#)
diff --git a/src/pages/faqs/allFAQS.md b/src/pages/faqs/allFAQS.md
index b0047f3c..cba5bb32 100644
--- a/src/pages/faqs/allFAQS.md
+++ b/src/pages/faqs/allFAQS.md
@@ -1,9 +1,9 @@
---
-
-description: "Blockstack Network documentation"
+description: 'Blockstack Network documentation'
redirect_from: /org/voucherholder
---
+
# Blockstack FAQs
This is a comprehensive list of all the Blockstack FAQs.
@@ -98,10 +98,10 @@ This is a comprehensive list of all the Blockstack FAQs.
## Important disclaimer
-*The Securities and Exchange Commission (SEC) has qualified the offering statement that we have filed with the SEC under Regulation A for our offering of certain of our Stacks Tokens. The information in that offering statement is more complete than the information we are providing now, and could differ in important ways. You must read the documents filed with the SEC before investing. The offering is being made only by means of its offering statement. This document shall not constitute an offer to sell or the solicitation of an offer to buy, nor shall there be any sale of these securities in any state or jurisdiction in which such offer, solicitation or sale would be unlawful prior to registration or qualification under the securities laws of any such state or jurisdiction.*
+_The Securities and Exchange Commission (SEC) has qualified the offering statement that we have filed with the SEC under Regulation A for our offering of certain of our Stacks Tokens. The information in that offering statement is more complete than the information we are providing now, and could differ in important ways. You must read the documents filed with the SEC before investing. The offering is being made only by means of its offering statement. This document shall not constitute an offer to sell or the solicitation of an offer to buy, nor shall there be any sale of these securities in any state or jurisdiction in which such offer, solicitation or sale would be unlawful prior to registration or qualification under the securities laws of any such state or jurisdiction._
-*An indication of interest involves no obligation or commitment of any kind. Any person interested in investing in any offering of Stacks Tokens should review our disclosures and the publicly filed offering statement and the ffinal offering circular that is part of that offering statement. Blockstack is not registered, licensed or supervised as a broker dealer or investment adviser by the SEC, the Financial Industry Regulatory Authority (FINRA) or any other financial regulatory authority or licensed to provide any financial advice or services.*
+_An indication of interest involves no obligation or commitment of any kind. Any person interested in investing in any offering of Stacks Tokens should review our disclosures and the publicly filed offering statement and the ffinal offering circular that is part of that offering statement. Blockstack is not registered, licensed or supervised as a broker dealer or investment adviser by the SEC, the Financial Industry Regulatory Authority (FINRA) or any other financial regulatory authority or licensed to provide any financial advice or services._
## Forward-looking statements
-*This communication contains forward-looking statements that are based on our beliefs and assumptions and on information currently available to us. In some cases, you can identify forward-looking statements by the following words: “will,” “expect,” “would,” “intend,” “believe,” or other comparable terminology. Forward-looking statements in this document include, but are not limited to, statements about our plans for developing the platform and future utility for the Stacks Token, our Clarity smart contracting language, and potential mining operations. These statements involve risks, uncertainties, assumptions and other factors that may cause actual results or performance to be materially different. More information on the factors, risks and uncertainties that could cause or contribute to such differences is included in our filings with the SEC, including in the “Risk Factors” and “Management’s Discussion & Analysis” sections of our offering statement on Form 1-A. We cannot assure you that the forward-looking statements will prove to be accurate. These forward-looking statements speak only as of the date hereof. We disclaim any obligation to update these forward-looking statements.*
+_This communication contains forward-looking statements that are based on our beliefs and assumptions and on information currently available to us. In some cases, you can identify forward-looking statements by the following words: “will,” “expect,” “would,” “intend,” “believe,” or other comparable terminology. Forward-looking statements in this document include, but are not limited to, statements about our plans for developing the platform and future utility for the Stacks Token, our Clarity smart contracting language, and potential mining operations. These statements involve risks, uncertainties, assumptions and other factors that may cause actual results or performance to be materially different. More information on the factors, risks and uncertainties that could cause or contribute to such differences is included in our filings with the SEC, including in the “Risk Factors” and “Management’s Discussion & Analysis” sections of our offering statement on Form 1-A. We cannot assure you that the forward-looking statements will prove to be accurate. These forward-looking statements speak only as of the date hereof. We disclaim any obligation to update these forward-looking statements._
diff --git a/src/pages/ios/tutorial.md b/src/pages/ios/tutorial.md
index ec58218a..c31a4e02 100644
--- a/src/pages/ios/tutorial.md
+++ b/src/pages/ios/tutorial.md
@@ -1,9 +1,9 @@
---
-
description: How to use Blockstack on iOS Mobile
-
---
+
# iOS DApps
+
This tutorial teaches you how to create a decentralized application using
Blockstack's iOS SDK using the following content:
@@ -18,7 +18,7 @@ experienced. For best results, beginners should follow the guide as written. It
is expected that the fast or furiously brilliant will skip ahead and improvise
on this material at will. God speed one and all.
-If you want to download a complete application rather than working through a tutorial, see this *alternative* sample, the photoblock-demo.
+If you want to download a complete application rather than working through a tutorial, see this _alternative_ sample, the photoblock-demo.
## Understand the sample application flow
@@ -102,62 +102,62 @@ In this section, you build an initial React.js application called
1. Create a `hello-blockstack` directory.
- ```bash
- mkdir hello-blockstack
- ```
+ ```bash
+ mkdir hello-blockstack
+ ```
2. Change into your new directory.
- ```bash
- cd hello-blockstack
- ```
+ ```bash
+ cd hello-blockstack
+ ```
3. Create your initial `hello-world-tutorial` application.
- ```bash
- $ npx generator-blockstack --react
- npx: installed 338 in 13.792s
- create package.json
- create .gitignore
- create webpack.config.js
- create netlify.toml
- create firebase.json
- ...
- I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
-
- > fsevents@1.2.9 install /private/tmp/testymc/node_modules/fsevents
- > node install
- added 775 packages from 455 contributors and audited 9435 packages in 20.934s
- found 0 vulnerabilities
+ ```bash
+ $ npx generator-blockstack --react
+ npx: installed 338 in 13.792s
+ create package.json
+ create .gitignore
+ create webpack.config.js
+ create netlify.toml
+ create firebase.json
+ ...
+ I'm all done. Running npm install for you to install the required dependencies. If this fails, try running the command yourself.
+
+ > fsevents@1.2.9 install /private/tmp/testymc/node_modules/fsevents
+ > node install
+ added 775 packages from 455 contributors and audited 9435 packages in 20.934s
+ found 0 vulnerabilities
- ```
+ ```
- Depending on your environment you may have some warnings with the installation. Optionally, you can fix these before continuing to the next section.
+ Depending on your environment you may have some warnings with the installation. Optionally, you can fix these before continuing to the next section.
4. Run the initial application.
- ```bash
- npm run start
-
- > hello-blockstack@0.0.0 start /Users/meepers/repos/hello-blockstack
- > webpack-dev-server
-
- Project is running at http://localhost:8080/
- webpack output is served from /
- 404s will fallback to /index.html
- Hash: 4d2312ba236a4b95dc3a
- Version: webpack 2.7.0
- Time: 2969ms
- Asset Size Chunks Chunk Names
- ....
- Child html-webpack-plugin for "index.html":
- chunk {0} index.html 541 kB [entry] [rendered]
- [0] ./~/lodash/lodash.js 540 kB {0} [built]
- [1] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 533 bytes {0} [built]
- [2] (webpack)/buildin/global.js 509 bytes {0} [built]
- [3] (webpack)/buildin/module.js 517 bytes {0} [built]
- webpack: Compiled successfully.
- ```
+ ```bash
+ npm run start
+
+ > hello-blockstack@0.0.0 start /Users/meepers/repos/hello-blockstack
+ > webpack-dev-server
+
+ Project is running at http://localhost:8080/
+ webpack output is served from /
+ 404s will fallback to /index.html
+ Hash: 4d2312ba236a4b95dc3a
+ Version: webpack 2.7.0
+ Time: 2969ms
+ Asset Size Chunks Chunk Names
+ ....
+ Child html-webpack-plugin for "index.html":
+ chunk {0} index.html 541 kB [entry] [rendered]
+ [0] ./~/lodash/lodash.js 540 kB {0} [built]
+ [1] ./~/html-webpack-plugin/lib/loader.js!./src/index.html 533 bytes {0} [built]
+ [2] (webpack)/buildin/global.js 509 bytes {0} [built]
+ [3] (webpack)/buildin/module.js 517 bytes {0} [built]
+ webpack: Compiled successfully.
+ ```
At this point, the browser is running a Blockstack server on your local host.
@@ -172,18 +172,16 @@ In this section, you build an initial React.js application called
The system displays a prompt allowing you to create a new Blockstack ID or restore an existing one.
- ![]({{ site.baseurl }}/browser/images/login-choice.png)
+ ![]({{ site.baseurl }}/browser/images/login-choice.png)
7. Follow the prompts appropriate to your situation.
- If you are restoring an existing ID, you may see a prompt about your user
- being nameless, ignore it. At this point you have only a single application
- on your test server. So, you should see this single application, with your
- own `blockstack.id` display name, once you are signed in:
-
- ![]({{ site.baseurl }}/browser/images/hello-authd.png)
-
+ If you are restoring an existing ID, you may see a prompt about your user
+ being nameless, ignore it. At this point you have only a single application
+ on your test server. So, you should see this single application, with your
+ own `blockstack.id` display name, once you are signed in:
+ ![]({{ site.baseurl }}/browser/images/hello-authd.png)
### Add a redirect end point to your application
@@ -192,55 +190,55 @@ you want the web app to redirect the user to your iOS application. The work
you do here will allow it.
1. From the terminal command line, change directory to your web
-application directory (`hello-blockstack`).
+ application directory (`hello-blockstack`).
1. If it doesn't ext, create the `public` directory.
- ```bash
- $ mkdir public
- ```
+ ```bash
+ $ mkdir public
+ ```
-2. Use the `touch` command to add a redirect endpoint to your application.
+1. Use the `touch` command to add a redirect endpoint to your application.
This endpoint on the web version of your app will redirect iOS users back
to your mobile app.
- ```bash
- $ touch public/redirect.html
- ```
-
-3. Open `redirect.html` and add code to the endpoint.
+ ```bash
+ $ touch public/redirect.html
+ ```
- ```
-
-
-
- Product Name | -hello-blockstack-ios |
-
---|---|
Organization Name | -USERNAME |
-
User Interface | -Storyboard | -
Product Name | +hello-blockstack-ios |
+
---|---|
Organization Name | +USERNAME |
+
User Interface | +Storyboard | +
Select a VPC.
-A default VPC is created with a free tier account. You can use this
- default VPC. Or you can choose another VPC. If you choose another VPC,
- ensure the Subnet
value is set to a subnet reachable by a public IP.
-
Set Protect against accidental termination.
-If you terminate a Gaia instance, you lose all the data associated with it. Protection adds an extra step to terminating your Gaia instance.
-Open the Advanced Details.
-At this point, you are going to configure environment variables for your instance.
-Paste the following into the Advanced Details.
- -
- {
- "ignition": { "version": "2.2.0" },
- "storage": {
- "files": [{
- "filesystem": "root",
- "path": "/etc/environment",
- "mode": 420,
- "contents": {
- "source": "data:application/octet-stream,API_KEY%3DKEYPHRASE%0ADOMAIN%3DNAME_OF_DOMAIN%0ASTAGING%3DSTAGING_VALUE"
- }
- }]
- }
- }
-
Replace the following values in the JSON.
-Value | -Description | -
---|---|
<KEYPHRASE> |
- A phrase to pass when using the hub admin. For example, hubba is a fun key phrase. |
-
<NAME_OF_DOMAIN> |
- Your hub's domain name. For example, maryhub.ml is the domain name in this example. |
-
<STAGING_VALUE> |
-
- Indicates what type of SSL to create, testing (`1`) or production (`0`). Set testing if you want to test without worrying about rate limiting. A testing cerificate is not secure. -For this tutorial, use production (`0`). - |
-
Check your Advanced Details they should look similar to the following:
- - {
- "ignition": { "version": "2.2.0" },
- "storage": {
- "files": [{
- "filesystem": "root",
- "path": "/etc/environment",
- "mode": 420,
- "contents": {
- "source": "data:application/octet-stream,API_KEY%3Dhubba%0ADOMAIN%3Dmaryhub.ml%0ASTAGING%3D0"
- }
- }]
- }
- }
-
Select a VPC.
+A default VPC is created with a free tier account. You can use this
+ default VPC. Or you can choose another VPC. If you choose another VPC,
+ ensure the Subnet
value is set to a subnet reachable by a public IP.
+
Set Protect against accidental termination.
+If you terminate a Gaia instance, you lose all the data associated with it. Protection adds an extra step to terminating your Gaia instance.
+Open the Advanced Details.
+At this point, you are going to configure environment variables for your instance.
+Paste the following into the Advanced Details.
+ +
+ {
+ "ignition": { "version": "2.2.0" },
+ "storage": {
+ "files": [{
+ "filesystem": "root",
+ "path": "/etc/environment",
+ "mode": 420,
+ "contents": {
+ "source": "data:application/octet-stream,API_KEY%3DKEYPHRASE%0ADOMAIN%3DNAME_OF_DOMAIN%0ASTAGING%3DSTAGING_VALUE"
+ }
+ }]
+ }
+ }
+
Replace the following values in the JSON.
+Value | +Description | +
---|---|
<KEYPHRASE> |
+ A phrase to pass when using the hub admin. For example, hubba is a fun key phrase. |
+
<NAME_OF_DOMAIN> |
+ Your hub's domain name. For example, maryhub.ml is the domain name in this example. |
+
<STAGING_VALUE> |
+
+ Indicates what type of SSL to create, testing (`1`) or production (`0`). Set testing if you want to test without worrying about rate limiting. A testing cerificate is not secure. +For this tutorial, use production (`0`). + |
+
Check your Advanced Details they should look similar to the following:
+ + {
+ "ignition": { "version": "2.2.0" },
+ "storage": {
+ "files": [{
+ "filesystem": "root",
+ "path": "/etc/environment",
+ "mode": 420,
+ "contents": {
+ "source": "data:application/octet-stream,API_KEY%3Dhubba%0ADOMAIN%3Dmaryhub.ml%0ASTAGING%3D0"
+ }
+ }]
+ }
+ }
+
If the response is | -Do this... | -
---|---|
![]() |
- You should see a message that your connection is not private. - Everything is fine, continue to the next step, step 8. | -
![]() |
-
-
|
-
If the response is | +Do this... | +
---|---|
![]() |
+ You should see a message that your connection is not private. +Everything is fine, continue to the next step, step 8. | +
![]() |
+
+
|
+
500
, enter that port instead. " %}
+ {% include note.html content="If your app is running a different port than 500
, enter that port instead. " %}
The extra `solicitGaiaHubUrl` parameter of `true` will cause the Blockstack Browser to prompt new identity creators for a storage hub URL.
5. Save and close the `public/app.js` file.
6. Make sure your app rebuilds cleanly.
-
## Task 4: Try the new authentication flow
Try your new authentication code.
1. Refresh the client at `http://localhost:5000/`.
-2. Click *Sign in with Blockstack*.
+2. Click _Sign in with Blockstack_.
The Blockstack Browser prompts you to sign in. I you are _not already authenticated_ with the browser, you should see the following:
@@ -241,20 +239,25 @@ If you want to create specific sign-up flows for your DApp, you can pass a prese
do this if you have a corporate client whose employees would all like to use
your application with a company-run Gaia hub.
-To suggest a Gaia hub URL, provide an additional `recommendedGaiaHubUrl` value
+To suggest a Gaia hub URL, provide an additional `recommendedGaiaHubUrl` value
alongside the `solicitGaiaHubUrl`, for example:
```javascript
-import {
- makeAuthRequest,
- redirectToSignInWithAuthRequest
-} from 'blockstack';
+import { makeAuthRequest, redirectToSignInWithAuthRequest } from 'blockstack';
-var userSession = new UserSession()
-const authRequest = userSession.makeAuthRequest(undefined, undefined, undefined, undefined, undefined, undefined, {
- solicitGaiaHubUrl: true,
- recommendedGaiaHubUrl: 'https://mygaiahub.com'
-});
+var userSession = new UserSession();
+const authRequest = userSession.makeAuthRequest(
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ undefined,
+ {
+ solicitGaiaHubUrl: true,
+ recommendedGaiaHubUrl: 'https://mygaiahub.com',
+ }
+);
const authRequest = userSession.makeAuthRequest(
generateAndStoreTransitKey(),
@@ -262,9 +265,10 @@ const authRequest = userSession.makeAuthRequest(
'http://localhost:5000/manifest.json',
['store_write', 'publish_data'],
'http://localhost:5000/',
- nextHour().getTime(), {
+ nextHour().getTime(),
+ {
solicitGaiaHubUrl: true, //new options param
- recommendedGaiaHubUrl: 'https://mygaiahub.com' // new options param
+ recommendedGaiaHubUrl: 'https://mygaiahub.com', // new options param
}
);
@@ -275,6 +279,6 @@ Passing these parameters changes the storage hub URL prompt to the following:
![Gaiastorage](/storage/images/recommended-provider.png)
-
## Related information
+
[`makeAuthRequest()`](https://blockstack.github.io/blockstack.js/#makeauthrequest) method
diff --git a/src/pages/storage/hub-operation.md b/src/pages/storage/hub-operation.md
index e8267c1e..1f9a72b2 100644
--- a/src/pages/storage/hub-operation.md
+++ b/src/pages/storage/hub-operation.md
@@ -1,19 +1,19 @@
---
-
-description: "Storing user data with Blockstack"
+description: 'Storing user data with Blockstack'
redirect_from:
-- /storage/hello-hub-choice.html
-
+ - /storage/hello-hub-choice.html
---
+
# Understand hub operation
+
This page describes the considerations hub operators must take into account when creating and operating a Gaia storage hub.
## Configuration files
You should store a JSON configuration file either in the top-level directory of
the hub server. Alternatively, you can specify a file location using the
-`CONFIG_PATH` environment variable. The following is an example configuration file for Amazon S3:
+`CONFIG_PATH` environment variable. The following is an example configuration file for Amazon S3:
```json
{
@@ -24,8 +24,8 @@ the hub server. Alternatively, you can specify a file location using the
"pageSize": 20,
"bucket": "YOUR_BUCKET_NAME",
"awsCredentials": {
- "accessKeyID": "YOUR_ACCESS_KEY",
- "secretAccessKey": "YOUR_SECRET_KEY"
+ "accessKeyID": "YOUR_ACCESS_KEY",
+ "secretAccessKey": "YOUR_SECRET_KEY"
},
"argsTransport": {
"level": "debug",
@@ -74,7 +74,6 @@ Past users could configure this setting as a crude spam-control mechanism.
However, for the smoothest operation of your Gaia hub, set the
`proofsConfig.proofsRequired` value to `0`.
-
## Open or private hubs
You can configure an open-membership storage hub or a private storage hub. An open-membership hub, as it sounds, allows any user to use the hub service. A private hub limits the use of the service. In this section, you learn about configuring each type.
@@ -94,7 +93,7 @@ via _whitelisting_ the addresses allowed to write files. Recall that each applic
support application storage, your configuration must add to the whitelist each application you wish to use.
Alternatively, the user's client can use the authentication scheme and generate
-an association token for each app. The user should whitelist her address, and
-use her associated private key to sign each app's association token. This
+an association token for each app. The user should whitelist her address, and
+use her associated private key to sign each app's association token. This
removes the need to whitelist each application, but with the caveat that the
user needs to take care that her association tokens do not get misused.
diff --git a/src/pages/storage/overview.md b/src/pages/storage/overview.md
index fe165420..b8bad167 100644
--- a/src/pages/storage/overview.md
+++ b/src/pages/storage/overview.md
@@ -1,8 +1,7 @@
---
-
-description: "Storing user data with Blockstack"
-
+description: 'Storing user data with Blockstack'
---
+
# A decentralized storage architecture
The Blockstack Network stores application data using a storage system called
@@ -12,7 +11,7 @@ ensures that Blockstack applications can provide users with high performance and
high availability for data reads and writes without introducing central trust
parties.
-## Understand Gaia in the Blockstack architecture
+## Understand Gaia in the Blockstack architecture
The following diagram depicts the Blockstack architecture and Gaia's place in it:
@@ -20,7 +19,7 @@ The following diagram depicts the Blockstack architecture and Gaia's place in it
## User control or how is Gaia decentralized?
-A Gaia hub runs as a service which writes to data storage. The storage itself is a simple key-value store. The hub service
+A Gaia hub runs as a service which writes to data storage. The storage itself is a simple key-value store. The hub service
writes to data storage by requiring a valid authentication token from a requestor. Typically, the hub service runs on a compute resource and the storage itself on separate, dedicated storage resource. Typically, both resources belong to the same cloud computing provider.
![Gaiastorage](/storage/images/gaia-storage.png)
@@ -32,8 +31,8 @@ The control of user data lies in the way that user data is accessed. When an app
1. Fetch the `zonefile` for `alice.id`.
2. Read her profile URL from her `zonefile`.
3. Fetch Alice's profile.
-4. _Verify_ that the profile is signed by `alice.id`'s key
-5. Read the `gaiaHubUrl` (e.g. `https://gaia.alice.org/`) out of the profile
+4. _Verify_ that the profile is signed by `alice.id`'s key
+5. Read the `gaiaHubUrl` (e.g. `https://gaia.alice.org/`) out of the profile
6. Fetch the file from `https://gaia.alice.org/data.txt`.
Because `alice.id` has access to her zonefile, she can change where her profile is stored. For example, she may do this if the current profile's service provider or storage is compromised. To change where her profile is stored, she changes her Gaia hub URL to another Gaia hub URL. If a user has sufficient compute and storage resources, a user may run their own Gaia Storage System and bypass a commercial Gaia hub provider all together.
@@ -41,7 +40,7 @@ Because `alice.id` has access to her zonefile, she can change where her profile
{% include note.html content="Users with existing identities cannot yet migrate
their data from one hub to another." %}
-Applications writing directly on behalf of `alice.id` do not need to perform a lookup. Instead, the [Blockstack authentication flow](http://blockstack.github.io/blockstack.js/index.html) provides Alice's chosen application root URL to the application. This authentication flow _is also_ within Alice's control because Alice's browser _must_ generate the authentication response.
+Applications writing directly on behalf of `alice.id` do not need to perform a lookup. Instead, the [Blockstack authentication flow](http://blockstack.github.io/blockstack.js/index.html) provides Alice's chosen application root URL to the application. This authentication flow _is also_ within Alice's control because Alice's browser _must_ generate the authentication response.
## Understand data storage
@@ -51,7 +50,7 @@ Client libraries (such as `blockstack.js`) are capable of providing these guaran
## Gaia versus other storage systems
-Here's how Gaia stacks up against other decentralized storage systems. Features
+Here's how Gaia stacks up against other decentralized storage systems. Features
that are common to all storage systems are omitted for brevity.