Clarity-abitype: Better TypeScript DX for Stacks Developers

Hey all,

Sharing another library I’ve been working on: clarity-abitype.

If you’ve worked with Clarity contracts in TypeScript, you know the type safety could be improved. You end up with a lot of any types or manual type definitions that can become out of sync with your actual contracts as they change.

clarity-abitype takes a different approach to solving this problem, instead of code generation, it uses TypeScript’s type inference to derive types directly from your contract ABI at compile time. Just import your ABI (with as const) and you get full autocomplete and type checking for function names, arguments, and return types.

import type {
  ClarityAbiArgsToPrimitiveTypes,
  ExtractAbiFunction,
  ExtractAbiFunctionNames,
} from "clarity-abitype";

// Get typed function names
type FunctionNames = ExtractAbiFunctionNames<typeof myAbi, "public">;
//   ^? "transfer" | "mint" | ...

// Get typed args for a specific function
type TransferArgs = ClarityAbiArgsToPrimitiveTypes
  ExtractAbiFunction<typeof myAbi, "transfer">["args"]
>;
//   ^? readonly [bigint, string, string, `0x${string}` | null]

If you’ve used clarigen, this solves a similar problem but with a different philosophy, no codegen, just pure TypeScript inference.

Vision: Better DX for the Stacks Ecosystem

Ideally, clarity-abitype would be integrated into the core Stacks tooling (stacks.js, clarinet, etc.). Devs wouldn’t need to know clarity-abitype exists, they’d just get autocomplete and type errors when they make mistakes. That would be a massive DX improvement, and it’s how the EVM ecosystem works today with abitype + viem/wagmi and matching that experience would also make Stacks feel a lot more familiar to devs coming from Ethereum.

Example of how this could work in stacks.js:

const balance = await callReadOnlyFunction({
  abi: sip10Abi,
  // type-safe: autocomplete + error if function doesn't exist
  functionName: "get-balance",
  // type-safe: error if args don't match the expected types
  functionArgs: ["SP2C2YFP12AJZB4MABJBAJ55XECVS7E4PMMZ89YZR"],
});

Links

Let me know what you think — feedback and PRs welcome!

1 Like

This is great for simulations!

How could I use this for unit tests? Can clarinet generate the ABI?

Right now Clarinet don’t generate the local ABI directly. One can use this workaround for now Generate local contract ABI JSON · Issue #2071 · stx-labs/clarinet · GitHub