Quickstart
In this guide, you'll build a simple counter smart contract and interact with it in a local environment.
What you'll learn
Create a Clarity smart contract project
Write Clarity code with maps and public functions
Test and validate your contracts using Clarinet's console
Prerequisites
Clarinet installed on your machine. Follow the installation guide if needed.
A code editor like VS Code for editing Clarity files.
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 counterClarinet creates a complete project structure for you. Each folder serves a specific purpose in your development workflow:
- counter/
- contracts/
- settings/
- Devnet.toml
- Mainnet.toml
- Testnet.toml
- tests/
- Clarinet.toml
- package.json
- vitest.config.jsGenerate 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 counter
Created file contracts/counter.clar
Created file tests/counter.test.ts
Updated Clarinet.toml with contract counterClarinet automatically creates both your contract file and a corresponding test file. This follows the best practice of writing tests alongside your contract code:
contracts/counter.clar
Your smart contract code
tests/counter.test.ts
Test file for your contract
Write your contract code
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-mapcreates a persistent storage map that associates each user (principal) with their counttx-senderis a built-in variable that contains the address of whoever calls the functiondefine-publicdeclares functions that can modify contract statedefine-read-onlydeclares 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 checkIf you see errors instead, here are the most common issues and how to fix them:
Unknown keyword
Check spelling of Clarity functions
Type mismatch
Ensure you're using correct types (uint, principal, etc.)
Unresolved contract
Verify contract name in Clarinet.toml matches the contract name in the file
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 consoleOnce 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)
u2Last updated
Was this helpful?
