While we put the final touches on launching a public testnet, we wanted to share how you can get started building a Clarity app.
Here’s the screenshare version:
This is not official documentation! Things will change quickly, and some of these instructions may get out of date.
While we’ve been working on Clarity and the new Stacks Blockchain for a long time, a few recent developments have unlocked new abilities for using them. This guide is meant to introduce you to many of these new pieces, and by the end, you should be able to use them to build your own app.
Basic dependencies
Before getting started, you need a development environment with Rustup, Git, and Yarn installed.
Setting up the Stacks Blockchain
You’ll need to run a Stacks node locally on your machine.
If you haven’t already, follow the setup instructions for downloading and building the Stacks Blockchain.
Once you’ve done that, use Git to checkout the feature/genesis branch:
git checkout feature/genesis
cargo build
Next, we’re going to customize the genesis block, to give a bunch of STX to an address that we control.
Open up Stacks.toml, and add the following lines to the bottom:
[[mstx_balance]]
address = "ST3SX4MA9EXP7YNEMQ1HW2RPC6P6YR3E74S6XEYEY"
amount = 100000000
Create a “mempool” folder on your machine. Later on, we’ll drop files into this folder, and it’ll include those transactions in the Blockchain.
You can use whatever file you want. If you’re on unix, something like this could work:
mkdir -p /Users/myname/stacks/mempool
Replace myname with your username, or use whatever folder you want. Then, take whatever folder you just created, and replace the mempool section in Stacks.toml with that folder:
[mempool]
path = "/Users/myname/stacks/mempool"
Cool, we can run the chain now! In a terminal, run:
cargo run --bin blockstack-core testnet Stacks.toml
Our Stacks node is running! Feel free to stop and restart this whenever you want. When you restart it, it’ll start the chain from scratch.
Publish the demo app smart contract
We have a simple Clarity contract inside the UX monorepo, located at packages/test-app/contracts/stream.clar. We need to publish it.
In your terminal, in the Stacks node folder, run this command to generate a “publish contract” transaction:
cargo run --bin blockstack-cli publish ef52e331703f06aa81774dcf209580ca07c7925ed0b22302230d6317dab6b0f801 0 0 stream ~/blockstack/ux/packages/test-app/contracts/stream.clar --testnet | xxd -r -p > tx1.bin
Make sure you replace the path for stream.clar with whatever is correct on your machine.
Next, move the tx1.bin file we just created into your mempool:
cp tx1.bin /Users/myname/stacks/mempool
Replace the second folder with your correct mempool folder, from the earlier step.
Use a web app with your Clarity contract
Now, you can try out our demo application at our hosted preview site.
First, login with Blockstack.
A note about weird behavior with nonce
Currently, we don’t have a good mechanism to keep track of the nonce of an account. Because of this, the authenticator always uses a nonce of 0. If you want to broadcast more than one transaction from the same account, you’ll have to restart your Stacks node. That also means you’ll need to re-deploy the contract. Or, if you’re running these apps locally, you can manually bump up the nonce here. This will be fixed soon!
I also recommend you create a new ID, otherwise you might end up with a weird state with nonce. We’ll have that all working appropriately when we have a public testnet.
You can start using the ‘Smart Contract’ widgets.
Note: the faucet only works when running the app locally.
Hello, Clarity
Click the button in the ‘Hello Clarity’ section. This will open up the authenticator, and prompt you to sign a transaction that calls the say-hi method. The only thing this function does is return (ok hello-world.
Confirm the transaction, and you’ll have the TX hash copied onto your clipboard. To broadcast this transaction, we need to add it to our local mempool folder. Run this in the terminal:
echo "my-clipboard-tx-hash" | xxd -p -r > tx2.bin
cp tx2.bin /Users/myname/stacks/mempool
Be sure to replace the my-clipboard-tx-hash with your actual TX hash, and replace the mempool folder with the one you made earlier.
Now, switch over to the terminal running your Stacks node. You should see a log message that indicates your transaction was processed, and you should see the result of this function!
Status
We also have a simple function that lets you store a “status” in the state of this smart contract. The stream.clar contract has a statuses map, which stores a single status for each “sender” who called the function.
Enter your status in the ‘Status’ input. Click ‘Submit’, and view the transaction details in the authenticator’s popup. You should be able to verify that the status you’re sending is the same as what you entered in the demo app.
Confirm the transaction in the authenticator, then copy the same steps from the “Hello Clarity” section above for including the transaction in your Stacks node.
When it’s confirmed, you should see something like this:
Run the demo app on your machine:
Now that you’ve tried out the basic of the Stacks node, you can start playing around with a real app that uses Clarity smart contracts!
We’ll be using the code in the UX Monorepo for this section.
Clone the repo and checkout the new branch:
git clone [email protected]:blockstack/ux.git
cd ux
git checkout feat/clarity
Next, we install dependencies. We need to specify the BLOCKSTACK_CORE_SOURCE_BRANCH
environment variable when running yarn
, because it will instruct clarity-js-sdk
to build binaries from source. This ensures you have the most up-to-date binaries. As these things mature, we’ll make sure that we always provide the right binaries for every platform out of the box, so you don’t have to install from source.
BLOCKSTACK_CORE_SOURCE_BRANCH="feature/genesis" yarn
Now, you can run everything:
yarn dev
This runs three apps:
- A React demo app at http://localhost:3000, for testing out the authenticator
- The authenticator, running at http://localhost:8080
- A small node.js server with a STX faucet, running at http://localhost:5555
Now that your app is running, you can repeat all of the above steps to test out the web app with a Clarity contract!
Updating the Clarity Contract and running tests
Now, you’ll start to learn about how you can actually extend this example app to write your own Clarity apps.
In an editor, the UX monorepo, and view packages/test-app/contracts/stream.clar . This is our example Clarity contract.
We have lots of other examples for other contracts, and I’d encourage you to read them in order to learn:
- clarity-js-sdk tutorial contracts
- BNS - the BNS smart contract that will be included in the genesis block of the Stacks Blockchain
- Rust docs for Clarity - the ‘source of truth’ for the Clarity language spec
You can also open up packages/test-app/tests/contracts.test.ts to see the (basic) tests we have setup.
When you’re toying with this contract, it helps to run the tests in watch mode:
yarn lerna run test:watch --stream --scope test-app
One of these tests checks to make sure you have a valid Clarity contract (i.e. no type or syntax errors).
The other tests actually invoke Clarity functions, and then test that the result is correct.
I’d encourage you to dive into clarity-js-sdk to see how you can write tests for your own code.
Update the demo app to use your new code
The demo app is built with React, and if you have a basic understanding of React, you can see how we’re passing parameters to the Authenticator to sign a transaction.
In an editor, open packages/test-app/components/cards/write-status.tsx . This component uses @blockstack/connect, using a new function called doContractCall.
Note: the API for signing transactions with @blockstack/connect is just a prototype. Expect this functionality to change a lot in the coming weeks, which may introduce breaking changes. We’ll keep you updated!
The main code to pay attention to looks like this:
const { doContractCall } = useConnect();
const status = 'hey, im on clarity';
await doContractCall({
contractAddress: 'ST22T6ZS7HVWEMZHHFK77H4GTNDTWNPQAX8WZAKHJ',
functionName: 'write-status!',
functionArgs: [status],
contractName: 'stream',
});
Each of these parameters is required. Hopefully they’re mostly straightforward, but please ask clarifying questions and we’ll update this and our documentation.
Go change the world
OK, are you still here? Yeah, things are pretty alpha right now. We will continue to refine this workflow, and new developments of the Stacks node and developer tools should reduce all the steps here by 80+%.
If you’re eager to start working on a Clarity app, you now have many of the puzzle pieces to get started.
Please share feedback with the team. We know you’ll likely run into bugs at some point. We’ll keep working on those, and together we can get the Stacks 2.0 world to a mature state in no time.