Skip to content

satoshai-dev/abi-cli

Repository files navigation

@satoshai/abi-cli

npm version CI License: MIT

CLI tool to fetch ABIs from deployed Stacks blockchain contracts and output TypeScript-ready definitions (as const).

Install

# Global install
npm install -g @satoshai/abi-cli

# Or run directly with npx
npx @satoshai/abi-cli fetch <contract>

Usage

Basic — fetch and write to file

By default, the CLI writes a TypeScript file named after the contract to the current directory:

abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01
# → writes amm-pool-v2-01.ts

The generated file looks like:

import type { ClarityAbi } from '@stacks/transactions';

// ABI for SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01
// Generated by @satoshai/abi-cli

export const abi = {
  "functions": [...],
  "variables": [...],
  ...
} as const satisfies ClarityAbi;

export type Abi = typeof abi;

Output to stdout

Use --stdout to print the output instead of writing a file:

abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01 --stdout

Custom output path

abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01 -o ./abis/amm-pool.ts

JSON format

# Write to file (amm-pool-v2-01.json)
abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01 --format json

# Print to stdout
abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01 --format json --stdout

Networks

Defaults to mainnet. Use -n / --network to switch:

# Testnet
abi-cli fetch ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.my-contract -n testnet

# Devnet (localhost:3999)
abi-cli fetch ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.my-contract -n devnet

# Custom Stacks API URL
abi-cli fetch SP...contract -n https://my-node.example.com

Multiple contracts

Comma-separate contract IDs to fetch several at once:

abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01,SP2C2YFP12AJZB1KD5HQ4XFRYGEK02H70HVK8GQH.arkadiko-swap-v2-1
# → writes amm-pool-v2-01.ts and arkadiko-swap-v2-1.ts

Sync — config-driven multi-contract sync

For projects with multiple contracts, create a config file to keep ABIs in sync declaratively.

Create abi.config.json in your project root:

{
  "outDir": "./src/abis",
  "format": "ts",
  "network": "mainnet",
  "contracts": [
    { "id": "SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01", "name": "amm-pool" },
    { "id": "SP2C2YFP12AJZB1KD5HQ4XFRYGEK02H70HVK8GQH.arkadiko-swap-v2-1", "name": "arkadiko-swap" },
    { "id": "ST1PQHQKV0RJXZFY1DGX8MNSNYVE3VGZJSRTPGZGM.my-contract", "network": "testnet" }
  ]
}

The name field controls the output filename. This decouples your imports from the on-chain contract ID — when you upgrade to a new contract version, change the id but keep the name. Your imports stay the same.

Or use abi.config.ts for type-safe config with autocomplete:

import type { AbiConfig } from '@satoshai/abi-cli';

export default {
  outDir: './src/abis',
  format: 'ts',
  network: 'mainnet',
  contracts: [
    { id: 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01', name: 'amm-pool' },
    { id: 'SP2C2YFP12AJZB1KD5HQ4XFRYGEK02H70HVK8GQH.arkadiko-swap-v2-1', name: 'arkadiko-swap' },
  ],
} satisfies AbiConfig;

Then run:

abi-cli sync
# → reads abi.config.json (or .ts), writes all ABIs to outDir

This generates:

src/abis/
├── amm-pool.ts
├── arkadiko-swap.ts
└── index.ts          # barrel file with re-exports

The barrel file re-exports all ABIs with camelCase names:

export { abi as ammPoolAbi } from './amm-pool.js';
export { abi as arkadikoSwapAbi } from './arkadiko-swap.js';

Use --config / -c to point to a custom config path:

abi-cli sync --config ./configs/my-abis.json

Config schema

Field Type Required Default Description
outDir string yes Output directory for generated files
format "ts" | "json" no "ts" Output format
network string no "mainnet" Default network for all contracts
contracts ContractEntry[] yes List of contracts to sync
contracts[].id string yes Contract ID in address.name format
contracts[].name string no contract name from ID Alias for output filename and barrel export
contracts[].network string no top-level network Per-contract network override

Check — CI staleness detection

Use --check to verify local files are in sync with on-chain ABIs without writing anything. Exits with code 1 if any files are stale or missing.

# Single contract
abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01 --check

# All contracts from config
abi-cli sync --check

Add it to your CI pipeline to catch stale types:

- name: Check ABIs are up-to-date
  run: npx @satoshai/abi-cli sync --check

Flags Reference

abi-cli fetch

Flag Alias Default Description
--network -n mainnet Network: mainnet, testnet, devnet, or a custom URL
--output -o <contract-name>.<format> Output file path (single contract only)
--format -f ts Output format: ts or json
--stdout false Print to stdout instead of writing a file
--check false Check if local files match on-chain ABI (exit 1 if stale)
--help Show help

abi-cli sync

Flag Alias Default Description
--config -c auto-discover Path to config file
--check false Check if local files match on-chain ABIs (exit 1 if stale)
--help Show help

Programmatic API

import { fetchContractAbi, generateTypescript, generateJson, parseContractId } from '@satoshai/abi-cli';

// Fetch an ABI
const abi = await fetchContractAbi('mainnet', 'SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM', 'amm-pool-v2-01');

// Generate TypeScript (as const)
const tsCode = generateTypescript('SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01', abi);

// Generate JSON
const json = generateJson(abi);

// Parse a contract ID string
const { address, name } = parseContractId('SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01');

Config loading

import { loadConfig, validateConfig } from '@satoshai/abi-cli';
import type { AbiConfig, ContractEntry } from '@satoshai/abi-cli';

// Load and validate from file (auto-discovers abi.config.json/.ts)
const config = await loadConfig();

// Or from a specific path
const config2 = await loadConfig('./my-config.json');

// Validate a raw object
const validated = validateConfig({ outDir: './abis', contracts: [{ id: 'SP1.token' }] });

Types are re-exported from @stacks/transactions:

import type { ClarityAbi, ClarityAbiFunction, ClarityAbiType } from '@satoshai/abi-cli';

License

MIT

About

CLI to fetch Stacks contract ABIs and generate TypeScript definitions

Topics

Resources

License

Contributing

Stars

Watchers

Forks

Packages

 
 
 

Contributors