Browse Source

feat: improve tx signing guide, add dependencies install

feat/build-apps-rebase
Mark Hendrickson 4 years ago
committed by Thomas Osmonson
parent
commit
cd8bae71a6
  1. 14
      src/pages/build-apps/guides/authentication.md
  2. 9
      src/pages/build-apps/guides/data-storage.md
  3. 270
      src/pages/build-apps/guides/transaction-signing.md

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

@ -49,6 +49,14 @@ The first two of these functions are particularly relevant to [data storage with
[Learn more about keypairs](#key-pairs) used by authentication. [Learn more about keypairs](#key-pairs) used by authentication.
## Install dependency
The following dependency must be installed:
```
npm install @stacks/connect
```
## Initiate userSession object ## Initiate userSession object
Apps keep track of user authentication state with the `userSession` object, initiated with the `UserSession` and `AppConfig` classes: Apps keep track of user authentication state with the `userSession` object, initiated with the `UserSession` and `AppConfig` classes:
@ -144,6 +152,12 @@ If the user has indeed confirmed authentication in the context of a popup window
It will then trigger the `finished` function provided above, which can be used similarly to save the user's information into their session as retrieved with `userSession.loadUserData()`. It will then trigger the `finished` function provided above, which can be used similarly to save the user's information into their session as retrieved with `userSession.loadUserData()`.
## Usage in React Apps
Import the `useConnect` from the `connect` package to integrate transaction signing more seamlessly into React apps.
TODO: Add guidance for authentication with React
## Key pairs ## Key pairs
Authentication with Stacks makes extensive use of public key cryptography generally and ECDSA with the `secp256k1` curve in particular. Authentication with Stacks makes extensive use of public key cryptography generally and ECDSA with the `secp256k1` curve in particular.

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

@ -19,6 +19,15 @@ Storing data off the Stacks blockchain ensures that apps can provide users with
[See the Todos app tutorial](/build-apps/tutorials/todos) for a concrete example of this functionality in practice. [See the Todos app tutorial](/build-apps/tutorials/todos) for a concrete example of this functionality in practice.
## Install dependencies
The following dependencies must be installed:
```
npm install @stacks/connect
npm install @stacks/storage
```
## Initiate session ## Initiate session
Users must authenticate to an app before the `storage` package will work to save or retrieve data on their behalf. Users must authenticate to an app before the `storage` package will work to save or retrieve data on their behalf.

270
src/pages/build-apps/guides/transaction-signing.md

@ -15,64 +15,60 @@ This guide explains how to prompt users to sign transactions and broadcast them
Transaction signing provides a way for users execute [Clarity smart contracts](/write-smart-contracts/overview) that are relevant to your app then handle the result immediately. Transaction signing provides a way for users execute [Clarity smart contracts](/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. Users can sign transactions that exchange fungible or non-fungible tokens with upfront guarantees that help them retain control over their digital assets.
There are three types of transactions:
1. STX transfer
2. Contract deployment
3. Contract execution
[See the public registry tutorial](/build-apps/tutorials/public-registry) for a concrete example of this functionality in practice. [See the public registry tutorial](/build-apps/tutorials/public-registry) for a concrete example of this functionality in practice.
## How it works ## Install dependency
For your app's users to be able to execute a smart contract function, they need to sign and broadcast a transaction. The following dependency must be installed:
```
npm install @stacks/connect
```
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. ## Initiate session
Connect allows you to open the authenticator with parameters indicating the details of the transaction - like the smart Users must authenticate to an app before the `connect` package will work to prompt them for signing and broadcasting transactions to the Stacks blockchain with an authenticator such as [the Stacks Wallet](https://blockstack.org/wallet).
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.
## Calling Clarity Contract Functions [See the authentication guide](/build-apps/guides/authentication) before proceeding to integrate the following transaction signing capabilities in cases where `userSession.isUserSignedIn()` returns `true`.
Once you have a Clarity smart contract built and deployed, you'll naturally want to allow your app's users to interact ## Prompt to transfer STX
with it.
To initiate a contract call transaction, use the `openContractCall` function. Call the `openSTXTransfer` function provided by the `connect` package to trigger the display of a transaction signing prompt for transferring STX:
```tsx ```tsx
import { openContractCall } from '@stacks/connect'; import { openSTXTransfer } from '@stacks/connect';
const myStatus = 'hey there'; openSTXTransfer({
const options = { recipient: 'ST2EB9WEQNR9P0K28D2DC352TM75YG3K0GT7V13CV',
contractAddress: 'ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ', amount: '100',
contractName: 'status', memo: 'Reimbursement',
functionName: 'write-status!',
functionArgs: [
{
type: 'buff',
value: myStatus,
},
],
authOrigin, authOrigin,
appDetails: { appDetails: {
name: 'SuperApp', name: 'My App',
icon: 'https://example.com/icon.png', icon: window.location.origin + '/my-app-logo.svg',
}, },
finished: data => { finished: data => {
console.log('TX ID:', data.txId); console.log('Transaction ID:', data.txId);
console.log('Raw TX:', data.txRaw); console.log('Raw transaction:', data.txRaw);
}, },
}; });
await openContractCall(options);
``` ```
There are some required parameters needed when calling `openContractCall`. Here is the exact interface which describes what options you have: Several parameters are available for calling `openSTXTransfer`. Here's the exact interface for them:
```tsx ```tsx
interface ContractCallOptions { interface STXTransferOptions {
contractAddress: string; recipient: string;
functionName: string; amount: string;
contractName: string; memo?: string;
functionArgs?: any[];
authOrigin?: string; authOrigin?: string;
appDetails: { appDetails: {
name: string; name: string;
@ -82,75 +78,44 @@ interface ContractCallOptions {
} }
``` ```
| parameter | type | optional | description | | parameter | type | required | description |
| --------------- | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ---------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| contractAddress | string | false | The Stacks address that published this contract | | recipient | string | true | STX address for recipient of transfer |
| contractName | string | false | The name that was used when publishing this contract | | amount | string | true | Amount of microstacks (µSTX, with 1,000,000 µSTX per 1 STX) to be transferred provided as string to prevent floating point errors. |
| functionName | string | false | The name of the function you're calling. This needs to be a [public function](/references/language-functions#define-public). | | appDetails | object | true | Dictionary that requires `name` and `icon` for app |
| 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. Defaults to `[]`. | | finished | function | true | Callback executed by app when transaction has been signed and broadcasted. It received an object back with `txId` and `txRaw` properties, both of which are strings. |
| appDetails | object | false | A dictionary that includes `name` and `icon` | | memo | string | false | Optional memo for inclusion with transaction |
| 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 | false | URL of authenticator to use for prompting signature and broadcast. Defaults to `https://wallet.hiro.so` for the Stacks Wallet, which is handled by the Stacks Wallet browser extension if installed. |
| 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"`. |
### 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` - for example `"240"` ## Prompt to deploy smart contract
- `int` - for example `"12"`
- `bool` - can be `true`, `false`, `0` or `1`
- `buff` - for example `"asdf"`
- `principal` - This can be a contract principal, or a standard principal.
[Read more about principals](/write-smart-contracts/principals). Examples: `"ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ"`
or `"ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ.my-contract"`.
Using these types, each argument is an object with the keys `type` and `value`. For example: Call the `openContractDeploy` function provided by the `connect` package to trigger the display of a transaction signing prompt for deploying a smart contract:
```tsx ```tsx
const functionArguments = [ import { openContractDeploy } from '@blockstack/connect';
{
type: 'buff',
value: 'hello, world',
},
{
type: 'uint',
value: '1',
},
];
```
If you're using TypeScript, these Clarity types can be imported as `ContractCallArgumentType` from `@stacks/connect`.
## Stacks (STX) Token Transfers
STX token transfers can be initiated with the `openSTXTransfer` function.
```tsx const codeBody = '(begin (print "hello, world"))';
import { openSTXTransfer } from '@stacks/connect';
openSTXTransfer({ openContractDeploy({
recipient: 'ST2EB9WEQNR9P0K28D2DC352TM75YG3K0GT7V13CV', contractName: 'my-contract-name',
amount: '100', codeBody,
memo: 'Testing STX Transfers!',
authOrigin,
appDetails: { appDetails: {
name: 'SuperApp', name: 'My App',
icon: 'https://example.com/icon.png', icon: window.location.origin + '/my-app-logo.svg',
}, },
finished: data => { finished: data => {
console.log(data.txId); console.log('Transaction ID:', data.txId);
console.log('Raw transaction:', data.txRaw);
}, },
}); });
``` ```
When calling `openSTXTransfer`, you need to specify a few details. Here are the options you have: Several parameters are available for calling `openContractDeploy`. Here's the exact interface for them:
```tsx ```tsx
interface STXTransferOptions { interface ContractDeployOptions {
recipient: string; codeBody: string;
amount: string; contractName: string;
memo?: string;
authOrigin?: string; authOrigin?: string;
appDetails: { appDetails: {
name: string; name: string;
@ -160,43 +125,55 @@ interface STXTransferOptions {
} }
``` ```
| parameter | type | optional | description | | parameter | type | required | description |
| ---------- | -------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------ | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| recipient | string | false | The STX Address for the recipient of this STX transfer | | codeBody | string | true | Clarity source code for contract |
| 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. | | contractName | string | true | Name for contract |
| memo | string | true | An optional memo to include in the transaction. | | appDetails | object | true | Dictionary that requires `name` and `icon` for app |
| appDetails | object | false | A dictionary that includes `name` and `icon` | | finished | function | true | Callback executed by app when transaction has been signed and broadcasted. It received an object back with `txId` and `txRaw` properties, 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 | false | URL of authenticator to use for prompting signature and broadcast. Defaults to `https://wallet.hiro.so` for the Stacks Wallet, which is handled by the Stacks Wallet browser extension if installed. |
| authOrigin | string | true | Location of the authenticator to use for signing. Defaults `"https://app.blockstack.org"`. |
## Deploy smart contract -> Contracts will deploy to the Stacks address of the authenticated user.
To allow your app's users to deploy Clarity smart contracts, use the `openContractDeploy` method. ## Prompt to execute contract
```tsx Call the `openContractCall` function provided by the `connect` package to trigger the display of a transaction signing prompt for executing a contract:
import { openContractDeploy } from '@blockstack/connect';
const codeBody = '(begin (print "hello, world"))'; ```tsx
import { openContractCall } from '@stacks/connect';
openContractDeploy({ const options = {
contractName: 'my-contract-name', contractAddress: 'ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ',
codeBody, contractName: 'status',
functionName: 'write-status!',
functionArgs: [
{
type: 'buff',
value: 'hello world',
},
],
authOrigin,
appDetails: { appDetails: {
name: 'SuperApp', name: 'My App',
icon: 'https://example.com/icon.png', icon: window.location.origin + '/my-app-logo.svg',
}, },
finished: data => { finished: data => {
console.log(data.txId); console.log('Transaction ID:', data.txId);
console.log('Raw transaction:', data.txRaw);
}, },
}); };
await openContractCall(options);
``` ```
Here is the interface for the options you can provide to `openContractDeploy`: Several parameters are available for calling `openContractCall`. Here's the exact interface for them:
```tsx ```tsx
interface ContractDeployOptions { interface ContractCallOptions {
codeBody: string; contractAddress: string;
functionName: string;
contractName: string; contractName: string;
functionArgs?: any[];
authOrigin?: string; authOrigin?: string;
appDetails: { appDetails: {
name: string; name: string;
@ -206,21 +183,56 @@ interface ContractDeployOptions {
} }
``` ```
| parameter | type | optional | description | | parameter | type | required | description |
| ------------ | -------- | -------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | --------------- | -------- | -------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| codeBody | string | false | The Clarity source code for this contract | | contractAddress | string | true | Stacks address to which contract is deployed |
| contractName | string | false | The name for this contract | | contractName | string | true | Name of contract to sign |
| appDetails | object | false | A dictionary that includes `name` and `icon` | | functionName | string | true | Name of function for signing / execution, which needs to be a [public function](/references/language-functions#define-public). |
| 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. | | functionArgs | array | true | Arguments for calling the function. [Provide the Clarity type with each argument](#passing-clarity-types-with-function-arguments). Defaults to `[]`. |
| 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"`. | | appDetails | object | true | Dictionary that requires `name` and `icon` for app |
| finished | function | true | Callback executed by app when transaction has been signed and broadcasted. It received an object back with `txId` and `txRaw` properties, both of which are strings. |
| authOrigin | string | false | URL of authenticator to use for prompting signature and broadcast. Defaults to `https://wallet.hiro.so` for the Stacks Wallet, which is handled by the Stacks Wallet browser extension if installed. |
### Passing Clarity types with function arguments
To serialize your transaction properly, you'll need to provide an appropriate Clarity type for each function argument.
These types are named the same as in Clarity and must be passed as strings:
- `uint`: Unsigned integer (e.g. `"240"`)
- `int`: Signed integer (e.g. `"12"`)
- `bool`: Boolean (e.g. `true` or `false`, `0` or `1`)
- `buff`: Buffer (e.g. `"hello world"`)
- `principal`: [Contract or standard principal](/write-smart-contracts/principals) (e.g. `"ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ"`) or `"ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ.my-contract"`.
Argument are provided in an array of objects with keys `type` and `value`:
```tsx
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 `@stacks/connect`.
## Usage in React Apps ## Usage in React Apps
Make sure you follow the [setup instructions](/authentication/building-todo-app#onboard-into-your-first-stacks-app) first. When you're using Import the `useConnect` from the `connect` package to integrate transaction signing more seamlessly into React apps.
`useConnect`, you don't have to specify `appDetails` - we'll pick that up from your existing configuration.
Each transaction signing method is exposed through the `useConnect` hook, but they're prefixed with `do` instead of Each transaction signing method is itself available as a function returned by `useConnect` though prefixed with `do` for consistency with React action naming standards:
`open`, to remain consistent with our React action naming standards.
- `openContractCall` as `doContractCall`
- `openSTXTransfer` as `doSTXTransfer`
- `openContractDeploy` as `doContractDeploy`
Use these functions with the same parameters as outlined above. However, you don't have to specify `appDetails` since they are detected automatically if `useConnect` has been used already for authentication.
```tsx ```tsx
import { useConnect } from '@stacks/connect'; import { useConnect } from '@stacks/connect';
@ -239,8 +251,10 @@ const MyComponent = () => {
}; };
``` ```
## Network settings ## Change network
TBD: Instructions for changing between mainnet, testnet and local networks
TBD: instructions on toggling network ## Request testnet STX from faucet
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. You may find it useful to request testnet STX from [the faucet](https://testnet.blockstack.org/faucet) while developing your app with the Stacks testnet.

Loading…
Cancel
Save