Browse Source

feat: restructure "Build apps" section

- Organize navigation
- Rewrite overview page
- Migrate and merge section pages into sub-directories
- Update redirects
- Add authentication guide page
- Improve page meta data for related pages
- Draft introductions for guide pages
- Indicate TBD info areas
- Update library references to @stacks/*
- Update references to authenticator / Stacks Wallet
- Rename authentication reference to Stacks Connect
feat/build-apps
Mark Hendrickson 4 years ago
parent
commit
a76447c40b
  1. 91
      src/pages/build-apps.md
  2. 4
      src/pages/build-apps/collections/overview.md
  3. 3
      src/pages/build-apps/collections/types.md
  4. 63
      src/pages/build-apps/guides/authentication.md
  5. 209
      src/pages/build-apps/guides/data-storage.md
  6. 54
      src/pages/build-apps/guides/transaction-signing.md
  7. 4
      src/pages/build-apps/indexing/collaboration.md
  8. 4
      src/pages/build-apps/indexing/models.md
  9. 4
      src/pages/build-apps/indexing/overview.md
  10. 4
      src/pages/build-apps/indexing/server.md
  11. 35
      src/pages/build-apps/overview.md
  12. 9
      src/pages/build-apps/references/bns.md
  13. 24
      src/pages/build-apps/references/gaia.md
  14. 34
      src/pages/build-apps/references/stacks-connect.md
  15. 2
      src/pages/build-apps/tutorials/angular.md
  16. 4
      src/pages/build-apps/tutorials/indexing.md
  17. 2
      src/pages/build-apps/tutorials/public-registry.md
  18. 6
      src/pages/build-apps/tutorials/todos.md
  19. 41
      src/pages/data-storage/authentication.md
  20. 121
      src/pages/data-storage/storage-guide.md
  21. 94
      src/pages/data-storage/storage-write-read.md
  22. 4
      src/pages/ecosystem/contributing.md
  23. 2
      src/pages/write-smart-contracts/overview.md

91
src/pages/build-apps.md

@ -1,91 +0,0 @@
---
title: Building apps with Stacks
description: Resources for building apps on the Stacks blockchain
images:
large: /images/pages/build-apps.svg
sm: /images/pages/build-apps-sm.svg
---
## Introduction
Prefer to jump right in? Get started with these tutorials such as creating a decentralized to-do list app
[@page-reference | inline]
| /authentication/building-todo-app
[@page-reference | inline]
| /authentication/building-with-angular
## What are decentralized apps?
Decentralized apps are apps that don’t depend on a centralized platform, server or database. Instead, they use a
decentralized network, built on the Stacks blockchain, for [authentication](/authentication/overview), [data storage](/data-storage/overview),
and [backend logic](/data-storage/indexing-overview). Just like Bitcoin, a decentralized network of applications is accessible to
anyone and not controlled by any central authority.
To learn more about the Stacks network and decentralization, read the [Stacks overview](/ecosystem/overview).
### User-owned data
Data is stored with the user and encrypted with a key that only they own. Developers aren’t responsible for, or have to
host, their users’ data. This protects users against security breaches and keeps their data private.
### Smart contracts
Decentralized apps can use [smart contracts](/write-smart-contracts/overview) to make their backend logic public, open, and
permissionless. Once published on the blockchain, no one really owns or controls a smart contract. They will execute when
the terms are met, regardless of who interacts with it.
### Compatible and extendable
Decentralized apps are compatible by nature because they use the same data and shared state. You can build on top of
other apps without requiring permission or fear of being shut out.
## Getting started
To build your decentralized app, you’ll use [authentication](/authentication/overview), [data storage](/data-storage/overview),
[data indexing](/data-storage/indexing-overview) (optional), and [smart contracts](/write-smart-contracts/overview) (optional).
Get started with the documentation and tutorials below.
### Authentication and data storage
Like a regular app, yours will require user authentication and data storage, but decentralized. Get started with the documentation below or try the tutorial.
[@page-reference | inline]
| /authentication/overview
[@page-reference | inline]
| /data-storage/overview
[@page-reference | inline]
| /authentication/building-todo-app
### Data indexing
If you need to store and index data shared by multiple users, such as messages or a shared document, read the Radiks
documentation.
[@page-reference | inline]
| /data-storage/indexing-overview
### Smart contracts
You can use smart contracts to decentralize your app’s backend logic, making it open and permissionless. Smart contracts
on the Stacks blockchain are written in the [Clarity language](https://clarity-lang.org). View the smart contracts documentation or get started with a tutorial.
[@page-reference | inline]
| /write-smart-contracts/overview
[@page-reference | inline]
| /write-smart-contracts/hello-world-tutorial
[@page-reference | inline]
| /write-smart-contracts/counter-tutorial
[@page-reference | inline]
| /write-smart-contracts/public-registry-tutorial
### Stacks.js
[Stacks.js](https://blockstack.github.io/stacks.js/) is a collection of JavaScript library developed by Blockstack PBC that makes it easy to integrate authentication, data storage
and smart contracts functionality in a user-friendly way.

4
src/pages/data-storage/collections.md → src/pages/build-apps/collections/overview.md

@ -1,6 +1,6 @@
--- ---
title: Collections (Preview) title: Overview
description: Learn about the beta release of Collections and how you can start using it. description: Store data in standardized formats
--- ---
## Introduction ## Introduction

3
src/pages/data-storage/collection-type.md → src/pages/build-apps/collections/types.md

@ -1,5 +1,6 @@
--- ---
title: Create a Collection type title: Types
description: Create new collection types
--- ---
## Introduction ## Introduction

63
src/pages/build-apps/guides/authentication.md

@ -0,0 +1,63 @@
---
title: Authentication
description: Register and sign in users with identities on the Stacks blockchain
experience: beginners
tags:
- tutorial
images:
large: /images/pages/write-smart-contracts.svg
sm: /images/pages/write-smart-contracts-sm.svg
---
## Introduction
This guide explains how to authenticate users with [the Stacks Connect protocol](/build-apps/references/stacks-connect) by implementing the `connect` package of [Stacks.js](https://blockstack.github.io/stacks.js/).
Authentication provides a way for users to identify themselves to an app while retaining complete control over their credentials and personal details. It can be integrated alone or used in conjunction with [transaction signing](/build-apps/tutorials/transaction-signing) and [data storage](/build-apps/tutorials/data-storage), for which it is a prerequisite.
Users who register for your app can subsequently authenticate to any other app with support for the [Blockchain Naming System](/build-apps/references/bns) and vice versa.
See [the Todos app tutorial](/build-apps/tutorials/todos) for a concrete example of this functionality in practice.
## Initiate authentication flow
```js
import { AppConfig, UserSession, showConnect } from '@stacks/connect';
const appConfig = new AppConfig(['store_write', 'publish_data']);
const userSession = new UserSession({ appConfig });
function authenticate() {
showConnect({
appDetails: {
name: 'My App',
icon: window.location.origin + '/my-app-logo.svg',
},
redirectTo: '/',
finished: () => {
window.location.reload();
},
userSession: userSession,
});
}
```
## Handle pending sign in (still needed??)
```jsx
import { AppConfig, UserSession, showConnect } from '@stacks/connect';
const appConfig = new AppConfig(['store_write', 'publish_data']);
const userSession = new UserSession({ appConfig });
function componentDidMount() {
if (userSession.isSignInPending()) {
userSession.handlePendingSignIn().then(userData => {
window.history.replaceState({}, document.title, '/');
this.setState({ userData: userData });
});
} else if (userSession.isUserSignedIn()) {
this.setState({ userData: userSession.loadUserData() });
}
}
```

209
src/pages/build-apps/guides/data-storage.md

@ -0,0 +1,209 @@
---
title: Data storage
description: Save and retrieve data for users with Gaia
experience: beginners
tags:
- tutorial
images:
large: /images/pages/write-smart-contracts.svg
sm: /images/pages/write-smart-contracts-sm.svg
---
## Introduction
This guide explains how to save and retrieve data for users with [Gaia](/build-apps/references/gaia) by implementing the `connect` and `storage` packages of [Stacks.js](https://blockstack.github.io/stacks.js/).
Data storage provides a way for users to save both public and private data off-chain while retaining complete control over it.
Storing data off of the blockchain ensures that apps can provide users with high performance and high availability for data reads and writes without the involvement of centralized parties that could comprise their privacy or accessibility.
See [the Todos app tutorial](/build-apps/tutorials/todos) for a concrete example of this functionality in practice.
## How data is stored
Gaia storage is a key-value store.
## Creating a file
Use the [Storage.putFile](https://blockstack.github.io/stacks.js/classes/storage.html#putfile) method:
```tsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
const options: PutFileOptions = {
encrypt: false,
};
userSession.putFile('hello.txt', 'hello world', options).then(() => {
// hello.txt exists now, and has the contents "hello world"
});
```
## Creating an encrypted file
Use the [Storage.putFile](https://blockstack.github.io/stacks.js/classes/storage.html#putfile) method and
pass `encrypt: true` within the options object. See the [`PutFileOptions` type definition here](https://blockstack.github.io/stacks.js/interfaces/putfileoptions.html#encrypt)
```tsx
const userSession = new UserSession();
const options: PutFileOptions = {
encrypt: true,
};
userSession.putFile('message.txt', 'Secret hello', options).then(() => {
// message.txt exists now, and has the contents "Secret hello"
});
```
## Reading a file
Use the [Storage.getFile](https://blockstack.github.io/stacks.js/classes/storage.html#getfile) method:
```tsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
const options: GetFileOptions = {
decrypt: false,
};
storage.getFile('hello.txt', options).then(fileContents => {
// get the contents of the file hello.txt
assert(fileContents === 'hello world!');
});
```
## Reading an encrypted file
Use the [Storage.getFile](https://blockstack.github.io/stacks.js/classes/storage.html#getfile) method and pass
`decrypt: true` within the options object. See the [`GetFileOptions` type definition here](https://blockstack.github.io/stacks.js/interfaces/getfileoptions.html#decrypt)
```tsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
const options: GetFileOptions = {
decrypt: true,
};
storage.getFile('message.txt', options).then(fileContents => {
// get & decrypt the contents of the file /message.txt
assert(fileContents === 'Secret hello!');
});
```
## Reading another user's unencrypted file
In order for files to be publicly readable, the app must request
the [`publish_data` scope](https://blockstack.github.io/stacks.js/enums/authscope.html#publish_data) during authentication.
```jsx
const options = {
user: 'ryan.id', // the Stacks ID of the user for which to lookup the file
app: 'https://BlockstackApp.com', // origin of the app this file is stored for
decrypt: false,
};
const userSession = new UserSession();
storage.getFile('hello.txt', options).then(fileContents => {
// get the contents of the file /message.txt
assert(fileContents === 'hello world!');
});
```
## Delete a file
Use the [`UserSession.deleteFile`](https://blockstack.github.io/stacks.js/classes/storage.html#deletefile) from the application's data store.
```jsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
storage.deleteFile('hello.txt').then(() => {
// hello.txt is now removed.
});
```
## Write-to and Read-from URL Guarantees
Gaia is built on a driver model that supports many storage services. So, with
very few lines of code, you can interact with providers on Amazon S3, Dropbox,
and so forth. The simple `getFile()` and `putFile()` interfaces are kept simple
because Stacks assumes and wants to encourage a community of
open-source-data-management libraries.
The performance and simplicity-oriented guarantee of the Gaia specification is
that when an application submits a write-to
`https://myhub.service.org/store/foo/bar` URL, the application is guaranteed to
be able to read from the `https://myreads.com/foo/bar` URL. Note that, while the
prefix in the write-to url (for example,`myhub.service.org/store`) and the read-from URL
(`https://myreads.com`) are different, the `foo/bar` suffixes are the same.
By default, `putFile()` encrypts information while `getFile()` decrypts it by default. Data stored in an
encrypted format means only the user that stored it can view it. For applications that want other users to
view data, the application should set the `encrypt` option to `false`. And, corresponding, the `decrypt`
option on `getFile()` should also be `false`.
Consistent, identical suffixes allow an application to know _exactly_ where a
written file can be read from, given the read prefix. The Gaia service defines a `hub_info` endpoint to obtain
that read prefix:
```bash
GET /hub_info/
```
The endpoint returns a JSON object with a `read_url_prefix`, for example, if my service returns:
```jsx
{ ...,
"read_url_prefix": "https://myservice.org/read/"
}
```
The data be read with this `getFile()` and this address:
```
https://myservice.org/read/1DHvWDj834zPAkwMhpXdYbCYh4PomwQfzz/0/profile.json
```
The application is guaranteed that the profile is written with `putFile()` this request address:
```
https://myservice.org/store/1DHvWDj834zPAkwMhpXdYbCYh4PomwQfzz/0/profile.json
```
When you use the `putFile()` method it takes the user data and POSTs it to the user's Gaia storage hub.
The data POSTs directly to the hub, the blockchain is not used and no data is stored there. The limit on
file upload is currently 25mb.
## Address-based access-control
Access control in a Gaia storage hub is performed on a per-address basis.
Writes to URLs `/store/<address>/<file>` are allowed only if the writer can
demonstrate that they control _that_ address. This is achieved via the
authentication token which is a message _signed_ by the private key associated
with that address. The message itself is a challenge text, returned via the
`/hub_info/` endpoint.
Reads can be done by everybody. The URLs to a user's app data are in a canonical location in their profile.
For example, here's how you would get data from the [Banter](https://banter.pub/) app, stored under the
Stacks ID `gavin.id`.
### Step 1: Get the bucket URL
```bash
BUCKET_URL="$(curl -sL https://core.blockstack.org/v1/users/gavin.id | jq -r '."gavin.id"["profile"]["apps"]["https://banter.pub"]')" 
echo "$BUCKET_URL"  https://gaia.blockstack.org/hub/16E485MVpR3QpmjVkRgej7ya2Vnzu3jyTR/
```
### Step 2: Get the data
```bash
curl -sL "${BUCKET_URL%%/}/Message/3e866af471d0-4072-beba-06ad1e7ad4bd"
```
```bash
{"content":"Anyone here?","votes":[],"createdBy":"gavin.id",...}
```
This data is public and unencrypted. The same works for encrypted data. Only the holder of the private key used for encryption would be able to decrypt the data.

54
src/pages/write-smart-contracts/signing-transactions.md → src/pages/build-apps/guides/transaction-signing.md

@ -1,8 +1,7 @@
--- ---
title: Signing transactions title: Transaction signing
description: Learn how to sign transactions using Stacks Connect. description: Prompt users to sign and broadcast transactions to the Stacks blockchain
experience: advanced experience: beginners
duration: 30 minutes
tags: tags:
- tutorial - tutorial
images: images:
@ -12,15 +11,19 @@ images:
## Introduction ## Introduction
With Stacks Connect, you can interact with the Stacks 2.0 blockchain, empowering your users to sign transactions and interact with smart contracts. This guide explains how to prompt users to sign transactions and broadcast them to the Stacks blockchain by implementing the `connect` package of [Stacks.js](https://blockstack.github.io/stacks.js/).
This functionality currently operates on [the Stacks 2.0 Testnet](http://testnet.blockstack.org/). The user interface has been designed with developers in mind and prominently displays debug information. STX testnet tokens for paying transaction fees can be obtained for free with [the testnet faucet](https://testnet.blockstack.org/faucet). We will update this functionality and experience for mainnet upon its release. Transaction signing provides a way for users execute [smart contracts written in Clarity](/write-smart-contracts/overview) that are relevant to your app then handle the result immediately.
Users can sign transactions that exchange fungible or non-fungible tokens with upfront guarantees while retaining complete control over their digital assets.
See [the public registry tutorial](/build-apps/tutorials/public-registry) for a concrete example of this functionality in practice.
## How it works ## How it works
For your app's users to be able to execute a smart contract function, they need to sign and broadcast a transaction. For your app's users to be able to execute a smart contract function, they need to sign and broadcast a transaction.
It's important that users remain in control of the private keys that sign these transactions. Connect provides an
easy-to-use workflow that allows your users to securely sign transactions. It's important that users remain in control of the private keys that sign these transactions. Connect provides an easy-to-use workflow that allows your users to securely sign transactions.
Connect allows you to open the authenticator with parameters indicating the details of the transaction - like the smart Connect allows you to open the authenticator with parameters indicating the details of the transaction - like the smart
contract address, function name, and specific arguments. Your users get the chance to see these details, and then sign contract address, function name, and specific arguments. Your users get the chance to see these details, and then sign
@ -35,9 +38,8 @@ with it.
To initiate a contract call transaction, use the `openContractCall` function. To initiate a contract call transaction, use the `openContractCall` function.
```tsx ```tsx
import { openContractCall } from '@blockstack/connect'; import { openContractCall } from '@stacks/connect';
// Here's an example of options:
const myStatus = 'hey there'; const myStatus = 'hey there';
const options = { const options = {
contractAddress: 'ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ', contractAddress: 'ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ',
@ -118,14 +120,14 @@ const functionArguments = [
]; ];
``` ```
If you're using TypeScript, these Clarity types can be imported as `ContractCallArgumentType` from `@blockstack/connect`. If you're using TypeScript, these Clarity types can be imported as `ContractCallArgumentType` from `@stacks/connect`.
## Stacks (STX) Token Transfers ## Stacks (STX) Token Transfers
STX token transfers can be initiated with the `openSTXTransfer` function. STX token transfers can be initiated with the `openSTXTransfer` function.
```tsx ```tsx
import { openSTXTransfer } from '@blockstack/connect'; import { openSTXTransfer } from '@stacks/connect';
openSTXTransfer({ openSTXTransfer({
recipient: 'ST2EB9WEQNR9P0K28D2DC352TM75YG3K0GT7V13CV', recipient: 'ST2EB9WEQNR9P0K28D2DC352TM75YG3K0GT7V13CV',
@ -158,18 +160,18 @@ interface STXTransferOptions {
} }
``` ```
| parameter | type | optional | description | | parameter | type | optional | description |
| ---------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ---------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| recipient | string | false | The STX Address for the recipient of this STX transfer | | recipient | string | false | The STX Address for the recipient of this STX transfer |
| amount | string | false | The amount of microstacks (µSTX) to be transferred. This argument is a string to prevent floating point errors. There are 1,000,000 µSTX per STX. | | amount | string | false | The amount of microstacks (µSTX) to be transferred. This argument is a string to prevent floating point errors. There are 1,000,000 µSTX per STX. |
| memo | string | true | An optional memo to include in the transaction. | | memo | string | true | An optional memo to include in the transaction. |
| appDetails | object | false | A dictionary that includes `name` and `icon` | | appDetails | object | false | A dictionary that includes `name` and `icon` |
| finished | function | false | A callback that is fired when the transaction is signed and broadcasted. Your callback will receive an object back with a `txId` and a `txRaw`, both of which are strings. | | finished | function | false | A callback that is fired when the transaction is signed and broadcasted. Your callback will receive an object back with a `txId` and a `txRaw`, both of which are strings. |
| authOrigin | string | true | The location of the authenticator. This is only necessary when developing the authenticator locally, or when using beta features. Defaults to `"https://app.blockstack.org"`. | | authOrigin | string | true | Location of the authenticator to use for signing. Defaults `"https://app.blockstack.org"`. |
## Deploying Clarity Contracts ## Deploy smart contract
To allow your app's users to deploy arbitrary Clarity contracts, use the `openContractDeploy` method. To allow your app's users to deploy Clarity smart contracts, use the `openContractDeploy` method.
```tsx ```tsx
import { openContractDeploy } from '@blockstack/connect'; import { openContractDeploy } from '@blockstack/connect';
@ -221,7 +223,7 @@ Each transaction signing method is exposed through the `useConnect` hook, but th
`open`, to remain consistent with our React action naming standards. `open`, to remain consistent with our React action naming standards.
```tsx ```tsx
import { useConnect } from '@blockstack/connect'; import { useConnect } from '@stacks/connect';
const MyComponent = () => { const MyComponent = () => {
const { doContractCall } = useConnect(); const { doContractCall } = useConnect();
@ -236,3 +238,9 @@ const MyComponent = () => {
return <span onClick={onClick}>Call my contract</span>; return <span onClick={onClick}>Call my contract</span>;
}; };
``` ```
## Network settings
TBD: instructions on toggling network
You may find it useful to request testnet STX from [the faucet](https://testnet.blockstack.org/faucet) while developing and testing your app with the Stacks testnet.

4
src/pages/data-storage/indexing-collaborate.md → src/pages/build-apps/indexing/collaboration.md

@ -1,6 +1,6 @@
--- ---
title: Collaborate with groups title: Collaboration
description: A key feature of Radiks is support for private collaboration between multiple users. description: Support private collaboration between multiple users with Radiks
--- ---
## Introduction ## Introduction

4
src/pages/data-storage/indexing-models.md → src/pages/build-apps/indexing/models.md

@ -1,6 +1,6 @@
--- ---
title: Create and use models title: Models
description: Model and query application data with Radiks. description: Model and query application data with Radiks
--- ---
## Introduction ## Introduction

4
src/pages/data-storage/indexing-overview.md → src/pages/build-apps/indexing/overview.md

@ -1,6 +1,6 @@
--- ---
title: Indexing overview title: Overview
description: Using Radiks you can build multi-player apps that index, store, and query user data. description: Build multi-player apps that index, store, and query user data with Radiks
images: images:
large: /images/pages/radiks.svg large: /images/pages/radiks.svg
sm: /images/pages/radiks-sm.svg sm: /images/pages/radiks-sm.svg

4
src/pages/data-storage/indexing-server-extras.md → src/pages/build-apps/indexing/server.md

@ -1,6 +1,6 @@
--- ---
title: Server tips and tricks title: Server
description: Some tips and tricks for working with a Radiks server. description: Tips and tricks for working with Radiks server
--- ---
## Access the MongoDB collection ## Access the MongoDB collection

35
src/pages/build-apps/overview.md

@ -0,0 +1,35 @@
---
title: Build apps with Stacks
description: Authenticate users, sign transactions and store data with the Stacks blockchain
images:
large: /images/pages/build-apps.svg
sm: /images/pages/build-apps-sm.svg
---
## Introduction
Apps built with the Stacks blockchain give users control over their digital identities, assets and data.
Unlike most cloud-based apps, they are "decentralized" since they don't depend on any centralized platform, server or database to function. Rather, they use the Stacks blockchain to authenticate users and facilitate read and write transactions for them without any single point of failure or trust.
This page provides information on how to build such apps using [Stacks.js](https://github.com/blockstack/stacks.js) and other libraries that make integration of the Stacks blockchain easy for front-end developers.
Three main types of integration are available:
- **Authentication**: Register and sign in users with identities with the Stacks blockchain
- **Transaction signing**: Prompt users to sign and broadcast transactions to the Stacks blockchain
- **Data storage**: Save and retrieve data for users with Gaia
All three of these types can be used together to create powerful new user experiences that rival or exceed those of traditional apps – all while protecting your users' digital rights.
While integration is possible for any type of app, most of the resources available here are for web developers experienced with JavaScript.
## Guides
[@page-reference | grid]
| /build-apps/guides/authentication, /build-apps/guides/transaction-signing, /build-apps/guides/data-storage
## Tutorials
[@page-reference | grid]
| /build-apps/tutorials/todos, /build-apps/tutorials/public-registry, /build-apps/tutorials/angular, /build-apps/tutorials/radiks

9
src/pages/technology/naming-system.md → src/pages/build-apps/references/bns.md

@ -1,12 +1,11 @@
--- ---
title: Overview title: Blockchain Naming System
description: 'Blockchain naming system (BNS)' description: Binds Stacks usernames to off-chain state
--- ---
# Blockchain Naming System (BNS) Blockchain Naming System (BNS) is a network system that binds Stacks usernames
BNS is a network system that binds names
to off-chain state without relying on any central points of control. to off-chain state without relying on any central points of control.
The Stacks V1 blockchain implemented BNS through first-order name operations. The Stacks V1 blockchain implemented BNS through first-order name operations.
In Stacks V2, BNS is instead implemented through a smart-contract loaded In Stacks V2, BNS is instead implemented through a smart-contract loaded
during the genesis block. during the genesis block.

24
src/pages/data-storage/overview.md → src/pages/build-apps/references/gaia.md

@ -1,6 +1,6 @@
--- ---
title: A decentralized storage architecture title: Gaia
description: Storing user data with Stacks description: Decentralized storage architecture for off-chain data
images: images:
large: /images/pages/data-storage.svg large: /images/pages/data-storage.svg
sm: /images/pages/data-storage-sm.svg sm: /images/pages/data-storage-sm.svg
@ -8,11 +8,13 @@ images:
## Introduction ## Introduction
The Stacks Network stores application data using a storage system called Apps built with the Stacks blockchain store off-chain data using a storage system called
Gaia. Transactional metadata is stored on the Stacks blockchain and user Gaia.
application data is stored in Gaia storage. Storing data off of the blockchain
ensures that Stacks applications can provide users with high performance and Whereas public transactional metadata is best stored on the Stacks blockchain, user
high availability for data reads and writes without introducing central trust application data can often be stored more efficiently and privately in Gaia storage.
Storing data off of the blockchain ensures that Stacks applications can provide users with high performance and high availability for data reads and writes without introducing central trust
parties. parties.
## Understand Gaia in the Stacks architecture ## Understand Gaia in the Stacks architecture
@ -63,7 +65,13 @@ Applications writing directly on behalf of `alice.id` do not need to perform a l
A Gaia hub stores the written data _exactly_ as given. It offers minimal guarantees about the data. It does not ensure that data is validly formatted, contains valid signatures, or is encrypted. Rather, the design philosophy is that these concerns are client-side concerns. A Gaia hub stores the written data _exactly_ as given. It offers minimal guarantees about the data. It does not ensure that data is validly formatted, contains valid signatures, or is encrypted. Rather, the design philosophy is that these concerns are client-side concerns.
Client libraries (such as `Stacks.js`) are capable of providing these guarantees. Blockstack used a liberal definition of the [end-to-end principle](https://en.wikipedia.org/wiki/End-to-end_principle) to guide this design decision. Client libraries (such as `Stacks.js`) are capable of providing these guarantees. A liberal definition of the [end-to-end principle](https://en.wikipedia.org/wiki/End-to-end_principle) guides this design decision.
When an application writes to a Gaia hub, an authentication token, key, and the data are passed to the Gaia hub.
![Gaia writes](/images/gaia-writes.png)
The token ensures the app has the authorization to write to the hub on the user's behalf.
## Gaia versus other storage systems ## Gaia versus other storage systems

34
src/pages/authentication/overview.md → src/pages/build-apps/references/stacks-connect.md

@ -1,26 +1,28 @@
--- ---
title: Authentication title: Stacks Connect
description: Stacks Auth provides single sign on and authentication without third parties or remote servers. description: Open protocol for connecting apps built with Stacks
images: images:
large: /images/pages/authentication.svg large: /images/pages/authentication.svg
sm: /images/pages/authentication-sm.svg sm: /images/pages/authentication-sm.svg
--- ---
Stacks Connect is an open protocol for connecting apps built with the Stacks blockchain, such as consumer apps with authenticators and wallets.
## Authentication flow ## Authentication flow
For an application developer, the application flow is similar to the typical client-server flow used by centralized sign in services (for example, OAuth). However, with Stacks auth, the authentication flow happens entirely client-side. For an application developer, the application flow is similar to the typical client-server flow used by centralized sign in services (for example, OAuth). However, with Stacks Connect, the authentication flow happens entirely client-side.
A decentralized application and [the Blockstack App](https://github.com/blockstack/ux/tree/master/packages/app) communicate during the authentication flow by passing back and forth two tokens. The requesting application sends the Blockstack App an `authRequest` token. Once a user approves a sign-in, the Blockstack App responds to the application with an `authResponse` token. These tokens are <a href="https://jwt.io/" target="\_blank">JSON Web Tokens</a>, and they are passed via URL query strings. An app and authenticator, such as [the Stacks Wallet](https://blockstack.org/wallet), communicate during the authentication flow by passing back and forth two tokens. The requesting application sends the authenticator an `authRequest` token. Once a user approves a sign-in, the authenticator responds to the application with an `authResponse` token. These tokens are <a href="https://jwt.io/" target="\_blank">JSON Web Tokens</a>, and they are passed via URL query strings.
![](/images/app-sign-in.png) ![](/images/app-sign-in.png)
When a user chooses to authenticate a decentralized application, it calls the `doOpenAuth()` method which sends an `authRequest` to the Blockstack App. Stacks auth passes the token in via a URL query string in the `authRequest` parameter: When a user chooses to authenticate a decentralized application, it calls the `doOpenAuth()` method which sends an `authRequest` to the authenticator. Stacks auth passes the token in via a URL query string in the `authRequest` parameter:
`https://app.blockstack.org/#/sign-up?authRequest=j902120cn829n1jnvoa...` `https://app.blockstack.org/#/sign-up?authRequest=j902120cn829n1jnvoa...`
When the Blockstack App receives the request, it generates an (`authResponse`) token to the application using an _ephemeral transit key_ . The ephemeral transit key is just used for the particular instance of the application, in this case, to sign the `authRequest`. The application stores the ephemeral transit key during the request generation. The public portion of the transit key is passed in the `authRequest` token. The Blockstack App uses the public portion of the key to encrypt an _app-private key_ which is returned via the `authResponse`. When the authenticator receives the request, it generates an (`authResponse`) token to the application using an _ephemeral transit key_ . The ephemeral transit key is just used for the particular instance of the application, in this case, to sign the `authRequest`. The application stores the ephemeral transit key during the request generation. The public portion of the transit key is passed in the `authRequest` token. The authenticator uses the public portion of the key to encrypt an _app-private key_ which is returned via the `authResponse`.
During sign in, the Blockstack App generates the app-private key from the user's _identity-address private_ key and the application's `appDomain`. The app private key serves three functions: During sign in, the authenticator generates the app-private key from the user's _identity-address private_ key and the application's `appDomain`. The app private key serves three functions:
- It is used to create the credentials that give an app access to the Gaia storage bucket for that specific app. - It is used to create the credentials that give an app access to the Gaia storage bucket for that specific app.
- It is used in the end-to-end encryption of files stored for the app in the user's Gaia storage. - It is used in the end-to-end encryption of files stored for the app in the user's Gaia storage.
@ -62,7 +64,7 @@ The following is an example manifest file.
} }
``` ```
The Blockstack App retrieves the manifest file from the app during the authentication process and displays the The Stacks Wallet retrieves the manifest file from the app during the authentication process and displays the
information in it such as the app `name` and to the user during sign in. The location of the app manifest file is specific information in it such as the app `name` and to the user during sign in. The location of the app manifest file is specific
in the authentication request token and **must** be on the same origin as the app requesting authentication. in the authentication request token and **must** be on the same origin as the app requesting authentication.
@ -88,13 +90,13 @@ following sections describe the three public-private key pairs used in the authe
### Transit private key ### Transit private key
The transit private is an ephemeral key that is used to encrypt secrets that The transit private is an ephemeral key that is used to encrypt secrets that
need to be passed from the Blockstack App to the decentralized app during the need to be passed from the authenticator to the decentralized app during the
authentication process. It is randomly generated by the app at the beginning of authentication process. It is randomly generated by the app at the beginning of
the authentication response. the authentication response.
The public key that corresponds to the transit private key is stored in a single The public key that corresponds to the transit private key is stored in a single
element array in the `public_keys` key of the authentication request token. The element array in the `public_keys` key of the authentication request token. The
Blockstack App encrypts secret data such as the app private key using this authenticator encrypts secret data such as the app private key using this
public key and sends it back to the app when the user signs in to the app. The public key and sends it back to the app when the user signs in to the app. The
transit private key signs the app authentication request. transit private key signs the app authentication request.
@ -103,7 +105,7 @@ transit private key signs the app authentication request.
The identity address private key is derived from the user's keychain phrase and The identity address private key is derived from the user's keychain phrase and
is the private key of the Stacks username that the user chooses to use to sign in is the private key of the Stacks username that the user chooses to use to sign in
to the app. It is a secret owned by the user and never leaves the user's to the app. It is a secret owned by the user and never leaves the user's
instance of the Blockstack App. instance of the authenticator.
This private key signs the authentication response token for an app to indicate that the user approves sign in to that app. This private key signs the authentication response token for an app to indicate that the user approves sign in to that app.
@ -114,7 +116,7 @@ user's identity address private key using the `domain_name` as input. It is
deterministic in that for a given Stacks username and `domain_name`, the same deterministic in that for a given Stacks username and `domain_name`, the same
private key is generated each time. private key is generated each time.
The app private key is securely shared with the app on each authentication, encrypted by the Blockstack App with the transit public key. The app private key is securely shared with the app on each authentication, encrypted by the authenticator with the transit public key.
## JSON Web Token signatures ## JSON Web Token signatures
@ -144,9 +146,9 @@ const requestPayload = {
public_keys, // single entry array with public key of transit key public_keys, // single entry array with public key of transit key
domain_name, // app origin domain_name, // app origin
manifest_uri, // url to manifest file - must be hosted on app origin manifest_uri, // url to manifest file - must be hosted on app origin
redirect_uri, // url to which the Blockstack App redirects user on auth approval - must be hosted on app origin redirect_uri, // url to which the authenticator redirects user on auth approval - must be hosted on app origin
version, // version tuple version, // version tuple
do_not_include_profile, // a boolean flag asking Blockstack App to send profile url instead of profile object do_not_include_profile, // a boolean flag asking authenticator to send profile url instead of profile object
supports_hub_url, // a boolean flag indicating gaia hub support supports_hub_url, // a boolean flag indicating gaia hub support
scopes, // an array of string values indicating scopes requested by the app scopes, // an array of string values indicating scopes requested by the app
}; };
@ -277,3 +279,7 @@ const recoveredProfile = Person.fromToken(tokenFile, publicKey);
```jsx ```jsx
const validationResults = Person.validateSchema(recoveredProfile); const validationResults = Person.validateSchema(recoveredProfile);
``` ```
### Transaction signing
TBD: info on transaction signing protocol

2
src/pages/authentication/building-with-angular.md → src/pages/build-apps/tutorials/angular.md

@ -1,5 +1,5 @@
--- ---
title: Stacks Auth with Angular title: Angular
description: How to integrate authentication within an Angular application description: How to integrate authentication within an Angular application
experience: beginners experience: beginners
duration: 30 minutes duration: 30 minutes

4
src/pages/data-storage/integrate-indexing.md → src/pages/build-apps/tutorials/indexing.md

@ -1,6 +1,6 @@
--- ---
title: Integrate Radiks title: Radiks
description: Learn how to setup Radiks with your application description: Learn how to setup Radiks with your app
icon: BlockstackIcon icon: BlockstackIcon
duration: 1 hour duration: 1 hour
experience: intermediate experience: intermediate

2
src/pages/write-smart-contracts/public-registry-tutorial.md → src/pages/build-apps/tutorials/public-registry.md

@ -1,5 +1,5 @@
--- ---
title: Building a public registry title: Public registry
description: Learn how to read state from the Stacks blockchain. description: Learn how to read state from the Stacks blockchain.
duration: 60 minutes duration: 60 minutes
experience: intermediate experience: intermediate

6
src/pages/authentication/building-todo-app.md → src/pages/build-apps/tutorials/todos.md

@ -1,6 +1,6 @@
--- ---
title: Building a Todo app title: Todos app
description: Learn how to integrate authentication and data storage with React. description: Review authentication and data storage integration
experience: beginners experience: beginners
duration: 30 minutes duration: 30 minutes
tags: tags:
@ -10,8 +10,6 @@ images:
sm: /images/pages/todo-app-sm.svg sm: /images/pages/todo-app-sm.svg
--- ---
# Learn from a todos app built with Stacks
![What you'll be studying in this tutorial](/images/todos/home.png) ![What you'll be studying in this tutorial](/images/todos/home.png)
## Introduction ## Introduction

41
src/pages/data-storage/authentication.md

@ -1,41 +0,0 @@
---
description: 'Storing user data with Stacks'
---
## Introduction
Stacks authentication is a bearer token-based authentication system. From an app user's perspective,
login similar to third-party authentication techniques that they're familiar with. For an app developer,
the flow is unlike the typical client-server flow of centralized sign-in services such as OAuth. With Stacks Auth
the authentication flow happens entirely client-side.
In this section, you get an overview of the authentication system and learn how Gaia fits into it.
## Authentication and Gaia
A decentralized application (DApp) and the Stacks authenticator communicate during
the authentication flow by passing back and forth two tokens. The requesting
application sends the Stacks authenticator an `authRequest` token. Once a user
approves a sign-in, the Stacks authenticator responds to the application with an
`authResponse` token. These tokens are <a href="https://jwt.io/" target="\_blank">JSON Web Tokens</a>, and they are
passed via URL query strings.
When a user chooses to "Sign in with Stacks Auth" on your DApp, the `redirectToSignIn()` method sends the user to the
Stacks authenticator. The browser responds with an authentication token and an _app private key_.
![](/images/app-sign-in.png)
The app private key is application-specific. It is generated from the user's identity address private key using the
`appDomain` as input. This key is deterministic, meaning that for a given Stacks ID and domain name, the same
private key is generated each time. The app private key is securely shared with the app on each authentication and
encrypted by the Stacks authenticator. The key serves three functions, it:
- is used to create the credentials that give an app access to the Gaia hub storage bucket for that specific app
- is used in the end-to-end encryption of files stored for the app on the user's Gaia hub
- serves as a cryptographic secret that apps can use to perform other cryptographic functions
When an application writes to a Gaia hub, the authentication token, key, and the data are passed to the Gaia hub.
![Gaia writes](/images/gaia-writes.png)
The token ensures the DApp has the authorization to write to the hub on the user's behalf.

121
src/pages/data-storage/storage-guide.md

@ -1,121 +0,0 @@
---
title: Guide to Stacks Storage
---
## Introduction
The Stacks Platform stores application data in the Gaia Storage System. Transactional metadata is stored on the
Stacks blockchain and user application data is stored in Gaia storage. Storing data off of the blockchain ensures
that Stacks applications can provide users with high performance and high availability for data reads and writes
without introducing central trust parties.
-> Stacks Gaia Storage APIs and on-disk format will change in upcoming pre-releases breaking backward compatibility. File encryption is currently opt-in on a file by file basis. Certain storage features such as collections are not implemented in the current version. These features will be rolled out in future updates.
## How data is stored
Gaia storage is a key-value store.
## Creating a file
Use the [Storage.putFile](https://blockstack.github.io/stacks.js/classes/storage.html#putfile) method:
```tsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
const options: PutFileOptions = {
encrypt: false,
};
userSession.putFile('hello.txt', 'hello world', options).then(() => {
// hello.txt exists now, and has the contents "hello world"
});
```
## Creating an encrypted file
Use the [Storage.putFile](https://blockstack.github.io/stacks.js/classes/storage.html#putfile) method and
pass `encrypt: true` within the options object. See the [`PutFileOptions` type definition here](https://blockstack.github.io/stacks.js/interfaces/putfileoptions.html#encrypt)
```tsx
const userSession = new UserSession();
const options: PutFileOptions = {
encrypt: true,
};
userSession.putFile('message.txt', 'Secret hello', options).then(() => {
// message.txt exists now, and has the contents "Secret hello"
});
```
## Reading a file
Use the [Storage.getFile](https://blockstack.github.io/stacks.js/classes/storage.html#getfile) method:
```tsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
const options: GetFileOptions = {
decrypt: false,
};
storage.getFile('hello.txt', options).then(fileContents => {
// get the contents of the file hello.txt
assert(fileContents === 'hello world!');
});
```
## Reading an encrypted file
Use the [Storage.getFile](https://blockstack.github.io/stacks.js/classes/storage.html#getfile) method and pass
`decrypt: true` within the options object. See the [`GetFileOptions` type definition here](https://blockstack.github.io/stacks.js/interfaces/getfileoptions.html#decrypt)
```tsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
const options: GetFileOptions = {
decrypt: true,
};
storage.getFile('message.txt', options).then(fileContents => {
// get & decrypt the contents of the file /message.txt
assert(fileContents === 'Secret hello!');
});
```
## Reading another user's unencrypted file
In order for files to be publicly readable, the app must request
the [`publish_data` scope](https://blockstack.github.io/stacks.js/enums/authscope.html#publish_data) during authentication.
```jsx
const options = {
user: 'ryan.id', // the Stacks ID of the user for which to lookup the file
app: 'https://BlockstackApp.com', // origin of the app this file is stored for
decrypt: false,
};
const userSession = new UserSession();
storage.getFile('hello.txt', options).then(fileContents => {
// get the contents of the file /message.txt
assert(fileContents === 'hello world!');
});
```
## Delete a file
Use the [`UserSession.deleteFile`](https://blockstack.github.io/stacks.js/classes/storage.html#deletefile) from the application's data store.
```jsx
const userSession = new UserSession();
const storage = new Storage({ userSession });
storage.deleteFile('hello.txt').then(() => {
// hello.txt is now removed.
});
```
## Related Information
To learn more about the guarantees provided by Gaia, see [Storage write and read](/data-storage/storage-write-read)

94
src/pages/data-storage/storage-write-read.md

@ -1,94 +0,0 @@
---
description: 'Storing user data with Stacks'
---
## Introduction
Once a user authenticates and a DApp obtains authentication, the application interacts with Gaia through the
`@stacks/auth` library. There are two simple methods in `@stacks/storage` for working with data in Gaia hub:
the `putFile()` and `getFile()` methods. This section goes into greater detail about the methods, how they
interact with a hub, and how to use them.
## Write-to and Read-from URL Guarantees
Gaia is built on a driver model that supports many storage services. So, with
very few lines of code, you can interact with providers on Amazon S3, Dropbox,
and so forth. The simple `getFile()` and `putFile()` interfaces are kept simple
because Stacks assumes and wants to encourage a community of
open-source-data-management libraries.
The performance and simplicity-oriented guarantee of the Gaia specification is
that when an application submits a write-to
`https://myhub.service.org/store/foo/bar` URL, the application is guaranteed to
be able to read from the `https://myreads.com/foo/bar` URL. Note that, while the
prefix in the write-to url (for example,`myhub.service.org/store`) and the read-from URL
(`https://myreads.com`) are different, the `foo/bar` suffixes are the same.
By default, `putFile()` encrypts information while `getFile()` decrypts it by default. Data stored in an
encrypted format means only the user that stored it can view it. For applications that want other users to
view data, the application should set the `encrypt` option to `false`. And, corresponding, the `decrypt`
option on `getFile()` should also be `false`.
Consistent, identical suffixes allow an application to know _exactly_ where a
written file can be read from, given the read prefix. The Gaia service defines a `hub_info` endpoint to obtain
that read prefix:
```bash
GET /hub_info/
```
The endpoint returns a JSON object with a `read_url_prefix`, for example, if my service returns:
```jsx
{ ...,
"read_url_prefix": "https://myservice.org/read/"
}
```
The data be read with this `getFile()` and this address:
```
https://myservice.org/read/1DHvWDj834zPAkwMhpXdYbCYh4PomwQfzz/0/profile.json
```
The application is guaranteed that the profile is written with `putFile()` this request address:
```
https://myservice.org/store/1DHvWDj834zPAkwMhpXdYbCYh4PomwQfzz/0/profile.json
```
When you use the `putFile()` method it takes the user data and POSTs it to the user's Gaia storage hub.
The data POSTs directly to the hub, the blockchain is not used and no data is stored there. The limit on
file upload is currently 25mb.
## Address-based access-control
Access control in a Gaia storage hub is performed on a per-address basis.
Writes to URLs `/store/<address>/<file>` are allowed only if the writer can
demonstrate that they control _that_ address. This is achieved via the
authentication token which is a message _signed_ by the private key associated
with that address. The message itself is a challenge text, returned via the
`/hub_info/` endpoint.
Reads can be done by everybody. The URLs to a user's app data are in a canonical location in their profile.
For example, here's how you would get data from the [Banter](https://banter.pub/) app, stored under the
Stacks ID `gavin.id`.
### Step 1: Get the bucket URL
```bash
BUCKET_URL="$(curl -sL https://core.blockstack.org/v1/users/gavin.id | jq -r '."gavin.id"["profile"]["apps"]["https://banter.pub"]')" 
echo "$BUCKET_URL"  https://gaia.blockstack.org/hub/16E485MVpR3QpmjVkRgej7ya2Vnzu3jyTR/
```
### Step 2: Get the data
```bash
curl -sL "${BUCKET_URL%%/}/Message/3e866af471d0-4072-beba-06ad1e7ad4bd"
```
```bash
{"content":"Anyone here?","votes":[],"createdBy":"gavin.id",...}
```
This data is public and unencrypted. The same works for encrypted data. Only the holder of the private key used for encryption would be able to decrypt the data.

4
src/pages/ecosystem/contributing.md

@ -148,11 +148,9 @@ sections:
- path: /hello-world-tutorial - path: /hello-world-tutorial
- path: /counter-tutorial - path: /counter-tutorial
- path: /testing-contracts - path: /testing-contracts
- path: /public-registry-tutorial
- path: /signing-transactions
- path: /mining # is an overview page - path: /mining # is an overview page
- title: Technology - title: Technology ## NEEDS UPDATE ONCE STABLE
pages: pages:
- path: /authentication - path: /authentication
pages: pages:

2
src/pages/write-smart-contracts/overview.md

@ -67,7 +67,7 @@ Note some of the key Clarity language rules and limitations.
## Try a tutorial ## Try a tutorial
[@page-reference | grid] [@page-reference | grid]
| /write-smart-contracts/hello-world-tutorial, /write-smart-contracts/counter-tutorial, /write-smart-contracts/signing-transactions, /write-smart-contracts/public-registry-tutorial | /write-smart-contracts/hello-world-tutorial, /write-smart-contracts/counter-tutorial, /build-apps/guides/transaction-signing, /build-apps/tutorials/public-registry
## Explore more ## Explore more

Loading…
Cancel
Save