@ -0,0 +1,8 @@ |
|||
extends: existence |
|||
message: "'%s' should be in uppercase." |
|||
link: 'https://developers.google.com/style/capitalization#capitalization-in-titles-and-headings' |
|||
nonword: true |
|||
level: warning |
|||
scope: heading |
|||
tokens: |
|||
- ':\s[a-z]' |
Before Width: | Height: | Size: 26 KiB After Width: | Height: | Size: 13 KiB |
After Width: | Height: | Size: 271 KiB |
After Width: | Height: | Size: 91 KiB |
After Width: | Height: | Size: 138 KiB |
After Width: | Height: | Size: 185 KiB |
After Width: | Height: | Size: 96 KiB |
After Width: | Height: | Size: 222 KiB |
After Width: | Height: | Size: 32 KiB |
After Width: | Height: | Size: 26 KiB |
Before Width: | Height: | Size: 226 KiB After Width: | Height: | Size: 179 KiB |
After Width: | Height: | Size: 155 KiB |
Before Width: | Height: | Size: 150 KiB After Width: | Height: | Size: 126 KiB |
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 28 KiB |
@ -1,21 +0,0 @@ |
|||
--- |
|||
title: Confirm your address |
|||
description: Learn how to confirm a Stacks address |
|||
--- |
|||
|
|||
## Introduction |
|||
|
|||
We recommend that you confirm your address is correct by going through the following steps in the Stacks Wallet: |
|||
|
|||
If you created a software wallet, using the "New Wallet" option, choose "Restore from Seed Phrase" when you start the Stacks Wallet application, then enter your Seed Phrase, and click "Restore." The address that you see on the next screen should match the address you created earlier. |
|||
|
|||
## For Hardware Wallets: |
|||
|
|||
If you used a hardware wallet originally, you can go through the same process again (clicking "Use a Hardware Wallet" when you first start the Stacks Wallet application), and your hardware wallet should produce the same address every time. If you used a "passphrase" make sure that you use the correct passphrase when checking your wallet address; using a different passphrase will result in generating a different address. (For more information on using passphrases with Trezor, see this page and for information with Ledger, see this page) |
|||
|
|||
Make sure to store your hardware wallet's seed phrase (sometimes referred to as a "Recovery Phrase" or "Recovery Seed") in the correct order safely. We recommend in at least two locations. If you used a passphrase, you should store that as well. |
|||
|
|||
## For Multi-Sig Wallets: |
|||
|
|||
If you used a multi-signature wallet (for advanced users), you will need to re-enter your public keys to check your address (by clicking "Create Multi-signature Wallet"). |
|||
The order that you enter the public keys into the multi-sig wallet is important. If you do not remember the order in which you entered your public keys, please contact hello@StacksToken.com. |
@ -1,71 +0,0 @@ |
|||
--- |
|||
description: Learn about Stacks and decentralization |
|||
icon: BlockstackIcon |
|||
images: |
|||
large: /images/pages/ecosystem.svg |
|||
sm: /images/pages/ecosystem.svg |
|||
--- |
|||
|
|||
# Overview of Stacks |
|||
|
|||
Stacks is a full-stack decentralized computing network that enables a new generation of applications where developers and users can interact fairly and securely. Stacks uses blockchain technology to build protocols and developer tools designed to enable a fair and open Internet that returns digital rights to developers and consumers. |
|||
|
|||
## What is the Stacks Ecosystem? |
|||
|
|||
The Stacks Ecosystem is the legal entities and community structures that support the Stacks technology, the apps that rely on it, and the people that work with it. The ecosystem’s mission is to foster an open and decentralized Internet that establishes and protects privacy, security and freedom for all users. |
|||
|
|||
The documentation on this site focuses on the technologies produced by three entities in the ecosystem. |
|||
|
|||
### Blockstack Public Benefit Corp (PBC) |
|||
|
|||
Blockstack Public Benefit Corp. (PBC) started development of the Stacks |
|||
platform in 2014 and launched an alpha of the platform in early 2017. The |
|||
platform’s development philosophy followed two simple principles. First, create |
|||
backend facilities that allow blockchain applications to be both performant and |
|||
scalable. Second, provide simple, familiar development interfaces to blockchain |
|||
technology. The result of this effort is a technology platform that allows |
|||
developers to: |
|||
|
|||
- Build a blockchain application in any JavaScript framework. The platform does not require learning a new programming language or extending an existing application stack. |
|||
|
|||
- Use well-defined REST endpoints that simplify and encapsulate the blockchain backend. The Stacks JavaScript API reduces blockchain-backed applications to familiar `GET` and `PUT` operations. |
|||
|
|||
- Access the Blockstack’s Naming System (BNS). The system has over 70K users that can immediately start using your application. |
|||
|
|||
- Scale quickly to large, performant production systems. Stacks’s Gaia storage system gives fast, scalable performance on a level comparable to Amazon S3, Google Drive, or Azure. |
|||
|
|||
Using Stacks’s technology developers can start building immediately on the |
|||
blockchain with the knowledge you have today. You won’t need to spend time or |
|||
effort developing expertise in specialized languages or technologies. |
|||
|
|||
### Blockstack Token LLC |
|||
|
|||
Through the 2017 Blockstack token offering, Blockstack Token LLC created the |
|||
Stacks token. This year's hard fork is an especially exciting milestone for the ecosystem because it distributes the first Stacks tokens to existing purchasers and recipients. This hard fork launches the Stacks blockchain v1, and enables the following two features for the Blockstack network: |
|||
|
|||
- Registration of all digital assets and smart contracts for registering digital assets with the Stacks token. |
|||
|
|||
- A genesis block that distributes Stacks tokens to existing purchasers. |
|||
|
|||
A full technical description of the upgrade is available on [the Blockstack forum](https://forum.blockstack.org/t/blockstack-annual-hard-fork-2018/6518). |
|||
|
|||
In future upgrades and hard forks, the blockchain will expand to introduce a new |
|||
scalable consensus algorithm to increase the number of transactions it can |
|||
process. This consensus algorithm is planned to be introduced in additional |
|||
hard forks in 2019. |
|||
|
|||
Additionally, a future Stacks blockchain will support truly decentralized mobile |
|||
applications by removing the need to trust a remote Stacks Node. |
|||
Instead, it will be possible for light clients to calculate the economic weight |
|||
of different Stacks blockchain forks, and identify the fork with the most |
|||
economic activity. Today, light clients rely on other trusted sources for fork |
|||
selection and cannot make that decision independently. For mobile apps this |
|||
enables functionality like looking up names without having to rely on a remote |
|||
Stacks Node. |
|||
|
|||
Finally, Blockstack currently supports relatively simple smart contracts that |
|||
are used to register digital assets on the network. The Stacks blockchain v2 |
|||
will support general-purpose smart contracts written in a non-Turing-complete |
|||
language currently under development. |
|||
|
|||
~> This communication contains forward-looking statements that are based on our beliefs and assumptions and on information currently available to us. In some cases, you can identify forward-looking statements by the following words: "will," "expect," "would," "intend," "believe," or other comparable terminology. Forward-looking statements in this document include, but are not limited to, statements about our plans for developing the platform and future utility for the Stacks Token, our Clarity smart contracting language, and potential mining operations. These statements involve risks, uncertainties, assumptions and other factors that may cause actual results or performance to be materially different. More information on the factors, risks and uncertainties that could cause or contribute to such differences is included in our filings with the SEC, including in the "Risk Factors" and "Management’s Discussion & Analysis" sections of our offering statement on Form 1-A. We cannot assure you that the forward-looking statements will prove to be accurate. These forward-looking statements speak only as of the date hereof. We disclaim any obligation to update these forward-looking statements. |
@ -1,46 +0,0 @@ |
|||
--- |
|||
title: Stacks token holders |
|||
description: Stacks token holder documentation |
|||
--- |
|||
|
|||
## Introduction |
|||
|
|||
The information on this page is intended for **current Stacks (STX) token holders** during Blockstack’s token sale through early 2018. |
|||
|
|||
## Find your token balance and unlock date |
|||
|
|||
~> If you **purchased Stacks tokens during Summer 2019**, the form below will **not** work for your allocation. Please [check your allocation using this tool instead](https://explorer.blockstack.org/verifier). |
|||
|
|||
During your the initial grant process, you should have submitted a public _Stacks (STX) address_ (also known as a _wallet address_) to Blockstack. A STX address is a string of letters and numbers starting with an `SP` or `SM`, for example: `SM3KJBA4RZ7Z20KD2HBXNSXVPCR1D3CRAV6Q05MKT` |
|||
|
|||
If you purchased STX tokens through CoinList, you can find your address at |
|||
[CoinList](https://coinlist.co/distributions). If you submitted your Stacks |
|||
address directly to Blockstack, you can either use the **Restore from Seed |
|||
Phrase** feature on the Stacks Wallet or contact us at <hello@stackstoken.com> for |
|||
help. |
|||
|
|||
You should see a report detailing the tokens allocated to your address and when they unlock: |
|||
|
|||
![](/images/unlocking-address.png) |
|||
|
|||
If you have questions or concerns about your report, please contact [hello@StacksToken.com](mailto:hello@StacksToken.com). |
|||
|
|||
## Understanding the timeline for unlocking your tokens |
|||
|
|||
In October 2018, the Stacks blockchain launched under the STX token. With the |
|||
launch, STX tokens unlock for accredited token holders under a predetermined |
|||
unlocking schedule. The events on the unlocking schedule are the same for each |
|||
token holder, the dates of these events depend on the holders’s purchase date. |
|||
|
|||
The general timeline for unlocking tokens and the capabilities that are |
|||
potentially possible, are as follows: |
|||
|
|||
![](/images/unlocking.png) |
|||
|
|||
Your specific unlock date depends on when you purchased or were granted tokens. |
|||
You can use the Stacks Explorer to discover how many tokens you have |
|||
registered and when they will unlock. |
|||
|
|||
## Have more questions? |
|||
|
|||
For a list of frequent questions and answers about STX tokens, [see the Stacks token FAQs](/references/faqs). |
@ -1,55 +0,0 @@ |
|||
--- |
|||
title: Stacks token |
|||
description: Learn about the native token of Stacks |
|||
icon: StacksIcon |
|||
images: |
|||
large: /images/stx.svg |
|||
sm: /images/stx.svg |
|||
--- |
|||
|
|||
# Learn more about the Stacks token |
|||
|
|||
Stacks is the name of a token developed by Blockstack Token LLC in 2017 and |
|||
activated in the third quarter of 2018. This page discusses a brief history of |
|||
the Stacks token and deployment on the Stacks network as well as the current |
|||
role of the Stacks token. |
|||
|
|||
If you are a developer interested in the specific technical changes related to |
|||
the 2018 launch, see the [announcement in the Blockstack forum](https://forum.blockstack.org/t/blockstack-annual-hard-fork-2018/6518). |
|||
|
|||
## A brief history of the Stacks token |
|||
|
|||
In 2017 Blockstack PBC did a token sale. Participants became token holders when they |
|||
received allocations of Stacks tokens in the genesis block. A genesis block is |
|||
the first block of a blockchain. |
|||
|
|||
During the draft genesis block period token holders setup a seed phrase |
|||
(sometimes referred to as a _recovery phrase_ or a _recovery seed_ using the |
|||
Stacks Wallet software or their own hardware wallet. |
|||
|
|||
It was each token holder’s responsibility to store their own seed phrase in a |
|||
private and secure location. Holders could use their wallet to verify their |
|||
holdings and allocations on the genesis block explorer. Beyond that, while in |
|||
draft state, token holders were in a lock down period. |
|||
|
|||
## State of the Stacks blockchain V1 |
|||
|
|||
The initial block in the Stacks blockchain V1 allocates 1.32 billion |
|||
tokens. The launch is the culmination of two year’s hard work across the greater |
|||
Stacks community. With the launch, Stacks tokens unlock for accredited token |
|||
holders under a predetermined unlocking schedule. The events on the unlocking |
|||
schedule are the same for each investor, **the dates of these events** depend on the |
|||
holder's purchase date. |
|||
|
|||
-> **Note:** If you are a token holder and would like to review your unlocking schedule, visit the [For current token holders](/references/faqs) page in this documentation. |
|||
|
|||
The genesis block launch makes possible the following interactions: |
|||
|
|||
- Token holders can purchase names and namespaces with the Stacks token. Previously, names and namespaces required the purchaser to hold Bitcoin. Initially, this process relies on the Blockstack command-line interface (CLI). |
|||
|
|||
- Application developers can earn Stacks by building an application on the Stacks ecosystem. |
|||
|
|||
- Any Stacks tokens held at the time of launch or after remain usable under the Stacks Blockchain platform. |
|||
|
|||
Finally, in addition to the development of Stacks token, this launch enables |
|||
further development of Stacks Blockchain itself. |
@ -0,0 +1,100 @@ |
|||
--- |
|||
title: Microblocks |
|||
description: Guide to Stacks Microblocks |
|||
icon: TestnetIcon |
|||
images: |
|||
large: /images/pages/testnet.svg |
|||
sm: /images/pages/testnet-sm.svg |
|||
--- |
|||
|
|||
## Introduction |
|||
|
|||
Microblocks are a protocol-level feature of the Stacks blockchain that solve the technical challenge of transaction |
|||
latency. Because each Stacks block is anchored to a Bitcoin block through the [Proof-of-Transfer consensus mechanism][], |
|||
Stacks is necessarily limited to the same block times as the Bitcoin network. Microblocks allow the Stacks blockchain to |
|||
perform state transitions with a high degree of confidence between final settlements against Bitcoin. |
|||
|
|||
Microblocks are a powerful mechanism for developers to create performant, high quality applications on Stacks, while |
|||
still inheriting the security of Bitcoin. |
|||
|
|||
## Transaction states |
|||
|
|||
The [Stacks block production model][] is described in SIP-001. The standard outlines the mechanism by which elected |
|||
block leaders can produce blocks on the Stacks blockchain either by batching transactions or by streaming them. |
|||
Microblocks are the product of the streaming model. |
|||
|
|||
If a block leader has elected to mine microblocks, the leader selects transactions from the mempool and package them |
|||
into microblocks during the current epoch. Transactions included in microblocks don't achieve finality until they've |
|||
been confirmed by an anchor block, but can be assumed to be highly likely to achieve finality in the order in which the leader |
|||
packaged them. |
|||
|
|||
In most blockchains, transactions can be re-ordered and chain history can be re-written with support from enough miners. |
|||
This allows a blockchain to recover from certain types of attacks, as miners can collectively agree to rewrite history |
|||
and omit malicious blocks. As more blocks are added on top of a block that includes a transaction, the likelihood of a |
|||
transaction being reordered decreases. For example, many exchanges wait until at least 3 Bitcoin blocks have been added |
|||
to report a transaction as fully confirmed (3 block confirmation). Microblocks provide between 0 block and 1 block |
|||
confirmation. |
|||
|
|||
-> If a transaction is dependent on a chain state that could by altered by previous transactions with serious |
|||
implications, you should carefully consider whether it should be performed using microblocks. |
|||
|
|||
## Enabling microblocks |
|||
|
|||
Miners can choose to enable or disable microblocks in their mining configuration. As a best practice, miners should enable |
|||
microblock mining. When an application or user submits a transaction, the transaction can include an argument that |
|||
requires the transaction to be in a microblock, an anchor block, or in either. |
|||
|
|||
### Transactions |
|||
|
|||
Transactions include an option that controls if a miner should include them in microblocks or in anchor blocks. The |
|||
[anchor mode][] transaction option is an optional argument that controls whether a transaction must be included in |
|||
an anchor block or a microblock, or is eligible for either. |
|||
|
|||
### Mining |
|||
|
|||
Stacks miners must enable microblocks in their miner configuration to implement the block streaming model. For more |
|||
information, see [mining microblocks][]. |
|||
|
|||
## Developing with microblocks |
|||
|
|||
Stacks allows you to choose how any transaction should be included on the blockchain by the miners. This flexibility |
|||
means you can submit transactions that require low latency processing for inclusion in microblocks, and require that |
|||
highly order-dependent transactions wait for anchor block finality. |
|||
|
|||
### Stacks.js libraries |
|||
|
|||
Stacks.js provides the [AnchorMode][] argument on transaction objects so that your application can set the microblocks |
|||
preference for transactions. |
|||
|
|||
### API |
|||
|
|||
!> API support for microblocks is a work-in-progress. Review the [API documentation][microblocks_api] carefully to |
|||
ensure that you are up-to-date on the latest implementation details for microblocks. |
|||
|
|||
The Stacks Blockchain API exposes microblocks through several endpoints. Please review the |
|||
[Stacks Blockchain API guide][] for more details. |
|||
|
|||
## Best practices |
|||
|
|||
Working with microblocks is a design decision that you must make for your own application. When working with |
|||
microblocks, the following best practices are recommended. |
|||
|
|||
### Handling nonce |
|||
|
|||
Nonce handling with microblocks is challenging because the next account nonce must take into account any nonce values |
|||
included in microblocks, which may not yet be included in an anchor block. The Stacks Blockchain API |
|||
[provides an endpoint][] to retrieve the next nonce for a given principal. |
|||
|
|||
### Application design |
|||
|
|||
The state of microblock transactions should be carefully communicated to users. No transaction is final until it's |
|||
included in an anchor block, and your application design should reflect this. |
|||
|
|||
[proof-of-transfer consensus mechanism]: /understand-stacks/proof-of-transfer |
|||
[stacks block production model]: https://github.com/stacksgov/sips/blob/main/sips/sip-001/sip-001-burn-election.md#operation-as-a-leader |
|||
[mining microblocks]: /understand-stacks/mining#microblocks |
|||
[anchor mode]: /understand-stacks/transactions#anchor-mode |
|||
[anchormode]: https://stacks-js-git-master-blockstack.vercel.app/enums/transactions.anchormode.html |
|||
[stacks blockchain api guide]: /understand-stacks/stacks-blockchain-api#microblocks-support |
|||
[provides an endpoint]: /stacks-blockchain-api#nonce-handling |
|||
[microblocks_api]: https://stacks-blockchain-api-git-feat-microblocks-blockstack.vercel.app/#tag/Microblocks |
@ -0,0 +1,300 @@ |
|||
--- |
|||
title: Billboard |
|||
description: Learn how to store data on-chain and transfer STX tokens with Clarity |
|||
duration: 30 minutes |
|||
experience: intermediate |
|||
tags: |
|||
- tutorial |
|||
images: |
|||
large: /images/pages/billboard.svg |
|||
--- |
|||
|
|||
## Introduction |
|||
|
|||
This tutorial demonstrates how to transfer STX tokens and handle errors in Clarity by building a simple on-chain message |
|||
store. Additionally, this tutorial provides a simple overview of testing a smart contract. This tutorial builds on |
|||
concepts introduced in the [counter tutorial][], and uses [Clarinet][] to develop and test the smart contract. |
|||
|
|||
In this tutorial you will: |
|||
|
|||
- Set up a development environment with Clarinet |
|||
- Define codes for error handling |
|||
- Add a data storage variable with functions to get and set the variable |
|||
- Add a STX transfer function within the variable setter |
|||
- Develop a unit test to verify the contract works as expected |
|||
|
|||
The [final code for this tutorial][] is available in the Clarinet repository. |
|||
|
|||
## Prerequisites |
|||
|
|||
For this tutorial, you should have a local installation of [Clarinet][]. Refer to [Installing Clarinet][] for |
|||
instructions on how to set up your local environment. You should also have a text editor or IDE to edit the Clarity |
|||
smart contract. |
|||
|
|||
For developing the unit test, it's recommended that you have an IDE with Typescript support, such as |
|||
[Visual Studio Code][]. |
|||
|
|||
If you are using Visual Studio Code, you may want to install the [Clarity Visual Studio Code plugin][]. |
|||
|
|||
## Step 1: set up the project |
|||
|
|||
With Clarinet installed locally, open a new terminal window and create a new Clarinet project. Add a smart contract and |
|||
an empty test file to the project: |
|||
|
|||
```sh |
|||
clarinet new billboard-clarity && cd billboard-clarity |
|||
clarinet contract new billboard |
|||
``` |
|||
|
|||
These commands create the necessary project structure and contracts for completing this tutorial. Remember that at |
|||
any point during this tutorial you can use `clarinet check` to check the validity of your Clarity syntax. |
|||
|
|||
## Step 2: create message storage |
|||
|
|||
Open the `contracts/billboard.clar` file in a text editor or IDE. For this tutorial, you'll use the boilerplate comments |
|||
to structure your contract for easy readability. |
|||
|
|||
In this step, you'll add a variable to the contract that stores the billboard message, and define a getter function to |
|||
read the value of the variable. |
|||
|
|||
Under the `data maps and vars` comment, define the `billboard-message` variable. Remember that you must define the type of |
|||
the variable, in this case `string-utf8` to support emojis and extended characters. You must also define the |
|||
maximum length of the variable, for this tutorial use the value `500` to allow for a longer message. You must also |
|||
define the initial value for the variable. |
|||
|
|||
```clarity |
|||
;; data vars |
|||
(define-data-var billboard-message (string-utf8 500) u"Hello world!") |
|||
``` |
|||
|
|||
You also should define a read-only getter function returns the value of the `billboard-message` variable. |
|||
|
|||
```clarity |
|||
;; public functions |
|||
(define-read-only (get-message) |
|||
(var-get billboard-message)) |
|||
``` |
|||
|
|||
These are the required methods for storing and accessing the message on the billboard. |
|||
|
|||
## Step 3: define set message function |
|||
|
|||
Define a method to set the billboard message. Under the public functions, define a `set-message` function. This public |
|||
function takes a `string-utf8` with a max length of `500` as the only argument. Note that the type of the argument |
|||
matches the type of the `billboard-message` variable. Clarity's type checking ensures that an invalid input to the |
|||
function doesn't execute. |
|||
|
|||
```clarity |
|||
;; public functions |
|||
(define-public (set-message (message (string-utf8 500))) |
|||
(ok (var-set billboard-message message)) |
|||
) |
|||
``` |
|||
|
|||
The contract is now capable of updating the `billboard-message`. |
|||
|
|||
## Step 4: transfer STX to set message |
|||
|
|||
In this step, you'll modify the `set-message` function to add a cost in STX tokens, that increments by a set amount each |
|||
time the message updates. |
|||
|
|||
First, you should define a variable to track the price of updating the billboard. This value is in micro-STX. Under the |
|||
`data maps and vars` heading, add a new variable `price` with type `uint` and an initial value of `u100`. The initial |
|||
cost to update the billboard is 100 micro-STX or 0.0001 STX. |
|||
|
|||
```clarity |
|||
;; data vars |
|||
(define-data-var price uint u100) |
|||
``` |
|||
|
|||
You also should define a read-only getter function returns the value of the `price` variable. Read-only functions in |
|||
Clarity are public, and should be grouped with other public functions in the contract. |
|||
|
|||
```clarity |
|||
;; public functions |
|||
(define-read-only (get-price) |
|||
(var-get price) |
|||
) |
|||
``` |
|||
|
|||
It's a best practice to define codes to a descriptive constant for Clarity smart contracts. This makes the code easier |
|||
to understand for readers and makes errors reusable across contract methods. Under the `constants` comment, define a STX |
|||
transfer error constant. Assign the value `u0` to the constant. There is no standard for error constants in Clarity, |
|||
this value is used because it's the first error the contract defines. Error constants should be defined at the top of |
|||
the contract, usually preceding data variables. |
|||
|
|||
```clarity |
|||
;; error consts |
|||
(define-constant ERR_STX_TRANSFER u0) |
|||
``` |
|||
|
|||
Modify the `set-message` function to transfer the amount of STX represented by the current price of the billboard from |
|||
the function caller to the contract wallet address, and then increment the new price. The function is then executed in four steps: transferring STX from the function caller to the contract, updating the `billboard-message` variable, incrementing the |
|||
`price` variable, and returning the new price. |
|||
|
|||
The new `set-message` function uses [`let`][] to define local variables for the function. Two variables are declared, |
|||
the `cur-price`, which represents the current price of updating the billboard, and the `new-price`, which represents the |
|||
incremented price for updating the billboard. |
|||
|
|||
The function then calls the [`stx-transfer?`][] function to transfer the current price of the contract in STX from the |
|||
transaction sender to the contract wallet. This syntax can be confusing: the function call uses the `tx-sender` |
|||
variable, which is the principal address of the caller of the function. The second argument to [`stx-transfer?`][] uses |
|||
the [`as-contract`][] function to change the context's `tx-sender` value to the principal address that deployed the |
|||
contract. |
|||
|
|||
The entire [`stx-transfer?`][] function call is wrapped in the [`unwrap!`][] function, to provide protection from |
|||
the transfer failing. The [`unwrap!`][] function executes the first argument, in this case the [`stx-transfer?`][] |
|||
function. If the execution returns `(ok ...)`, the [`unwrap!`][] function returns the inner value of the `ok`, otherwise |
|||
the function returns the second argument and exits the current control-flow, in this case the `ERR_STX_TRANSFER` error |
|||
code. |
|||
|
|||
If the token transfer is successful, the function sets the new `billboard-message` and updates the `price` variable to |
|||
`new-price`. Finally, the function returns `(ok new-price)`. It's generally a good practice to have public functions |
|||
return `ok` when successfully executed. |
|||
|
|||
-> This function should replace the existing `set-message` function defined previously. |
|||
|
|||
```clarity |
|||
(define-public (set-message (message (string-utf8 500))) |
|||
(let ((cur-price (var-get price)) |
|||
(new-price (+ cur-price u10))) |
|||
|
|||
;; pay the contract |
|||
(unwrap! (stx-transfer? cur-price tx-sender (as-contract tx-sender)) (err ERR_STX_TRANSFER)) |
|||
|
|||
;; update the billboard's message |
|||
(var-set billboard-message message) |
|||
|
|||
;; update the price |
|||
(var-set price new-price) |
|||
|
|||
;; return the updated price |
|||
(ok new-price) |
|||
) |
|||
) |
|||
``` |
|||
|
|||
At this point, the final contract should look like this: |
|||
|
|||
```clarity |
|||
;; error consts |
|||
(define-constant ERR_STX_TRANSFER u0) |
|||
|
|||
;; data vars |
|||
(define-data-var billboard-message (string-utf8 500) u"Hello World!") |
|||
(define-data-var price uint u100) |
|||
|
|||
;; public functions |
|||
(define-read-only (get-price) |
|||
(var-get price) |
|||
) |
|||
|
|||
(define-read-only (get-message) |
|||
(var-get billboard-message) |
|||
) |
|||
|
|||
(define-public (set-message (message (string-utf8 500))) |
|||
(let ((cur-price (var-get price)) |
|||
(new-price (+ cur-price u10))) |
|||
|
|||
;; pay the contract |
|||
(unwrap! (stx-transfer? cur-price tx-sender (as-contract tx-sender)) (err ERR_STX_TRANSFER)) |
|||
|
|||
;; update the billboard's message |
|||
(var-set billboard-message message) |
|||
|
|||
;; update the price |
|||
(var-set price new-price) |
|||
|
|||
;; return the updated price |
|||
(ok new-price) |
|||
) |
|||
) |
|||
``` |
|||
|
|||
Use `clarinet check` to ensure that your Clarity code is well-formed and error-free. |
|||
|
|||
## Step 5: write a contract test |
|||
|
|||
At this point, the contract functions as intended, and can be deployed to the blockchain. However, it's good practice |
|||
to write automated testing to ensure that the contract functions perform in the expected way. Testing can be valuable |
|||
when adding complexity or new functions, as working tests can verify that any changes you make didn't fundamentally |
|||
alter the way the functions behave. |
|||
|
|||
Open the `tests/billboard_test.ts` file in your IDE. In this step, you will add a single automated test to exercise the |
|||
`set-message` and `get-message` functions of the contract. |
|||
|
|||
Using the Clarinet library, define variables to get a wallet address principal from the Clarinet configuration, and the |
|||
balance of that address on the chain. |
|||
|
|||
The functional part of the test is defined using the `chain.mineBlock()` function, which simulates the mining of a |
|||
block. Within that function, the test makes four contract calls (`Tx.contractCall()`), two calls to `set-message` and |
|||
two calls to `get-message`. |
|||
|
|||
Once the simulated block is mined, the test can make assertions about the chain state. This is accomplished using the |
|||
`assertEquals()` function and the `expect` function. In this case, the test asserts that the once the simulated block |
|||
is mined, the block height is now equal to `2`, and that the number of receipts (contract calls) in the block are |
|||
exactly `4`. |
|||
|
|||
The test can then make assertions about the return values of the contract. The test checks that the result of the |
|||
transaction calls to `get-message` match the string values that the calls to `set-message` contain. This covers the |
|||
capability of both contract functions. |
|||
|
|||
Finally, the test asserts that STX are transferred from the transaction caller wallet, covering the price updating and |
|||
token transfer. The test verifies that the addresses of the wallets match the expected addresses, and that the amount |
|||
transferred is the expected amount. |
|||
|
|||
```ts |
|||
import { Clarinet, Tx, Chain, Account, types } from 'https://deno.land/x/clarinet@v0.12.0/index.ts'; |
|||
import { assertEquals } from 'https://deno.land/std@0.90.0/testing/asserts.ts'; |
|||
|
|||
Clarinet.test({ |
|||
name: 'A quick demo on how to assert expectations', |
|||
async fn(chain: Chain, accounts: Map<string, Account>) { |
|||
let wallet_1 = accounts.get('wallet_1')!; |
|||
|
|||
let assetMaps = chain.getAssetsMaps(); |
|||
const balance = assetMaps.assets['STX'][wallet_1.address]; |
|||
|
|||
let block = chain.mineBlock([ |
|||
Tx.contractCall('billboard', 'set-message', [types.utf8('testing')], wallet_1.address), |
|||
Tx.contractCall('billboard', 'get-message', [], wallet_1.address), |
|||
Tx.contractCall('billboard', 'set-message', [types.utf8('testing...')], wallet_1.address), |
|||
Tx.contractCall('billboard', 'get-message', [], wallet_1.address), |
|||
]); |
|||
|
|||
assertEquals(block.receipts.length, 4); |
|||
assertEquals(block.height, 2); |
|||
|
|||
block.receipts[1].result.expectUtf8('testing'); |
|||
|
|||
block.receipts[3].result.expectUtf8('testing...'); |
|||
|
|||
let [event] = block.receipts[0].events; |
|||
let { sender, recipient, amount } = event.stx_transfer_event; |
|||
sender.expectPrincipal('ST1J4G6RR643BCG8G8SR6M2D9Z9KXT2NJDRK3FBTK'); |
|||
recipient.expectPrincipal('ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.billboard'); |
|||
amount.expectInt(100); |
|||
|
|||
assetMaps = chain.getAssetsMaps(); |
|||
assertEquals(assetMaps.assets['STX'][wallet_1.address], balance - 210); |
|||
}, |
|||
}); |
|||
``` |
|||
|
|||
Try running `clarinet test` to see the output of the unit test. |
|||
|
|||
=> You have now learned how to store and update data on chain with a variable, and how to transfer STX tokens from |
|||
a contract caller to a new principal address. Additionally, you have learned how to write a unit test for a simple |
|||
Clarity contract using Clarinet. |
|||
|
|||
[counter tutorial]: /write-smart-contracts/counter-tutorial |
|||
[clarinet]: /write-smart-contracts/clarinet |
|||
[installing clarinet]: /write-smart-contracts/clarinet#installing-clarinet |
|||
[visual studio code]: https://code.visualstudio.com/ |
|||
[final code for this tutorial]: https://github.com/hirosystems/clarinet/tree/master/examples/billboard |
|||
[`let`]: /references/language-functions#let |
|||
[`stx-transfer?`]: /references/language-functions#stx-transfer |
|||
[`as-contract`]: /references/language-functions#as-contract |
|||
[`unwrap!`]: /references/language-functions#unwrap |
|||
[clarity visual studio code plugin]: https://marketplace.visualstudio.com/items?itemName=HiroSystems.clarity-lsp |