@satoshai/abi-cli
v1.0.0
Published
CLI to fetch Stacks contract ABIs and generate TypeScript definitions.
Maintainers
Readme
@satoshai/abi-cli
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.tsThe 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 --stdoutCustom output path
abi-cli fetch SP102V8P0F7JX67ARQ77WEA3D3CFB5XW39REDT0AM.amm-pool-v2-01 -o ./abis/amm-pool.tsJSON 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 --stdoutNetworks
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.comMultiple 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.tsSync — 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 outDirThis generates:
src/abis/
├── amm-pool.ts
├── arkadiko-swap.ts
└── index.ts # barrel file with re-exportsThe 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.jsonConfig 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 --checkAdd it to your CI pipeline to catch stale types:
- name: Check ABIs are up-to-date
run: npx @satoshai/abi-cli sync --checkFlags 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
