A comprehensive viem-based web3 toolkit providing chain utilities, contract interactions, and developer tools for EVM-compatible blockchains.
- Viem Context: Robust utilities for EVM chain interactions with singleton management
- Chain Kit Registry: Per-chain utilities with address books and token registries
- ERC20 & WETH Utilities: Simplified token operations with comprehensive logging
- Transaction Helpers: Batch operations and transaction management
- Type Safety: Full TypeScript support with viem types
- CLI Tools: Command-line interface for asset management
- Custom Chain Support: Easy integration with custom EVM chains
The core package providing:
- Singleton chain management with
ChainKitRegistry - Address book and token registry
- ERC20/WETH utilities with reduced boilerplate
- Transaction helpers with logging
- Contract parsers for better debugging
- Batch operations support
pnpm depspnpm run buildpnpm run lint
pnpm run formatpnpm run cleanmake changeset SUMMARY='Describe the change' [BUMP=patch]writes a non-interactive changeset. With our fixed-version setup, omittingPACKAGESautomatically includes every workspace package at the specified bump type (default ispatch). SupplyPACKAGES='pkg:major,...'only when you need different bumps per package. UseSUMMARY_FILE=path/to/message.mdif you prefer writing the summary in a file.make changeset-dry-run …previews the generated markdown without touching the.changesetdirectory.make versionrunspnpm changeset versionand refreshes the lockfile viapnpm install.make publishcallspnpm changeset publish.make releaseperformsmake versionfollowed bymake publish.- Export
SLACK_WEBHOOK_URL(and optionallySLACK_MESSAGE_SUFFIX) so the postpublish hook can notify Slack after each package is published.
import { createPublicClient, createWalletClient, http } from 'viem';
import { base } from 'viem/chains';
import { ChainKitRegistry, ERC20, WETH } from '@derivation-tech/viem-kit';
// Setup clients
const publicClient = createPublicClient({
chain: base,
transport: http(),
});
const walletClient = createWalletClient({
account: mnemonicToAccount('your mnemonic here'),
chain: base,
transport: http(),
});
// Get chain kit instance
const kit = ChainKitRegistry.for(base);
// Query ERC20 balance
const usdcAddress = '0x833589fCD6eDb6E08f4c7C32D4f71b54bdA02913';
const balance = await ERC20.balanceOf(publicClient, usdcAddress, walletClient.account.address);
const formatted = kit.formatErc20Amount(balance, usdcAddress);
console.log(`USDC Balance: ${formatted}`);The toolkit ships a standalone CLI under packages/cli, run with tsx:
# Query balances
pnpm tsx packages/cli/src/asset.ts balance usdc -n base --id neo:0-10
# Transfer tokens
pnpm tsx packages/cli/src/asset.ts transfer usdc -n base --from neo:0 --to neo:1 --amount 100
# Batch transfers
pnpm tsx packages/cli/src/asset.ts transfer usdc -n base --from neo:0-5 --to neo:6-11 --amount 10 --batchExplore the examples in packages/viem-kit/examples/:
abc-testnet.ts- Custom chain setup and usageabc-transfer.ts- ERC20 transfers on custom chainsbatch-transfer.ts- Batch ERC20 operationserc20-transfer.ts- Standard ERC20 interactionssingleton.ts- Singleton pattern demonstrationweth-deposit-withdraw.ts- WETH operations
Run examples:
cd packages/viem-kit
npx tsx examples/abc-testnet.tsviem-kit/
├── packages/
│ ├── viem-kit/ # Core toolkit package
│ ├── cli/ # Asset/admin CLI (asset, spot-admin, aggregator-admin, perp-admin)
│ └── viem-ledger/ # Ledger account helpers
├── package.json # Workspace configuration
└── README.md # This file
To add a new package to the workspace:
./scripts/init.sh packageNameTo publish a package:
-
Navigate to the package directory:
cd packages/your-package -
Run the publish command:
pnpm run publish
- Fork the repository
- Create a feature branch
- Make your changes
- Ensure code quality with
pnpm run lintandpnpm run format - Add tests if applicable
- Submit a pull request
MIT License - see LICENSE file for details.