diff --git a/content/docs/stacks/clarinet-js-sdk/quickstart.mdx b/content/docs/stacks/clarinet-js-sdk/quickstart.mdx index 8de95438f..9a654bb15 100644 --- a/content/docs/stacks/clarinet-js-sdk/quickstart.mdx +++ b/content/docs/stacks/clarinet-js-sdk/quickstart.mdx @@ -3,10 +3,10 @@ title: Quickstart description: Learn how to test a simple counter contract using the Clarinet JS SDK. --- -import { ChevronRight, Code, Terminal } from 'lucide-react'; -import { File, Folder, Files } from 'fumadocs-ui/components/files'; -import { Steps, Step } from 'fumadocs-ui/components/steps'; -import { SmallCard } from '@/components/card'; +import { ChevronRight, Code, Terminal } from "lucide-react" +import { File, Folder, Files } from "fumadocs-ui/components/files" +import { Steps, Step } from "fumadocs-ui/components/steps" +import { SmallCard } from "@/components/card" In this quickstart guide, you will initialize a simulated development network for testing a smart contract using the Clarinet JS SDK. You'll learn how to initialize your project, interact with a smart contract, call its functions, and test the results. @@ -41,7 +41,7 @@ Check out the [methods](/stacks/clarinet-js-sdk/references/methods) page for the ``` The `Cl` namespace simplifies the process of creating and handling Clarity values. This functionality is particularly useful in testing environments where developers need to simulate contract interactions accurately. - + ## Retrieve an account from the simnet @@ -60,6 +60,7 @@ Check out the [methods](/stacks/clarinet-js-sdk/references/methods) page for the The `--stacks` flag is required and allows you to specify the network to scan. Other options include `--bitcoin`. + ## Write your first test @@ -80,6 +81,7 @@ Check out the [methods](/stacks/clarinet-js-sdk/references/methods) page for the }); }); ``` + ## Test the count-up function @@ -91,7 +93,7 @@ Check out the [methods](/stacks/clarinet-js-sdk/references/methods) page for the it("increments the count of the user's principal by 1", () => { const countUpCall = simnet.callPublicFn("counter", "count-up", [], wallet); expect(countUpCall.result).toBeOk(Cl.bool(true)); // [!code highlight] - + const getCountCall = simnet.callReadOnlyFn( "counter", "get-count", @@ -108,12 +110,13 @@ Check out the [methods](/stacks/clarinet-js-sdk/references/methods) page for the

The toBeOk and toBeUint methods are used to ensure the `count-up` function returns the proper Clarity values. For more details, check out the [custom matchers](/stacks/clarinet-js-sdk/references/custom-matchers) page.

+
## Run your tests Every generated project comes with a package.json file that contains the necessary dependencies and scripts to run your tests. - + ```json title="package.json" "scripts": { "test": "vitest run", // [!code highlight] @@ -123,10 +126,87 @@ Check out the [methods](/stacks/clarinet-js-sdk/references/methods) page for the ``` You can now run your tests, with your preferred package manager, by executing the following command: - + ```console npm run test ``` + + + + ## Run your tests with code coverage and cost analysis + + Clarinet can automatically also produce a code coverage report and cost analysis on the test you ran. + + ```json title="package.json" + "scripts": { + "test": "vitest run", + "test:report": "vitest run -- --coverage --costs", // [!code highlight] + "test:watch": "chokidar \"tests/**/*.ts\" \"contracts/**/*.clar\" -c \"npm run test:report\"" + } + ``` + + By running the `npm run test:report` command in your terminal, an `lcov.info` and `costs-reports.json` file will appear in your root folder: + + + + + + + + + + + + + + + + + + + The `costs-reports.json` file will output the cost analysis for every function ran in your tests. Since the `count-up` function was used in our test, this is how the cost analysis output would look like for that function: + + ```json title="costs-reports.json" + { + "test_name": "tests/counter.test.ts__counter contract__increments the count of the user's principal by 1", + "contract_id": "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.counter", + "method": "count-up", + "args": [], + "cost_result": { + "total": { + "write_length": 41, + "write_count": 1, + "read_length": 245, + "read_count": 5, + "runtime": 4752 + }, + "limit": { + "write_length": 15000000, + "write_count": 15000, + "read_length": 100000000, + "read_count": 15000, + "runtime": 5000000000 + }, + "memory": 40, + "memory_limit": 100000000 + } + } + ``` + + To access and read the `lcov.info` file in a human-readable format, we can first install the `lcov` [package](https://github.com/linux-test-project/lcov) that helps generate a graphical front-end for coverage testing tools. + + ```console title="Terminal" + brew install lcov + ``` + + Then we'll run the `genhtml` command below with the following options. This command and its options will generate the actual html file, add in additional branch coverage, and will automatically store the files in a new folder called `coverage`. + + ```console title="Terminal" + genhtml lcov.info --branch-coverage -o coverage + ``` + + You can then navigate into the new `coverage` folder and run the command `open index.html` to view your coverage report. In addition, a summary of the coverage report will be outputted in the terminal. + @@ -150,4 +230,4 @@ Check out the [methods](/stacks/clarinet-js-sdk/references/methods) page for the title="Migrating your tests to Clarinet SDK" description="Learn how to migrate your existing Clarinet projects to the Clarinet JS SDK" /> - \ No newline at end of file + diff --git a/content/docs/stacks/clarinet/guides/estimate-costs.mdx b/content/docs/stacks/clarinet/guides/estimate-costs.mdx new file mode 100644 index 000000000..7f186cb0a --- /dev/null +++ b/content/docs/stacks/clarinet/guides/estimate-costs.mdx @@ -0,0 +1,85 @@ +--- +title: Estimating contract costs +description: Analyze execution costs pertaining to your contract. +--- + +import { File, Folder, Files } from "fumadocs-ui/components/files" + +Transactions on the Stacks blockchain comes with execution costs that can dictate transaction fees for your users. To analyze the execution costs of your contract's functions, let's continue with the simple `counter` contract from the [Clarinet quickstart](/stacks/clarinet/quickstart) as an example. + +```clarity +(define-map Counters principal uint) + +(define-read-only (get-count (who principal)) + (default-to u0 (map-get? Counters who)) +) + +(define-public (count-up) + (ok (map-set Counters tx-sender (+ (get-count tx-sender) u1))) +) +``` + +To start analyzing execution costs , first run the `clarinet console` command inside your project. + +```console title="Terminal" +clarinet console +``` + +## Get Costs + +The `::get_costs ` command in the Clarinet console will display the cost analysis of the given expression as well as the return value of the given expression. The `::get_costs` command expects an expression, so make a `contract-call?` with our `count-up` function and see what happens. + +```console title="Terminal" +::get_costs (contract-call? .counter count-up) +``` + +We should see a chart breaking down the different types of execution costs in the console. Here's the execution cost analysis returned from running the above command: + +```console +>> ::get_costs (contract-call? .counter count-up) ++----------------------+-------------+----------------+-----------------+ +| | Consumed | Limit | Percentage | ++----------------------+-------------+----------------+-----------------+ +| Runtime | 4752 | 5000000000 | 0.00 % | ++----------------------+-------------+----------------+-----------------+ +| Read count | 5 | 15000 | 0.03 % | ++----------------------+-------------+----------------+-----------------+ +| Read length (bytes) | 245 | 100000000 | 0.00 % | ++----------------------+-------------+----------------+-----------------+ +| Write count | 1 | 15000 | 0.01 % | ++----------------------+-------------+----------------+-----------------+ +| Write length (bytes) | 41 | 15000000 | 0.00 % | ++----------------------+-------------+----------------+-----------------+ + + +(ok true) +``` + +As you can see from the chart, execution costs are broken into 5 different categories, each with its own limit. The limit is pertaining to what each Stacks block is limited to. + + +The below lists out each of the 5 different categories of Clarity execution costs. ([source](https://book.clarity-lang.org/ch12-00-runtime-cost-analysis.html)) + +- **Runtime** costs limits overall complexity of the code that can be executed. For example, negating a boolean value is less complex than calculating SHA512 hash, therefore (not false) will consume less runtime costs than (sha512 "hello world") . This category is also affected by contract size. +- **Read count** limits how many times we can read from memory or chain state to a extract piece of information. It is affected by reading constants, variables, intermediate variables created with let , maps, but also by some functions that needs to save intermediate results during execution. +- **Read length (bytes)** limits how much data we can read from memory or the chain. It is also affected by contract size. Calling into a contract using contract-call? Increases the read length by an amount equal to the contract size in bytes, every time. If you call into a contract with a length of 2, 000 bytes twice, the read length is increased twice. +- **Write count** limits how many times we can write data into chain. It increments when writing to variables and maps. +- **Write length (bytes)** limits how much data we can write to the chain. + + + +The percentage column shows what percentage of the execution costs your expression consumed out of the block limit given. + +## Toggle costs + +You can toggle the cost analysis to always be displayed after every expression execution in the console by toggling this feature on with the command `::toggle_costs`. + +```console title="Terminal" +::toggle_costs +``` + +To turn it off, just run the `::toggle_costs` command again. + +Check out the Clarity Book section on [runtime cost analysis](https://book.clarity-lang.org/ch12-00-runtime-cost-analysis.html) to read up on cost optimization techniques and recommendations. + +To see how you can run automated cost analysis on your unit tests, check out our [quickstart](/stacks/clarinet-js-sdk/quickstart#run-your-tests-with-code-coverage-and-cost-analysis) section for the Clarinet JS SDK. diff --git a/content/docs/stacks/clarinet/meta.json b/content/docs/stacks/clarinet/meta.json index cb885e837..e8bf930ed 100644 --- a/content/docs/stacks/clarinet/meta.json +++ b/content/docs/stacks/clarinet/meta.json @@ -14,6 +14,7 @@ "guides/add-a-contract", "guides/validate-a-contract", "guides/debug-a-contract", + "guides/estimate-costs", "guides/run-a-local-devnet", "guides/deploy-a-contract", "guides/create-deployment-plans"