Quickstart
Build your first Clarity smart contract in under 5 minutes
What you'll learn
In this guide, you'll build a simple counter smart contract and interact with it in a local environment. By the end, you'll understand:
Prerequisites
To follow this guide, you'll need:
Create your project
Let's start by creating a new Clarinet project. The clarinet new
command sets up everything you need for smart contract development, including a testing framework, deployment configurations, and a local development environment:
$clarinet new counterCreate directory counterCreate directory contractsCreate directory settingsCreate directory testsCreate file Clarinet.tomlCreate file package.jsonCreate file vitest.config.js
Clarinet creates a complete project structure for you. Each folder serves a specific purpose in your development workflow:
Generate your contract
Now that we have our project structure, let's create a smart contract. Navigate into your project directory and use Clarinet's contract generator:
$cd counter$clarinet contract new counterCreated file contracts/counter.clarCreated file tests/counter.test.tsUpdated Clarinet.toml with contract counter
Clarinet automatically creates both your contract file and a corresponding test file. This follows the best practice of writing tests alongside your contract code:
File | Purpose |
---|---|
contracts/counter.clar | Your smart contract code |
tests/counter.test.ts | Test file for your contract |
Notice that Clarinet also updated your Clarinet.toml
file. This configuration file tracks all contracts in your project and their deployment settings.
Write your contract code
Time to write our smart contract! Open contracts/counter.clar
and replace its contents with our counter implementation. This contract will maintain a separate count for each user who interacts with it:
;; Define a map to store counts for each user(define-map Counters principal uint);; Increment the count for the caller(define-public (count-up)(ok (map-set Counters tx-sender (+ (get-count tx-sender) u1))));; Get the current count for a user(define-read-only (get-count (who principal))(default-to u0 (map-get? Counters who)))
Let's understand what each part does:
define-map
creates a persistent storage map that associates each user (principal) with their counttx-sender
is a built-in variable that contains the address of whoever calls the functiondefine-public
declares functions that can modify contract statedefine-read-only
declares functions that only read data without modifying it
Validate your contract
Before we can test our contract, let's make sure it's syntactically correct and type-safe. Clarinet's check command analyzes your contract without deploying it:
$clarinet check✔ 1 contract checked
If you see errors instead, here are the most common issues and how to fix them:
Error | Fix |
---|---|
Unknown keyword | Check spelling of Clarity functions |
Type mismatch | Ensure you're using correct types (uint, principal, etc.) |
Unresolved contract | Verify contract name matches filename |
Test in the console
Now for the exciting part—let's interact with our contract! Clarinet provides an interactive console where you can call functions and see results immediately. Start the console with:
$clarinet console
Once the console loads, you can call your contract functions directly. Here are a few examples you can try:
$(contract-call? .counter count-up)(ok true)$(contract-call? .counter get-count tx-sender)u1$(contract-call? .counter count-up)(ok true)$(contract-call? .counter get-count tx-sender)u2