Разработка npm-пакета для смарт-контрактов
Контракт задеплоен, frontend-разработчик хочет с ним работать. Вариант первый — копировать ABI JSON в проект вручную, писать вызовы через ethers.Contract с кастингом типов на any. Вариант второй — npm-пакет с типизированными обёртками, который импортируется одной строкой и даёт автодополнение в IDE.
Разница между вариантами особенно ощущается при апгрейде контракта: в первом случае нужно найти все места, где используется старый ABI; во втором — обновить версию пакета.
Что должно быть внутри пакета
Минимальный полезный пакет для смарт-контракта включает:
ABI как TypeScript-константа. Не просто JSON-файл, а типизированная константа, сгенерированная через typechain или viem'овский parseAbi. С TypeChain получаем полностью типизированные классы-обёртки — MyContract__factory.connect(address, signer) — с автодополнением для всех функций, событий, ошибок.
Адреса деплоя по сетям. Объект вида { [chainId: number]: string }, собранный из deployment-артефактов Hardhat или Foundry. Когда контракт задеплоен в Arbitrum, Optimism и Polygon — фронтенд получает адрес одной строкой: ADDRESSES[chainId].
Утилиты для форматирования. Специфичные для контракта хелперы: парсинг событий, форматирование значений (например, formatUnits с правильными decimals), конвертация между on-chain представлением и UI.
TypeScript-типы для всех структур. Входные параметры функций, возвращаемые значения, события — всё типизировано. Ошибки компилируются с полным описанием.
Сборка и публикация
Стек для сборки пакета: tsup или rollup. tsup — проще настраивается, поддерживает dual CJS/ESM output из коробки:
{
"main": "./dist/index.cjs",
"module": "./dist/index.js",
"types": "./dist/index.d.ts",
"exports": {
".": {
"import": "./dist/index.js",
"require": "./dist/index.cjs"
}
}
}
Dual format важен: Next.js с App Router требует ESM, старые CRA-проекты могут требовать CJS. Без dual output пакет работает только в половине окружений.
CI/CD для публикации
GitHub Actions: при пуше тега v* — прогон тестов → сборка → публикация на npm. Версионирование через semantic-release или ручное по semver. Главное правило: мажорная версия меняется при любом breaking change в ABI (переименование функции, изменение параметров).
Для внутренних (закрытых) пакетов — GitHub Packages или Verdaccio self-hosted. Настройка .npmrc в проекте клиента:
@myorg:registry=https://npm.pkg.github.com
Интеграция с Foundry и Hardhat
Hardhat автоматически генерирует артефакты в artifacts/contracts/. TypeChain подхватывает их и генерирует типы. Нужно добавить в pipeline: compile → typechain → build package → publish.
С Foundry — через forge build, артефакты в out/. TypeChain поддерживает Foundry-формат через @typechain/hardhat с указанием artifacts директории. Альтернатива — wagmi cli generate с плагином foundry, который генерирует React hooks прямо из Foundry артефактов.
Сроки
Разработка npm-пакета для одного контракта с ABI, типами, адресами и базовыми утилитами — 1 рабочий день. Полноценный пакет с типизацией через TypeChain, dual ESM/CJS сборкой, CI/CD и документацией — 2-3 дня.







