Browse Source

feat: updates relating to testnet, clarity, Connect (#540)

* build: update jekyll version

* docs: add Connect docs

* docs: fix list issue

* feat: feedback

* feat: add ruby-version

* feat: bump ruby version

* feat: tableize connect clarity args

* docs: update function signatures for contract calls with connect

* docs: WIP for running a neon miner

* fix: better copy for `sendToSignIn` of connect

* Updates from stacks-blockchain:master (#543)

* updates from stacks-blockchain:master

* address feedback in principals.md

* feat: add notice to use beta authOrigin

* fix: move tx signing notice to 'usage'

Co-authored-by: Aaron Blankstein <aaron@blockstack.com>
feat/clarity-updates
Hank Stoever 5 years ago
committed by GitHub
parent
commit
5e5106cf63
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 1
      .ruby-version
  2. 5
      Gemfile
  3. 27
      Gemfile.lock
  4. 2
      README.md
  5. 90
      _core/smart/neon-node.md
  6. 95
      _core/smart/principals.md
  7. 6
      _data/navigation_learn.yml
  8. 144
      _develop/connect/get-started.md
  9. 25
      _develop/connect/overview.md
  10. 139
      _develop/connect/use-with-clarity.md

1
.ruby-version

@ -0,0 +1 @@
2.5.1

5
Gemfile

@ -1,5 +1,5 @@
source "https://rubygems.org"
ruby RUBY_VERSION
ruby '~> 2.5.1'
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
@ -9,7 +9,7 @@ ruby RUBY_VERSION
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
gem "jekyll", "3.6.3"
gem "jekyll", "3.8.6"
# This is the default theme for new Jekyll sites. You may change this to anything you like.
# gem "minima", "~> 2.0"
@ -24,7 +24,6 @@ group :jekyll_plugins do
gem 'jekyll-paginate', '~> 1.1'
gem 'jekyll-seo-tag'
gem 'jekyll-gist'
gem 'jekyll-livereload'
gem 'jekyll-avatar'
gem 'jekyll-titles-from-headings'
gem 'jekyll-sitemap'

27
Gemfile.lock

@ -5,13 +5,14 @@ GEM
public_suffix (>= 2.0.2, < 5.0)
coderay (1.1.2)
colorator (1.1.0)
concurrent-ruby (1.1.6)
em-websocket (0.5.1)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0.6.0)
eventmachine (1.2.7)
faraday (0.17.1)
multipart-post (>= 1.2, < 3)
ffi (1.11.3)
ffi (1.12.2)
formatador (0.2.5)
forwardable-extended (2.6.0)
guard (2.16.1)
@ -24,16 +25,20 @@ GEM
shellany (~> 0.0)
thor (>= 0.18.1)
http_parser.rb (0.6.0)
jekyll (3.6.3)
i18n (0.9.5)
concurrent-ruby (~> 1.0)
jekyll (3.8.6)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (~> 0.7)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 1.1)
jekyll-watch (~> 2.0)
kramdown (~> 1.14)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 3)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.7.0)
jekyll (>= 3.0, < 5.0)
@ -43,9 +48,6 @@ GEM
octokit (~> 4.2)
jekyll-google-tag-manager (1.0.3)
jekyll (>= 3.3, < 5.0)
jekyll-livereload (0.2.2)
em-websocket (~> 0.5)
jekyll (~> 3.0)
jekyll-paginate (1.1.0)
jekyll-redirect-from (0.15.0)
jekyll (>= 3.3, < 5.0)
@ -59,7 +61,7 @@ GEM
jekyll (>= 3.3, < 5.0)
jekyll-toc (0.12.2)
nokogiri (~> 1.9)
jekyll-watch (1.5.1)
jekyll-watch (2.2.1)
listen (~> 3.0)
kramdown (1.17.0)
liquid (4.0.3)
@ -84,11 +86,11 @@ GEM
pry (0.12.2)
coderay (~> 1.1.0)
method_source (~> 0.9.0)
public_suffix (4.0.1)
public_suffix (4.0.4)
rb-fsevent (0.10.3)
rb-inotify (0.10.0)
rb-inotify (0.10.1)
ffi (~> 1.0)
rouge (2.2.1)
rouge (3.17.0)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
@ -106,12 +108,11 @@ PLATFORMS
DEPENDENCIES
guard
jekyll (= 3.6.3)
jekyll (= 3.8.6)
jekyll-avatar
jekyll-feed (~> 0.6)
jekyll-gist
jekyll-google-tag-manager
jekyll-livereload
jekyll-paginate (~> 1.1)
jekyll-redirect-from
jekyll-seo-tag

2
README.md

@ -149,7 +149,7 @@ To run locally:
2. Build and serve locally.
```
bundle exec jekyll serve --config _config.yml,staticman.yml
bundle exec jekyll serve --config _config.yml,staticman.yml --livereload
```
Use this format to turn on production features:

90
_core/smart/neon-node.md

@ -0,0 +1,90 @@
---
layout: core
description: "Blockstack smart contracting language"
permalink: /:collection/:path.html
---
# Running a Neon Testnet Node
{:.no_toc}
"Neon" is phase 1 of the Stacks 2.0 testnet. In Neon, you can run a Stacks node and participate in proof-of-burn mining.
* TOC
{:toc}
### Download and build stacks-blockchain
The first step is to ensure that you have Rust and the support software installed.
```bash
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
```
From there, you can clone this repository:
```bash
git clone https://github.com/blockstack/stacks-blockchain.git
cd stacks-blockchain
```
Then build the project:
```bash
cargo build
```
Building the project on ARM:
```bash
cargo build --features "aarch64" --no-default-features
```
### Setup your Proof-of-Burn miner
In this phase of the testnet, miners will be burning BTC to participate in leader election. In order to mine, you'll need to configure your node with a BTC keychain, and you'll need to fund it with BTC. We're providing a BTC faucet to make it easy to run a miner.
Let's start by generating a keypair:
```bash
cargo run --bin blockstack-cli generate-sk --testnet
# Output
# {
# secretKey: "b8d99fd45da58038d630d9855d3ca2466e8e0f89d3894c4724f0efc9ff4b51f001",
# publicKey: "02781d2d3a545afdb7f6013a8241b9e400475397516a0d0f76863c6742210539b5",
# stacksAddress: "ST2ZRX0K27GW0SP3GJCEMHD95TQGJMKB7G9Y0X1MH"
# }
```
**TODO**: guidance / update on generating a BTC address from this keypair.
Once you have your BTC address, head over to our testnet website to use the BTC faucet:
**TODO**: URL, guidance for BTC faucet
Now that you have some testnet BTC, you'll need to configure your Stacks node to use this wallet.
Open up the file `testnet/Stacks.toml`. Find the section that starts with `[burnchain]`. Update that section so that it looks like this:
```toml
[burnchain]
chain = "bitcoin"
mode = "neon"
peer_host = "127.0.0.1" # todo(ludo): update URL with neon.blockstack.org when deployed
burnchain_op_tx_fee = 1000
commit_anchor_block_within = 10000
rpc_port = 3000
peer_port = 18444
```
**TODO**: update `peer_host`, and how do you specify your BTC keychain?
### Running your mining node
Now that you're all set up, you can run your miner. In the command line, run:
```bash
cargo testnet ./testnet/Stacks.toml
```
**TODO**: some way of confirming that the miner is running - expected logs, explorer, etc?

95
_core/smart/principals.md

@ -1,9 +1,13 @@
---
<<<<<<< HEAD
layout: smart
description: "Blockstack smart contracting language"
=======
layout: core
>>>>>>> Updates from stacks-blockchain:master (#543)
permalink: /:collection/:path.html
---
# Understanding Principals
# Principals
{:.no_toc}
_Principals_ are a Clarity native type that represents a spending entity. This section discusses principals and how they are used in the Clarity.
@ -14,47 +18,80 @@ _Principals_ are a Clarity native type that represents a spending entity. This s
## Principals and tx-sender
A principal is represented by a public-key hash or multi-signature Stacks address. Assets in Clarity and the Stacks blockchain are "owned" by objects of the principal type; put another way, principal object types may own an asset.
Assets in the smart contracting language and blockchain are
"owned" by objects of the principal type, meaning that any object of
the principal type may own an asset. For the case of public-key hash
and multi-signature Stacks addresses, a given principal can operate on
their assets by issuing a signed transaction on the blockchain. _Smart
contracts_ may also be principals (reprepresented by the smart
contract's identifier), however, there is no private key associated
with the smart contract, and it cannot broadcast a signed transaction
on the blockchain.
A Clarity contract can use a globally defined `tx-sender` variable to
obtain the current principal. The following example defines a transaction
type that transfers `amount` microSTX from the sender to a recipient if amount
is a multiple of 10, otherwise returning a 400 error code.
```scheme
(define-public (transfer-to-recipient! (recipient principal) (amount uint))
(if (is-eq (mod amount 10) 0)
(stx-transfer? amount tx-sender recipient)
(err u400)))
```
A given principal operates on its assets by issuing a signed transaction on the Stacks blockchain. A Clarity contract can use a globally defined `tx-sender` variable to obtain the current principal.
## Smart contracts as principals
The following user-defined function transfers an asset, in this case, tokens, between two principals:
Smart contracts themselves are principals and are represented by the
smart contract's identifier -- which is the publishing address of the
contract _and_ the contract's name, e.g.:
```scheme
'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.contract-name
```
(define (transfer! (sender principal) (recipient principal) (amount int))
(if (and
(not (eq? sender recipient))
(debit-balance! sender amount)
(credit-balance! recipient amount))
'true
'false))
```
The principal's signature is not checked by the smart contract, but by the virtual machine.
For convenience, smart contracts may write a contract's identifier in the
form `.contract-name`. This will be expanded by the Clarity interpreter into
a fully-qualified contract identifier that corresponds to the same
publishing address as the contract it appears in. For example, if the
same publisher key, `SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR`, is
publishing two contracts, `contract-A` and `contract-B`, the fully
qualified identifier for the contracts would be:
```scheme
'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.contract-A
'SZ2J6ZY48GV1EZ5V2V5RB9MP66SW86PYKKQ9H6DPR.contract-B
```
## Smart contracts as principals
Smart contracts themselves are principals and are represented by the smart contract's identifier. You create the identifier when you launch the contract, for example, the contract identifier here is `hanomine`.
But, in the contract source code, if the developer wishes
to call a function from `contract-A` in `contract-B`, they can
write
```bash
clarity-cli launch hanomine /data/hano.clar /data/db
```scheme
(contract-call? .contract-A public-function-foo)
```
A smart contract may use the special variable `contract-name` to refer to its own principal.
This allows the smart contract developer to modularize their
applications across multiple smart contracts _without_ knowing
the publishing key a priori.
To allow smart contracts to operate on assets it owns, smart contracts may use the special `(as-contract expr)` function. This function executes the expression (passed as an argument) with the `tx-sender` set to the contract's principal, rather than the current sender. The `as-contract` function returns the value of the provided expression.
In order for a smart contract to operate on assets it owns, smart contracts
may use the special `(as-contract ...)` function. This function
executes the expression (passed as an argument) with the `tx-sender`
set to the contract's principal, rather than the current sender. The
`as-contract` function returns the value of the provided expression.
For example, a smart contract that implements something like a "token faucet" could be implemented as so:
For example, a smart contract that implements something like a "token
faucet" could be implemented as so:
```cl
```scheme
(define-public (claim-from-faucet)
(if (is-none? (fetch-entry claimed-before (tuple (sender tx-sender))))
(let ((requester tx-sender)) ;; set a local variable requester = tx-sender
(begin
(insert-entry! claimed-before (tuple (sender requester)) (tuple (claimed 'true)))
(as-contract (stacks-transfer! requester 1)))))
(err 1))
(insert-entry! claimed-before (tuple (sender requester)) (tuple (claimed true)))
(as-contract (stx-transfer? u1 tx-sender requester))))
(err 1)))
```
In this example, the public function `claim-from-faucet`:
@ -64,6 +101,6 @@ In this example, the public function `claim-from-faucet`:
* Adds an entry to the tracking map.
* Uses `as-contract` to send 1 microstack
Contract writers can use the primitive function `is-contract?` to determine whether a given principal corresponds to a smart contract.
Unlike other principals, there is no private key associated with a smart contract. As it lacks a private key, a Clarity smart contract cannot broadcast a signed transaction on the blockchain.
Unlike other principals, there is no private key associated with a
smart contract. As it lacks a private key, a Clarity smart contract
cannot broadcast a signed transaction on the blockchain.

6
_data/navigation_learn.yml

@ -12,6 +12,12 @@
- develop/deploy-tips
- android/tutorial
- ios/tutorial
- title: Connect
docs:
- develop/connect/overview
- develop/connect/get-started
- develop/connect/use-with-clarity
- title: Data sharing & collaboration
docs:

144
_develop/connect/get-started.md

@ -0,0 +1,144 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Get Started
{:.no_toc}
Blockstack Connect is a Javascript library for integrating your application with Stacks v2. With Connect, you get some big benefits:
<!-- - -->
* TOC
{:toc}
## Installation
With yarn:
```bash
yarn add @blockstack/connect
```
With npm:
```bash
npm install --save @blockstack/connect
```
## Usage
### AuthOptions
Every major method you'll use with `connect` requires you to pass some options, like the name and icon of your app, and what to do when authentication is finished. In practice, this means you need to define these options, and pass them to the various API methods.
The exact interface you'll use [is defined as](https://github.com/blockstack/connect/blob/master/src/auth.ts#L12:L24):
```typescript
export interface AuthOptions {
redirectTo: string;
finished: (payload: FinishedData) => void;
sendToSignIn?: boolean;
userSession?: UserSession;
appDetails: {
name: string;
icon: string;
};
}
```
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
If you're using `connect` in a React app, then the best option is to include `connect`'s React Provider and hooks in your React app.
First, setup the `Connect` provider at the "top-level" of your app - probably next to wherever you would put a Redux provider, for example.
```javascript
import { Connect } from '@blockstack/connect';
const authOptions = {
redirectTo: '/',
finished: ({ userSession }) => {
console.log(userSession.loadUserData());
},
appDetails: {
name: 'My Cool App',
icon: 'https://example.com/icon.png',
},
};
const App = () => (
<Connect authOptions={authOptions}>
// the rest of your app's components
</Connect>
)
```
Later, when you want to begin the onboarding process, use the `useConnect` hook to get `connect`'s `doOpenAuth` method.
```javascript
import { useConnect } from '@blockstack/connect';
const SignInButton = () => {
const { doOpenAuth } = useConnect();
return (
<Button onClick={doOpenAuth}>
Sign In
</Button>
)
}
```
#### Sign In
To send the user straight to sign in, call `doOpenAuth(true)`.
### In ES6 (non-React) apps
If you aren't using React, or just want a simpler API, then you can use the `showBlockstackConnect` method.
```javascript
import { showBlockstackConnect } from '@blockstack/connect';
const authOptions = { /** See docs above for options */ };
showBlockstackConnect(authOptions);
```
#### Sign In
To send the user straight to sign in, include `sendToSignIn: true` in your `authOptions`.
#### Note about dependency size:
If you're building a non-React app, note that importing `@blockstack/connect` will add React dependencies to your JavaScript bundle. We recommend using something like [Webpack resolve aliases](https://webpack.js.org/configuration/resolve/) to replace `react` with `preact` in production, which reduces your bundle size. Check out [our own webpack.config.js file](https://github.com/blockstack/ux/blob/fix/connect-modal-accessibility/packages/connect/webpack.config.js#L87:L95) to see how we use this for production builds.
If you're using the hosted version of `@blockstack/connect` (described below), then you already have a production-optimized bundle.
### Using a hosted version of `@blockstack/connect`
If you aren't using ES6 imports, you can still use `connect`! We package the library so that it can be automatically used with [unpkg](https://unpkg.com/).
First, include the script in your HTML:
```html
<script src="https://unpkg.com/@blockstack/connect" />
```
Then, you can use API methods under the `blockstackConnect` global variable:
```javascript
const authOptions = { /** See docs above for options */ };
blockstackConnect.showBlockstackConnect(authOptions);
```

25
_develop/connect/overview.md

@ -0,0 +1,25 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Overview
{:.no_toc}
* TOC
{:toc}
Blockstack Connect is a JavaScript library for integrating your application with Stacks v2. With Connect, you get some big benefits:
- Pre-built UI to introduce your users to Blockstack, before they authenticate
- Integration with our new authenticator
- Ability to interact with the Stacks 2.0 blockchain, with support for smart contracts and other transactions.
## Demo
To get a test feel for the user experience of using Connect, you can use [Banter](https://banter.pub).
## How does this compare to `blockstack.js`?
Although [`blockstack.js`](https://github.com/blockstack/blockstack.js) exposes everything you need to handle authentication with Blockstack, there is still the hard problem of getting users familiar with the the paradigm of authentication that is privacy-first and self-sovereign. Many apps implement their own dialogues before authentication, which explain what Blockstack is and why they use it.
`@blockstack/connect` provides developers with a plug-and-play API that is simple to use, and provides great, out-of-the-box education that end-users can understand.

139
_develop/connect/use-with-clarity.md

@ -0,0 +1,139 @@
---
layout: learn
permalink: /:collection/:path.html
---
# Usage with Clarity
{:.no_toc}
With Connect, you can interact with the Stacks 2.0 blockchain. You can allow your users to send transactions and interact with smart contracts.
* TOC
{:toc}
## 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. It's important that users remain 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 contract address, function name, and specific arguments. Your users get the chance to see these details, and then sign and broadcast the transaction in a single click. Their transaction will be securely signed and broadcasted onto the Stacks blockchain. After this is done, a callback is fired to allow you to update your app.
## Usage
<div class="uk-card uk-card-default uk-card-body">
<h5 class="uk-card-title">Transaction signing is still in progress</h5>
<p>
The Stacks 2.0 blockchain is still in testnet, and our web app integration is also still in beta. In order to use transaction signing in your application, you need to use the configuration `authOrigin` with `@blockstack/connect`.
</p>
<pre>
<code>
const options = {
// your other options
authOrigin: 'https://deploy-preview-301--stacks-authenticator.netlify.app'
};
</code>
</pre>
</div>
### `ContractCallOptions`
When signing a transaction, you need to specify a few details. Here is the exact interface that describes what options you have:
```ts
export interface ContractCallOptions {
contractAddress: string;
functionName: string;
contractName: string;
functionArgs?: any[];
authOrigin?: string;
userSession?: UserSession;
appDetails?: AuthOptions['appDetails'];
finished?: (data: FinishedTxData) => void;
}
```
parameter | type | default | optional | description
---|---|---|---|---
contractAddress | string | | false | The Stacks address that published this contract
contractName | string | | false | The name that was used when publishing this contract
functionName | string | | false | The name of the function you're calling. This needs to be a [public function](/core/smart/clarityRef.html#define-public).
functionArgs | array | | false | The arguments you're calling the function with. You'll need to provide the Clarity type with each argument. See the below section for details.
userSession | UserSession | | true | A `UserSession` instance
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.
#### Passing Clarity types with function arguments
To be able to serialize your transaction properly, you need to provide the appropriate Clarity type with each argument. These types are named the same as they are in Clarity. The `value` that you pass must be a string. The types you can pass are:
- `uint` - i.e. `"240"`
- `int` - i.e. `"12"`
- `bool` - can be "true", "false", "0" or "1"
- `buff` - i.e. `"asdf"`
- `principal` - This can be a contract principal, or a standard principal. Examples: `"ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ"` or `"ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ.my-contract"`.
Using these types, each argument is an object with the keys `type` and `value`. For example:
```js
const functionArguments = [
{
type: 'buff',
value: 'hello, world'
},
{
type: 'uint',
value: '1'
}
]
```
If you're using Typescript, these Clarity types can be imported as `ContractCallArgumentType` from `@blockstack/connect`.
### Usage in ES6 (non-React) apps
```ts
import { openContractCall } from '@blockstack/connect';
// Here's an example of options:
const myStatus = 'hey there';
const options = {
contractAddress: 'ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ',
contractName: 'status',
functionName: 'write-status!',
functionArgs: [
{
type: 'buff',
value: myStatus,
}
],
appDetails: {
name: 'SuperApp',
icon: 'https://example.com/icon.png'
},
finished: (data) => {
console.log('TX ID:', data.txId);
console.log('Raw TX:', data.txRaw);
},
};
await openContractCall(opts);
```
### Usage in React Apps
Make sure you follow the [setup instructions](/develop/connect/get-started.html#in-react-apps) first. When you're using `useConnect`, you don't have to specify `appDetails` - we'll pick that up from your existing configuration.
```tsx
import { useConnect } from '@blockstack/connect';
const MyComponent = () => {
const { doContractCall } = useConnect();
const onClick = async () => {
const opts = { /** See examples above */};
await doContractCall(opts);
}
return (
<span onClick={onClick}>Call my contract</span>
);
};
```
Loading…
Cancel
Save