Clarity notes

1. Software

clarinet new my-project && cd my-project ;; Create a new project
clarinet contract new mycoolcontract ;; Create new contract in project
clarinet check ;; Check the sintax of Clarity
clarinet test ;; Test

2. Basics

;; Comments start with 2 semicolons.
(concat "Hello" " World!") ;;  

3.Types

Types are strictly enforced and can’t be mixed: (+ 2 u3) isn’t accepted.
3 categories of types: Primitives, Sequences and Composites.

3.1 Type: Primitives

These are signed and unsigned integers, booleans and principals

(* 4 (+ 15 10));; The result is 100.
(/ u99 u100) ;; Decimals are dropped not rounded up. The result will be 0.
(not true) ;; Inverts a boolean. The result is false
(and true true true) ;; 'and' returns true if all inputs are true. The result is true.
(or false true false) ;; 'or' returns true if at least one input is true. The result is true.

Principals

Represent a Stacks address on the blockchain.

'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE ;; A Stacks address
'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE.my-awesome-contract ;; A Stacks contract
(stx-get-balance 'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE) ;; Checks balance of a Stacks address

3.2 Type: Sequences

3 types os sequences:

buffers:

;; Buffers start with 0x followed by a hexadecimal string
0x68656c6c6f21

strings:

"ACII string"
u"UTF-8 string"

lists:

(list 4 8 15 16 23 42) ;; Types cannot mix in a list
(list "Hello" "World" "!")

;; map applies an input function to each element
(map not (list true true false false)) ;; This returns [false false true true]

;; fold applies an input function to each element AND the output value of the previous application
(fold + (list u1 u2 u3) u4) ;; This returns 10

(len "How long is this string?")

;; Position counts start at 0
;; Functions that might or might not return a value tend to return an optional type named 'some'
(element-at (list 4 8 15 16 23 42) u3) ;; Returns (some 16)
(index-of (list 4 8 15 16 23 42) 23) ;; Returns (some u4)
(index-of (list 4 8 15 16 23 42) 24) ;; Returns none

3.3 Type: Composites

Optionals

The type system in Clarity does not allow for empty values, so an integer always contains a number. To express a variable that could have some value or nothing we use the keyword some.

(some u5)
(some "An optional containing a string.")

;; To access the value contained within an optional, you have to unwrap it first:
(unwrap-panic (some u10)) ;; Returns (some u10)

Tuples

;; Declare a tuple
{
	id: u5, ;; a uint
	username: "ClarityIsAwesome", ;; an ASCI string
	address: 'ST1HTBVD3JG9C05J7HBJTHGR0GGW7KXW28M5JS8QE ;; and a principal
}
;; Get a value in a tuple:
(get username { id: 5, username: "bob" }) ;; Returns bob

;;Merge (to change) a tuple:
(merge
	{id: 5, score: 10, username: "bob"}
	{score: u20, active: true}
)
;; Returns {id: 5, score: 20, username: "bob", active: true}

Responses

;; Responses can be 'ok' or 'err'
(err u5)
(ok true)
(unwrap-panic (ok true)) ;; Returns true

3.4 Type Signatures

Type signature define the admitted type for variable or function argument

Type Signature
Buffer (buff max-len)
ASCII string (string-ascii max-len)
UTF-8 string (string-utf8 max-len)
List (list max-len element-type)
Optional (optional some-type)
Tuple {key1: type1, key2: type2}
Response (respone ok-type err-type)

4. Keywords

block-height ;; Stacks block number
burn-block-height ;; Bitcoins block number
tx-sender ;; Principal that sent the transaction
(as-contract tx-sender)
contract-caller ;; Contains the principal that called the function. It can be a standard principal or contract principal. If the contract is called via a signed transaction directly, then tx-sender and contract-caller will be the same. If the contract calls another contract in turn, then contract-caller will be equal to the previous contract in the chain.

5. Storing data

3 kinds of storage: Constants, Variables and Maps

5.1 Storing data: Constants

(define-constant my-constant "This is a constant")
(print my-constant)

5.2 Storing data: Variables

(define-data-var my-number uint u0)
(print (var-get my-number)) ;; Print the value
(var-set my-number u5000) ;; Change the value

5.3 Storing data: Maps

Maps are hash tables.
Maps are not iterable, you cannot loop though it to retrieve all values. The only way to access a value in a map is to enter the key.

(define-map map-name key-type value-type)

Set and delete values

(map-set map-name tx-sender u100)    ;; map-set sets or overwrites a value
(map-insert map-name tx-sender u100) ;; map-insert fails if the key already exists
(map-delete map-name tx-sender)

Retrieve value

(print (map-get? invoice u1))

6. Functions

3 kinds of functions: list of functions:

Public functions Private functions Read-only functions
Can be called externally. Calls require sending a transaction (fees). Only called by the current contract Can be called externally but may not change the chain state (no fees)
(define-public function-signature function-body)

** Function signature ** Defines the name of the function and any input parameters.

(function-name (param1-name param1-type) (param2-name param2-type) ...)

Example:

(define-public (hello (name (string-ascii 30)))
	(ok (concat "Hola " name))
)

(print (hello "Clarity"))

** Function body ** The variadic begin function takes an arbitrary amount of inputs and will return the result of the last expression.

(define-public (print-twice (first (string-ascii 40)) (second (string-ascii 40)))
	(begin
		(print first)
		(print second)
		(ok true)
	)
)

(print-twice "Hello world!" "Multiple prints!")

Outputs:

"Hello world!"
"Multiple prints!"

6.1 Public Functions

6.2. Private Functions

6.3 Read-only functions

7. Control flow functions

7.1 asserts!

If the boolean expression evaluates to true, then asserts! returns true and execution continues, but if the expression evaluates to false then asserts! will return the throw value and exit the current control flow.

(asserts! boolean-expression throw-value)

7.2 try!

The try! function takes an optional or a response type and will attempt to unwrap it.

(try! (some "wrapped string"))

try! can only unwrap someand ok values.
If it receives a none or an err, it will return it and exit the current control flow.

7.3 unwrap

7.4 unwrap-err!

7.5 unwrap-panic

7.6 unwrap-err-panic