Перейти к основному содержимому
Блокчейн34ГЛАВА 34Hardhat: пакет, npx и структура проектаpackagelocknode_modules/.binhardhatnpx hardhat

Hardhat: пакет, npx и структура проекта

Прочитано0%
Квизы0/4
Тренажёрыне пройден0/1
Уровень 1 · Новичок

Зачем это нужно​

Сеть есть. Контракты писать умеем. Но между исходником на Solidity и адресом в сети лежит работа, которую никто не делает руками: скачать компилятор нужной версии, собрать байт-код, разложить результат по файлам, отправить транзакцию развёртывания, дождаться её, достать адрес, прогнать тесты.

Hardhat — программа, которая делает всё это одной командой. Задание требует её прямым текстом, но дело не в требовании: без такого инструмента развёртывание десятка контрактов превращается в полдня ручной работы.

Эта глава — про то, откуда он берётся, куда ставится и почему у двух соседних папок могут быть разные его версии. Без этого следующая глава — про файл настроек — читается как заклинание.

Не программа, а пакет​

Инструменты ставят двумя способами, и Hardhat относится ко второму.

Системная программа — как geth из прошлой главы. Один исполняемый файл, установленный на компьютер, один на всех. Версия одна, и она общая для всех проектов.

Пакет проекта — как Hardhat. Живёт внутри папки проекта, в node_modules. Устанавливается вместе с проектом, версия своя у каждого.

Разница не косметическая. Задание на чемпионате приносят в готовом виде, решение сдают папкой, а принимающий разворачивает его у себя. Если версия инструмента прописана в проекте, у всех получится одно и то же. Если она «какая стояла на компьютере» — не получится ни у кого.

Важно

Ставить Hardhat глобально (npm i -g) можно, но не нужно: первый же проект с другой версией сломает второй. Все руководства последних лет ставят его только в проект — и мы тоже.

Шесть шагов от пустой папки​

Первая модель проходит путь с нуля и печатает, что происходит на каждом шаге:

── шаг 1: пустая папка ──
файлов: 0

── шаг 2: npm init -y ──
появился package.json, в нём:
name: hh-fresh
version: 1.0.0
main: index.js
type: commonjs

── шаг 3: npm i --save-dev hardhat ──
added 50 packages, and audited 51 packages in 9s
found 0 vulnerabilities
заняло: 8.7 c
папок в node_modules : 30
размер node_modules : 81M
версия в package.json: ^3.16.0
версия на диске : 3.16.0

Три вещи здесь стоят внимания.

--save-dev — значит «нужен для разработки». Hardhat не попадает в то, что уезжает в сеть: в блокчейн уезжает только байт-код контракта. Поэтому он записывается в отдельный список зависимостей.

50 пакетов вместо одного. Hardhat притащил за собой всё, на что опирается сам. Это норма для этой экосистемы, и именно поэтому node_modules никогда не кладут в репозиторий.

"type": "commonjs" в только что созданном описании — та самая строка из главы про модули. Запомните её: через полминуты она изменится сама.

Первая ошибка: инструмент есть, проекта нет​

── шаг 4: запускаем hardhat, ничего больше не сделав ──
Error HHE3: No Hardhat config file found.

You can initialize a new project by running Hardhat with --init

For more info go to https://hardhat.org/HHE3 or run Hardhat with --show-stack-traces

Установленный пакет сам по себе ничего не умеет: ему нужен файл настроек, по которому он поймёт, что за проект перед ним. Нет файла — нет проекта, и любая команда упирается в этот отказ.

Заодно обратите внимание на форму сообщения: код ошибки (HHE3), человеческое объяснение, подсказка, что делать, и ссылка. Так выглядят все ошибки Hardhat — по коду можно искать, а не гадать.

Три заготовки, и какую брать​

── шаг 5: какие заготовки есть ──
Available templates:
- node-test-runner-viem
- mocha-ethers
- minimal

minimal — только файл настроек, дальше сами. Годится, когда точно знаешь, что делаешь.

node-test-runner-viem — тесты встроенным средством Node, работа с сетью через библиотеку viem.

mocha-ethers — тесты через mocha, работа с сетью через ethers. Берём эту: ethers мы уже видели в главе про запросы к узлу, а в этой связке написано подавляющее большинство примеров в интернете.

── шаг 6: npx hardhat --init --template mocha-ethers ──
npm install --save-dev "@nomicfoundation/hardhat-toolbox-mocha-ethers@^3.0.7" …
added 212 packages, and audited 263 packages in 30s
Dependencies installed
Project initialized
заняло: 35.7 c
Нажми на часть выражения

Что появилось в папке​

── что появилось в папке ──
.gitignore
AGENTS.md
README.md
contracts/Counter.sol
contracts/Counter.t.sol
hardhat.config.ts
ignition/modules/Counter.ts
package-lock.json
package.json
scripts/send-op-tx.ts
test/Counter.ts
tsconfig.json

── и сколько всё это весит ──
папок в node_modules : 167
всего пакетов в lock : 293
node_modules : 188M
исходники и настройки: 204K
ЧТО ПОЯВЛЯЕТСЯ В ПАПКЕ И ЗАЧЕМ ОНОhardhat.config.tsверсия компилятора, сети, подключаемые частив репозиторийcontracts/исходники на Solidity — и обычные, и тестовыев репозиторийtest/тесты на TypeScriptв репозиторийignition/modules/описания развёртыванияв репозиторийpackage.json + lockсписок зависимостей и их точные версиив репозиторийnode_modules/188 МБ, 293 пакета — восстанавливается одной командойне кластьвсё, что человек написал, весит 204 КБ; всё, что скачано, — 188 МБ
Всё написанное человеком — 204 КБ; всё скачанное — 188 МБ и одна команда на восстановление

Разбор по назначению:

  • hardhat.config.ts — единственный обязательный файл. Версия компилятора, список сетей, подключаемые части. Ему посвящена следующая глава целиком.
  • contracts/ — исходники на Solidity. Заметьте два файла: обычный контракт и Counter.t.sol — тест, тоже написанный на Solidity.
  • test/ — тесты на TypeScript.
  • ignition/modules/ — описания развёртывания: что за чем разворачивать и с какими параметрами.
  • scripts/ — обычные скрипты, запускаемые вручную.
  • tsconfig.json — настройки компилятора типов для этого проекта.
  • .gitignore — список того, что не кладут в репозиторий. Первой строкой там node_modules.

Соотношение 204 КБ против 188 МБ — главное число этой секции. В репозиторий кладут первое; второе восстанавливается одной командой.

Отвечено вопросов: 0 из 3
Почему Hardhat ставят в проект, а не глобально?
Что означает ошибка HHE3: No Hardhat config file found?
Что из созданного кладут в репозиторий?
Отвечено верно: 0 из 3

Одна строка, которую Hardhat переписал сам​

Сравните описание проекта до и после создания:

// после npm init -y
"type": "commonjs"

// после npx hardhat --init
"type": "module"

Это та самая строка из главы про модули, и переписана она не случайно: Hardhat третьей версии работает только с современной системой модулей. Файл настроек и тесты у него написаны через import, а не через старую форму подключения.

Отсюда следствие, которое стоит держать в голове: в этом проекте все файлы .ts и .js читаются как современные модули. Пример из интернета, написанный под Hardhat 2 со старой формой подключения, здесь упадёт с уже знакомой ошибкой про require.

Интересный факт

Заодно tsconfig.json пришёл с параметром "verbatimModuleSyntax": true. Он означает «не переписывай мои импорты»: как написано, так и останется. Ровно то, о чём была секция про расширения в путях.

Откуда npx берёт команду​

Вторая модель запускает одну и ту же команду в трёх разных папках:

── есть ли hardhat в системе вообще ──
which hardhat → не найдено: глобально не установлен

── что такое node_modules/.bin/hardhat ──
новый проект: node_modules/.bin/hardhat → ../hardhat/dist/src/cli.js
старый проект: node_modules/.bin/hardhat → ../hardhat/internal/cli/bootstrap.js

── одна и та же команда в двух папках ──
hh-fresh: npx hardhat --version → 3.16.0 (1.00 c)
hh-old : npx hardhat --version → 2.29.1 (1.03 c)

── а в папке, где проекта нет ──
npm warn exec The following package was not found and will be installed: hardhat@2.22.19
заняло: 6.7 c — npx полез в интернет
ОДНА КОМАНДА, ТРИ РАЗНЫХ ОТВЕТАпапка нового проекта3.16.0взято из node_modules/.binпапка старого проекта2.29.1рядом, но версия другаяпапка без проекта?npx уходит в интернет за последнейnpx ищет команду в node_modules/.bin текущей папки, потом выше — и только потом в сетипоэтому версия инструмента — свойство папки, а не компьютера: два проекта рядом живут на разных
Версия инструмента — свойство папки: соседние проекты живут на 3.16.0 и 2.29.1 одновременно

Порядок поиска у npx такой: сначала node_modules/.bin текущей папки, потом то же самое в папках выше, и только если нигде не нашлось — установка из интернета во временный каталог.

node_modules/.bin/hardhat — не программа, а ссылка на файл внутри установленного пакета. Видно даже, что в разных версиях она указывает на разные файлы: путь у третьей версии отличается от пути у второй.

Глобально Hardhat не установлен вовсе — which его не находит. И тем не менее команда работает в обеих папках проекта. Это и есть смысл пакета проекта.

Важно

Последняя строка прогона — про чемпионат. npx в папке без проекта уходит в интернет. В модуле интернета нет: команда, которая дома отрабатывает за шесть секунд, там просто не выполнится. Единственная защита — заранее установленные зависимости в папке проекта.

Диапазон, замок и то, что на диске​

Третья модель удаляет node_modules и восстанавливает его:

── что переживает удаление node_modules ──
до : node_modules 188M, файлов проекта 14
после : node_modules нет, файлов проекта 14
команда на месте? нет: node_modules/.bin/hardhat исчез вместе с папкой

── npm ci: восстановить ровно то, что записано в замке ──
added 262 packages, and audited 263 packages in 3s
заняло: 3.3 c (из кеша, без интернета)
версия: 3.16.0

── а если package.json и замок разошлись ──
npm error code EUSAGE
npm error `npm ci` can only install packages when your package.json and
package-lock.json or npm-shrinkwrap.json are in sync. Please update your
lock file with `npm install` before continuing.
ДИАПАЗОН, ЗАМОК И ТО, ЧТО РЕАЛЬНО НА ДИСКЕpackage.json"hardhat": "^3.16.0"это диапазон: годится любаяверсия 3.x не ниже 3.16.0package-lock.json"version": "3.16.0"это ровно одна версия —и так для всех 293 пакетовnode_modules3.16.0npm i — можно новееnpm ci — строго по замкуна чужой машине проект ставят через npm ci: он не пересобирает замок и не подсунет другую версиюnpm error EUSAGE: package.json и package-lock.json разошлисьэта ошибка означает, что кто-то правил список зависимостей руками и не обновил замок
В описании проекта — диапазон версий, в замке — ровно одна; npm ci ставит по замку и не переписывает его

Три файла говорят о версии разное, и путать их нельзя.

package.json: "hardhat": "^3.16.0" — это диапазон. Значок ^ означает «любая версия 3.x, начиная с 3.16.0». Через полгода та же строка установит 3.20 — и поведение проекта может измениться.

package-lock.json: "version": "3.16.0" — это ровно одна версия, и так для всех 293 пакетов, включая те, о которых мы никогда не слышали.

npm i может поставить новее в рамках диапазона и переписать замок. npm ci ставит строго по замку и замок не трогает вовсе. Поэтому на чужой машине и в проверке используют второе.

Восстановление заняло 3,3 секунды и прошло из кеша, без интернета — потому что эти пакеты уже скачивались на эту машину раньше. Это важная деталь для следующей секции.

Отвечено вопросов: 0 из 2
В папке проекта npx hardhat даёт 3.16.0, в соседней — 2.29.1. Почему?
Чем npm ci отличается от npm i?
Отвечено верно: 0 из 2

Семь часов без интернета​

Условия модуля: интернета нет, принести с собой нельзя ничего. Значит, всё, что обычно скачивается, должно быть скачано заранее — организаторами, на тот компьютер, за которым вы сидите.

Что именно скачивается и когда:

чтокогда тянетсясколько
пакеты из node_modulesnpm i или npm ci188 МБ, 293 пакета
компилятор Solidityпервая команда сборкипо версии, отдельно каждая
npx без проектакаждый разразмер пакета

Порядок первых минут, который стоит отработать:

  1. проверить, что папка проекта уже содержит node_modules — если да, ничего не трогать;
  2. если нет — npm ci, и смотреть, прошло ли оно; кеш на машине может быть, а может и не быть;
  3. сразу запустить сборку один раз: если компилятор не скачан, лучше узнать об этом на первой минуте, а не на пятом часу;
  4. запомнить версию: npx hardhat --version. Все дальнейшие вопросы «почему пример не работает» начинаются с неё.
Совет

Вторая и третья версии Hardhat несовместимы по файлу настроек. Прежде чем брать пример из интернета, посмотрите на его hardhat.config: если там require и module.exports — это Hardhat 2, и здесь он не заработает.

Отвечено вопросов: 0 из 2
На чемпионате нет интернета. Что из этого важнее всего проверить в первые минуты?
Пример из интернета не запускается в вашем проекте. С чего начать?
Отвечено верно: 0 из 2

Типичные ошибки​

Error HHE3: No Hardhat config file found. Запустили не из той папки. Hardhat ищет настройки в текущей папке и выше — так же, как npx ищет команду.

npm warn exec The following package was not found and will be installed. Эта строка означает, что npx не нашёл команду в проекте и полез в сеть. Дома незаметно, на чемпионате — отказ.

npm error EUSAGE. Кто-то поправил список зависимостей руками и не обновил замок. Лечится обычным npm i, после которого замок надо обязательно положить в репозиторий вместе с изменением.

Пример из интернета не запускается. Первым делом — версия. Hardhat 2 и Hardhat 3 отличаются файлом настроек, системой модулей и способом подключения к сети. Между ними нельзя «немного поправить».

node_modules в репозитории. Формально работает, практически — 188 МБ мусора, конфликты при слиянии и путаница с версиями. Для этого и существует .gitignore, который Hardhat положил сам.

Слова главы​

  • Пакет проекта — инструмент, установленный в папку, а не в систему; версия своя у каждого проекта.
  • --save-dev — «нужен только при разработке»: в результат не попадает.
  • npx — запустить команду из пакета: сначала ищет в проекте, потом выше, потом в сети.
  • node_modules/.bin — папка со ссылками на команды установленных пакетов.
  • Файл настроек — без него Hardhat отказывается работать: HHE3.
  • Заготовка проекта — готовый набор файлов; берём тот, что на mocha и ethers.
  • Диапазон версий — ^3.16.0 означает «любая 3.x не ниже указанной».
  • Замок версий — точные версии всех 293 пакетов; ставится командой npm ci.

Тренажёр: набрать вслепую​

Цель: скорость ≥ 100 зн/мин, точность ≥ 88%

npm init -y

На чемпионате​

Задание сдают папкой, и папку эту разворачивает не автор. Отсюда три правила, которые ничего не стоят, пока про них помнят.

Замок версий — в репозиторий обязательно. Без него принимающий получит другие версии пакетов и, возможно, другое поведение.

node_modules — никогда. Но в инструкции к решению напишите одну строку: «установка — npm ci». Иначе проверяющему придётся угадывать.

Версию инструмента назовите явно. Одна строка в README — «Hardhat 3.16, Node 24» — снимает половину вопросов ещё до запуска.

И последнее, про время. Создание проекта заняло 35 секунд с установкой 212 пакетов. Восстановление из кеша — 3 секунды. Скачивание компилятора — ещё столько же на первую сборку. Это не те цифры, из-за которых стоит нервничать, но и не ноль: первую сборку лучше сделать сразу, а не в конце.

Куда углубиться​

  • Что ещё умеет npx — запуск конкретной версии одной командой, без установки в проект.
  • Как устроены зависимости зависимостей — почему из одного пакета вырастает 293.
  • npm audit — отчёт об известных уязвимостях в установленном; при создании проекта он сразу показал несколько.
  • Другие инструменты той же роли — Foundry: те же задачи, но тесты пишут на Solidity, а не на TypeScript.

Сводная проверка по всей главе: 8 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.

Куда дальше: проверенные ресурсы​

  • Hardhat: Getting started — официальное начало работы с третьей версией.
  • Hardhat: Migrating from Hardhat 2 — чем именно отличаются версии.
  • npm: package.json — зависимости, диапазоны версий, поля описания.
  • npm ci — когда и почему используют именно её.
  • npx — порядок поиска команды и запуск без установки.

Видео по теме

ВидеоУстановка и настройка Hardhat для работы со смарт-контрактами EthereumIlya Krukowski
ВидеоЧто такое HardHat? Лучшее IDE для Ethereum разработки.Future Markt
Видеоpackage-lock.json - что это и зачем (npm ci)dev_unicorn
ВидеоNPM для начинающих. Полный гайд: установка, команды, флаги, разбор package.jsonАлександр Ламков — Friendly Frontend
ВидеоIntro to HardhatChainlink

Комментарии

Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.