Blockwright. Манифест
Меня зовут - пока никак. Зовите меня Райт.
Днём я пишу продакшн-код на JS/TS. Здесь я строю то, ради чего вообще пришёл в разработку, - и беру вас с собой.
Этот канал - серия «Web3 для JS-разработчиков»: 20 постов, от «как на самом деле устроен блокчейн» до задеплоенного dApp с фронтендом и тестами. В конце мы взломаем собственный контракт - в учебных целях - и починим его.
Что построим: Копилку. On-chain piggy bank - копилка, которую у тебя не может отобрать никто. Даже я, её автор. Контракт + React, всё с нуля, весь код открыт.
Маршрут: фундамент → Solidity → фулстак-dApp → безопасность.
Формат:
- два поста в неделю, вторник и четверг, каждый читается за одну чашку кофе
- один пост = одна главная мысль + код в репозитории (тег на каждый пост - можно выкачать состояние проекта на любой момент серии)
- в конце поста - мини-задание, ответы в комментариях - кто пройдёт со мной до 20/20 - попадёт в список первопроходцев в финальном посте.
Это не последняя привилегия этого списка
Зачем это мне? У меня есть план длиной в несколько лет, и это - его первый шаг. Почему анонимно? Так надо. Однажды расскажу - история того стоит.
Старт - в четверг. Пост 1/20: «Зачем JS-разработчику web3 в 2026».
blockwright.eth · github.com/blockwright
Меня зовут - пока никак. Зовите меня Райт.
Днём я пишу продакшн-код на JS/TS. Здесь я строю то, ради чего вообще пришёл в разработку, - и беру вас с собой.
Этот канал - серия «Web3 для JS-разработчиков»: 20 постов, от «как на самом деле устроен блокчейн» до задеплоенного dApp с фронтендом и тестами. В конце мы взломаем собственный контракт - в учебных целях - и починим его.
Что построим: Копилку. On-chain piggy bank - копилка, которую у тебя не может отобрать никто. Даже я, её автор. Контракт + React, всё с нуля, весь код открыт.
Маршрут: фундамент → Solidity → фулстак-dApp → безопасность.
Формат:
- два поста в неделю, вторник и четверг, каждый читается за одну чашку кофе
- один пост = одна главная мысль + код в репозитории (тег на каждый пост - можно выкачать состояние проекта на любой момент серии)
- в конце поста - мини-задание, ответы в комментариях - кто пройдёт со мной до 20/20 - попадёт в список первопроходцев в финальном посте.
Это не последняя привилегия этого списка
Зачем это мне? У меня есть план длиной в несколько лет, и это - его первый шаг. Почему анонимно? Так надо. Однажды расскажу - история того стоит.
Старт - в четверг. Пост 1/20: «Зачем JS-разработчику web3 в 2026».
blockwright.eth · github.com/blockwright
Blockwright — web3 своими руками pinned «Blockwright. Манифест Меня зовут - пока никак. Зовите меня Райт. Днём я пишу продакшн-код на JS/TS. Здесь я строю то, ради чего вообще пришёл в разработку, - и беру вас с собой. Этот канал - серия «Web3 для JS-разработчиков»: 20 постов, от «как на самом…»
Начну с того, чего в этом канале не будет: сигналов, «иксов», торговых ботов и обещаний разбогатеть. Это канал про инженерию.
Теперь честно: а зачем тебе, JS-разработчику, вообще смотреть в сторону web3? Я вижу три ответа.
1. Арифметика конкуренции. В мире ~28 миллионов разработчиков. Активных web3-разработчиков — всего лишь около 21 тысячи. Не миллионов — тысяч. На хорошую фронтенд-вакансию ты конкурируешь с толпой; в web3 счёт идёт на десятки резюме. Рынок меньше — но и очередь несравнимо короче.
2. Деньги — без сказок. Вилки в web3 в среднем на 10–30% выше web2 при той же сеньорности: Solidity-разработчики — $100–250K в год, аудиторы смарт-контрактов — до $300K в год (по-нашему это $8–25K в месяц). Это глобальные цифры, и работа почти всегда удалённая — платят не по локальному рынку. Сверху обычно токен-гранты. Но скажу и минус, который от вас скроют продавцы курсов: рынок найма волатилен и ходит за крипто-циклами. Кто обещает стабильность — врёт.
3. Твой стек — уже большая часть пути. Фронтенд dApp — тот же React/TS, только вместо axios — viem и wagmi. Тесты, сборка, деплой фронта — всё знакомое. По-настоящему новое — смарт-контракты и мышление «код напрямую управляет деньгами, ошибка = потерянные деньги». Ровно этому и будем учиться.
Что будет в серии. За 20 постов построим Копилку — on-chain piggy bank: контракт на Solidity + React-фронтенд, с тестами, живым деплоем и одним взломом (нашего же контракта, намеренно — и починим). Весь код в открытом репо, на каждый пост — git-тег: можно выкачать проект в состоянии любого поста.
Маршрут: фундамент → Solidity → фулстак-dApp → безопасность. Два поста в неделю: вторник и четверг.
Задание №1 — самое простое в серии: напиши в комментариях свой стек и что до сих пор останавливало тебя от web3. Читаю всё — под ваши ответы настраиваю следующие посты.
Райт · blockwright.eth
github.com/blockwright/kopilka
Теперь честно: а зачем тебе, JS-разработчику, вообще смотреть в сторону web3? Я вижу три ответа.
1. Арифметика конкуренции. В мире ~28 миллионов разработчиков. Активных web3-разработчиков — всего лишь около 21 тысячи. Не миллионов — тысяч. На хорошую фронтенд-вакансию ты конкурируешь с толпой; в web3 счёт идёт на десятки резюме. Рынок меньше — но и очередь несравнимо короче.
2. Деньги — без сказок. Вилки в web3 в среднем на 10–30% выше web2 при той же сеньорности: Solidity-разработчики — $100–250K в год, аудиторы смарт-контрактов — до $300K в год (по-нашему это $8–25K в месяц). Это глобальные цифры, и работа почти всегда удалённая — платят не по локальному рынку. Сверху обычно токен-гранты. Но скажу и минус, который от вас скроют продавцы курсов: рынок найма волатилен и ходит за крипто-циклами. Кто обещает стабильность — врёт.
3. Твой стек — уже большая часть пути. Фронтенд dApp — тот же React/TS, только вместо axios — viem и wagmi. Тесты, сборка, деплой фронта — всё знакомое. По-настоящему новое — смарт-контракты и мышление «код напрямую управляет деньгами, ошибка = потерянные деньги». Ровно этому и будем учиться.
Что будет в серии. За 20 постов построим Копилку — on-chain piggy bank: контракт на Solidity + React-фронтенд, с тестами, живым деплоем и одним взломом (нашего же контракта, намеренно — и починим). Весь код в открытом репо, на каждый пост — git-тег: можно выкачать проект в состоянии любого поста.
Маршрут: фундамент → Solidity → фулстак-dApp → безопасность. Два поста в неделю: вторник и четверг.
Задание №1 — самое простое в серии: напиши в комментариях свой стек и что до сих пор останавливало тебя от web3. Читаю всё — под ваши ответы настраиваю следующие посты.
Райт · blockwright.eth
github.com/blockwright/kopilka
Первый день в эфире - и первый урок: комментарии, оказывается, надо не только включить, но и правильно привязать 😅 Теперь работают.
Так что задание №1 снова в силе: напиши в комментах свой стек и что останавливало тебя от web3. Проверим связь.
Так что задание №1 снова в силе: напиши в комментах свой стек и что останавливало тебя от web3. Проверим связь.
#словарь_райта · №1 - Event Sourcing
Обычное приложение хранит текущее состояние: в базе лежит баланс = 100, и при переводе цифра перезаписывается. История умирает при каждом UPDATE
Event sourcing переворачивает это: хранится не состояние, а история событий - +150, −50. А баланс = 100 - результат проигрывания всех событий с начала времён. Состояние можно снести и пересчитать из истории в любой момент - истина живёт в логе, а не в цифре
Ты сталкивался с этим у банка: выписка - это события, а остаток на счёте - производное от них
Зачем тебе это слово: завтра выйдет пост 2/20 - и окажется, что одна известная технология построена на этом принципе целиком
Райт · blockwright.eth
Обычное приложение хранит текущее состояние: в базе лежит баланс = 100, и при переводе цифра перезаписывается. История умирает при каждом UPDATE
Event sourcing переворачивает это: хранится не состояние, а история событий - +150, −50. А баланс = 100 - результат проигрывания всех событий с начала времён. Состояние можно снести и пересчитать из истории в любой момент - истина живёт в логе, а не в цифре
Ты сталкивался с этим у банка: выписка - это события, а остаток на счёте - производное от них
Зачем тебе это слово: завтра выйдет пост 2/20 - и окажется, что одна известная технология построена на этом принципе целиком
Райт · blockwright.eth
👍1
Забудь слово крипта. Сегодня смотрим на блокчейн как инженеры.
Блокчейн - это лог. Append-only лог транзакций, как WAL в Postgres или топик в Kafka: писать можно только в конец, менять прошлое нельзя. Раз в ~12 секунд очередная пачка транзакций упаковывается в блок, и каждый блок несёт в себе хеш предыдущего. Знакомая схема? Это git: цепочка коммитов, где подмена любого старого коммита рассыпает хеши всей истории после него.
А балансы кошельков - это не ячейки, которые где-то лежат. Это состояние, вычисленное из лога. Проекция. Materialized view поверх журнала событий. Event sourcing в чистом виде: истина - это история операций, а текущая цифра - производное от неё.
Чем это отличается от твоего Postgres:
1. Писать может кто угодно. Анонимно, без регистрации, без админа базы. Поэтому нужен механизм, которым тысячи незнакомых узлов договариваются, какой блок следующий, — консенсус. О нём отдельно.
2. Запись платная - тот самый газ. Твоя транзакция навсегда ложится в лог, который хранят десятки тысяч узлов по всему миру. Ты платишь не за INSERT - ты покупаешь кусочек вечного, отреплицированного на всю планету хранилища.
3. UPDATE и DELETE не существуют. Только append. Отменить транзакцию можно единственным способом - новой транзакцией в обратную сторону. Как
Вот и весь фундамент: реплицированный append-only лог + состояние как проекция + плата за место в вечности. Всё остальное в web3 - детали реализации поверх этой тройки, и мы до каждой доберёмся.
Задание №2 - назови в комментариях web2-технологию, которая по своей сути - тоже append-only log. Их вокруг больше, чем кажется.
Райт · blockwright.eth
github.com/blockwright/kopilka
Блокчейн - это лог. Append-only лог транзакций, как WAL в Postgres или топик в Kafka: писать можно только в конец, менять прошлое нельзя. Раз в ~12 секунд очередная пачка транзакций упаковывается в блок, и каждый блок несёт в себе хеш предыдущего. Знакомая схема? Это git: цепочка коммитов, где подмена любого старого коммита рассыпает хеши всей истории после него.
А балансы кошельков - это не ячейки, которые где-то лежат. Это состояние, вычисленное из лога. Проекция. Materialized view поверх журнала событий. Event sourcing в чистом виде: истина - это история операций, а текущая цифра - производное от неё.
Чем это отличается от твоего Postgres:
1. Писать может кто угодно. Анонимно, без регистрации, без админа базы. Поэтому нужен механизм, которым тысячи незнакомых узлов договариваются, какой блок следующий, — консенсус. О нём отдельно.
2. Запись платная - тот самый газ. Твоя транзакция навсегда ложится в лог, который хранят десятки тысяч узлов по всему миру. Ты платишь не за INSERT - ты покупаешь кусочек вечного, отреплицированного на всю планету хранилища.
3. UPDATE и DELETE не существуют. Только append. Отменить транзакцию можно единственным способом - новой транзакцией в обратную сторону. Как
git revert: старый коммит остаётся в истории навсегда, поверх просто добавляется отменяющий.Вот и весь фундамент: реплицированный append-only лог + состояние как проекция + плата за место в вечности. Всё остальное в web3 - детали реализации поверх этой тройки, и мы до каждой доберёмся.
Задание №2 - назови в комментариях web2-технологию, которая по своей сути - тоже append-only log. Их вокруг больше, чем кажется.
Райт · blockwright.eth
github.com/blockwright/kopilka
👍1
В web3 нет кнопки Sign up. Нет базы пользователей, нет «восстановить пароль», нет саппорта, который разблокирует аккаунт. И это не недоработка - это фундамент. Разбираемся.
Аккаунт - это случайное число. Приватный ключ - 256 случайных бит. Из него математика выводит публичный ключ, из публичного - твой адрес (то самое 0x...). Всё. Ты «зарегистрировался»: сгенерировал число у себя на устройстве, и сеть узнает о твоём существовании только при первой транзакции. Никто не выдавал тебе аккаунт - значит, никто не может его и отобрать.
Подпись вместо пароля. Пароль надо отправить серверу - и надеяться, что его не сольют. Приватный ключ не отправляется никому и никогда: он ставит криптографическую подпись под транзакцией, и любой может проверить её твоим адресом, не увидев ключа. Владение = знание ключа. Точка.
Отсюда легендарное «Not your keys - not your coins»: когда монеты «лежат на бирже», ключи - у биржи. У тебя не монеты, у тебя запись в её базе данных. Обещание. История знает десятки бирж, чьи обещания закончились внезапно.
Seed-фраза - это те же случайные биты, упакованные в 12–24 человекочитаемых слова. Из одной фразы детерминированно выводятся все твои ключи и адреса (это называется HD-кошелёк). Понимаешь масштаб: 12 слов на бумажке = все твои аккаунты, навсегда, на любом устройстве.
И главное недопонимание: кошелёк (MetaMask, Rabby) не хранит деньги. Деньги - записи в блокчейне. Кошелёк хранит ключи и подписывает транзакции - это менеджер паролей со встроенной подписывалкой, не сейф.
Да, и наша Копилка будет аккаунтом без приватного ключа - аккаунтом, которым управляет код. Но об этом в посте 7.
Задание №3 - поставь MetaMask или Rabby, создай кошелёк, получи тестовый ETH в сети Sepolia - рабочие фосеты собраны в репо, файл docs/faucets.md. Пришли свой тестовый адрес в комменты - соберу список первопроходцев прямо ончейн.
Кто вместо адреса пришлёт seed-фразу - отчислен. Это была первая проверка на внимательность.
Райт · blockwright.eth
github.com/blockwright/kopilka
Аккаунт - это случайное число. Приватный ключ - 256 случайных бит. Из него математика выводит публичный ключ, из публичного - твой адрес (то самое 0x...). Всё. Ты «зарегистрировался»: сгенерировал число у себя на устройстве, и сеть узнает о твоём существовании только при первой транзакции. Никто не выдавал тебе аккаунт - значит, никто не может его и отобрать.
Подпись вместо пароля. Пароль надо отправить серверу - и надеяться, что его не сольют. Приватный ключ не отправляется никому и никогда: он ставит криптографическую подпись под транзакцией, и любой может проверить её твоим адресом, не увидев ключа. Владение = знание ключа. Точка.
Отсюда легендарное «Not your keys - not your coins»: когда монеты «лежат на бирже», ключи - у биржи. У тебя не монеты, у тебя запись в её базе данных. Обещание. История знает десятки бирж, чьи обещания закончились внезапно.
Seed-фраза - это те же случайные биты, упакованные в 12–24 человекочитаемых слова. Из одной фразы детерминированно выводятся все твои ключи и адреса (это называется HD-кошелёк). Понимаешь масштаб: 12 слов на бумажке = все твои аккаунты, навсегда, на любом устройстве.
И главное недопонимание: кошелёк (MetaMask, Rabby) не хранит деньги. Деньги - записи в блокчейне. Кошелёк хранит ключи и подписывает транзакции - это менеджер паролей со встроенной подписывалкой, не сейф.
Да, и наша Копилка будет аккаунтом без приватного ключа - аккаунтом, которым управляет код. Но об этом в посте 7.
Задание №3 - поставь MetaMask или Rabby, создай кошелёк, получи тестовый ETH в сети Sepolia - рабочие фосеты собраны в репо, файл docs/faucets.md. Пришли свой тестовый адрес в комменты - соберу список первопроходцев прямо ончейн.
Кто вместо адреса пришлёт seed-фразу - отчислен. Это была первая проверка на внимательность.
Райт · blockwright.eth
github.com/blockwright/kopilka
#словарь_райта · №2 - Materialized View
Обычный VIEW в SQL - сохранённый запрос: каждое обращение выполняет его заново. Дёшево хранить, дорого читать
Materialized view - запрос, результат которого материализован: сохранён как готовая таблица и обновляется при изменении данных. Платишь местом и обновлением - получаешь мгновенное чтение. Это предвычисленный ответ на вопрос, который задают часто
Из этой же семьи: кэш, агрегаты в аналитике, счётчик лайков (никто не пересчитывает лайки заново при каждом открытии поста)
Зачем тебе это слово: во вторник в посте 2/20 мы говорили, что «баланс кошелька» в блокчейне нигде не лежит - он вычисляется из журнала транзакций. Теперь у тебя есть точный термин: баланс - это materialized view поверх лога
Райт · blockwright.eth
Обычный VIEW в SQL - сохранённый запрос: каждое обращение выполняет его заново. Дёшево хранить, дорого читать
Materialized view - запрос, результат которого материализован: сохранён как готовая таблица и обновляется при изменении данных. Платишь местом и обновлением - получаешь мгновенное чтение. Это предвычисленный ответ на вопрос, который задают часто
Из этой же семьи: кэш, агрегаты в аналитике, счётчик лайков (никто не пересчитывает лайки заново при каждом открытии поста)
Зачем тебе это слово: во вторник в посте 2/20 мы говорили, что «баланс кошелька» в блокчейне нигде не лежит - он вычисляется из журнала транзакций. Теперь у тебя есть точный термин: баланс - это materialized view поверх лога
Райт · blockwright.eth
👍1
#словарь_райта · №3 - Консенсус
В web2 эта задача давно решена: Raft, Paxos, ZooKeeper. Пять реплик твоей базы голосуют, кто лидер и в каком порядке применять записи. Работает, потому что все узлы - твои: их подняла твоя команда, они живут в твоём облаке и доверяют друг другу по определению.
Консенсус в блокчейне - та же задача на максимальной сложности: тысячи узлов, у которых нет общего хозяина, договариваются о каждом следующем блоке. Доверие заменено экономикой: хочешь участвовать - вносишь залог (стейк); подпишешь две противоречащие версии истории - протокол сожжёт залог автоматически. Честность тут не предположение о людях, а самая выгодная стратегия.
Зачем тебе это слово: в посте 2/20 мы оставили консенсус «за скобками». Скобки открыты. А во вторник посмотрим, как твой код разговаривает с этими узлами.
Райт · blockwright.eth
В web2 эта задача давно решена: Raft, Paxos, ZooKeeper. Пять реплик твоей базы голосуют, кто лидер и в каком порядке применять записи. Работает, потому что все узлы - твои: их подняла твоя команда, они живут в твоём облаке и доверяют друг другу по определению.
Консенсус в блокчейне - та же задача на максимальной сложности: тысячи узлов, у которых нет общего хозяина, договариваются о каждом следующем блоке. Доверие заменено экономикой: хочешь участвовать - вносишь залог (стейк); подпишешь две противоречащие версии истории - протокол сожжёт залог автоматически. Честность тут не предположение о людях, а самая выгодная стратегия.
Зачем тебе это слово: в посте 2/20 мы оставили консенсус «за скобками». Скобки открыты. А во вторник посмотрим, как твой код разговаривает с этими узлами.
Райт · blockwright.eth
У блокчейна нет REST API. Есть кое-что постарше и, внезапно, проще - JSON-RPC, протокол из середины нулевых.
Когда MetaMask показывает твой баланс, он не «лезет в блокчейн». Он спрашивает ноду - сервер, который хранит копию того самого append-only лога из поста 2 и отвечает на запросы:
Один эндпоинт, имя метода в теле, никаких /v2/users/:id. Весь web3 - кошельки, дексы, эксплореры - ходит в сеть вот этим протоколом: eth_getBalance, eth_call, eth_sendRawTransaction. Скоро ты будешь дёргать их сам.
Вопрос только один: чью ноду спрашивать? Три пути:
1. Публичные RPC - бесплатные эндпоинты без регистрации. Плюс: ноль порога. Минусы: жёсткие лимиты, падают когда хотят, и - про это забывают - оператор видит твой IP и адреса, которыми ты интересуешься. Для учёбы годится, для продукта - нет.
2. Провайдеры (Alchemy, Infura, QuickNode): free-tier с головой хватает на пет-проекты, стабильность, дашборды запросов. Минус концептуальный: твоё «децентрализованное» приложение разговаривает с миром через одну компанию, которая видит каждый его запрос.
3. Своя нода. Полный контроль и приватность, цена - сотни гигабайт диска и вечная синхронизация. Для нашей серии оверкилл, но знать, что этот путь есть, обязательно: это опция выхода, на которой держится вся модель доверия.
Для Копилки возьмём провайдера с бесплатным тарифом плюс публичный эндпоинт как запасной - так и соберём в посте 5, когда отправим первую транзакцию кодом.
И тонкость, ради которой стоило дочитать: MetaMask из коробки ходит через Infura. То есть дефолтный стек «децентрализованного» веба зависит от одной компании чуть более чем полностью. Децентрализация - это спектр, а не бинарник. Запомни эту рамку - она объясняет половину архитектурных решений в web3.
Задание №4: открой настройки сети в своём кошельке и посмотри, какой RPC URL там прописан. Бонус для смелых: дёрни
Райт · blockwright.eth
github.com/blockwright/kopilka
Когда MetaMask показывает твой баланс, он не «лезет в блокчейн». Он спрашивает ноду - сервер, который хранит копию того самого append-only лога из поста 2 и отвечает на запросы:
{
"jsonrpc":"2.0",
"method":"eth_getBalance",
"params": [
"0xТвойАдрес",
"latest"
],
"id":1
}Один эндпоинт, имя метода в теле, никаких /v2/users/:id. Весь web3 - кошельки, дексы, эксплореры - ходит в сеть вот этим протоколом: eth_getBalance, eth_call, eth_sendRawTransaction. Скоро ты будешь дёргать их сам.
Вопрос только один: чью ноду спрашивать? Три пути:
1. Публичные RPC - бесплатные эндпоинты без регистрации. Плюс: ноль порога. Минусы: жёсткие лимиты, падают когда хотят, и - про это забывают - оператор видит твой IP и адреса, которыми ты интересуешься. Для учёбы годится, для продукта - нет.
2. Провайдеры (Alchemy, Infura, QuickNode): free-tier с головой хватает на пет-проекты, стабильность, дашборды запросов. Минус концептуальный: твоё «децентрализованное» приложение разговаривает с миром через одну компанию, которая видит каждый его запрос.
3. Своя нода. Полный контроль и приватность, цена - сотни гигабайт диска и вечная синхронизация. Для нашей серии оверкилл, но знать, что этот путь есть, обязательно: это опция выхода, на которой держится вся модель доверия.
Для Копилки возьмём провайдера с бесплатным тарифом плюс публичный эндпоинт как запасной - так и соберём в посте 5, когда отправим первую транзакцию кодом.
И тонкость, ради которой стоило дочитать: MetaMask из коробки ходит через Infura. То есть дефолтный стек «децентрализованного» веба зависит от одной компании чуть более чем полностью. Децентрализация - это спектр, а не бинарник. Запомни эту рамку - она объясняет половину архитектурных решений в web3.
Задание №4: открой настройки сети в своём кошельке и посмотри, какой RPC URL там прописан. Бонус для смелых: дёрни
eth_blockNumber публичной ноды через curl - готовая команда лежит в репо (docs/rpc.md), пришли в комменты номер блока, который тебе ответили.Райт · blockwright.eth
github.com/blockwright/kopilka
#словарь_райта · №4 - Хеш-функция
Ты пользуешься ей каждый день: хеш git-коммита - это она. Функция, которая превращает любые данные в короткий отпечаток фиксированной длины.
Три свойства делают её фундаментом всего web3.
- Детерминированность: одинаковый вход - всегда одинаковый отпечаток
- Лавинный эффект: поменяй один байт - отпечаток изменится неузнаваемо
- Необратимость: из отпечатка нельзя восстановить данные, только проверить совпадение
Знакомо по web2: контрольные суммы файлов, хеши паролей в базе, ETag в HTTP-кеше
Зачем тебе это слово: «каждый блок несёт хеш предыдущего» из поста 2/20 - теперь ты точно знаешь, почему подмена старого блока рассыпает всю цепочку: лавинный эффект не оставляет шансов сделать это незаметно.
Райт · blockwright.eth
Ты пользуешься ей каждый день: хеш git-коммита - это она. Функция, которая превращает любые данные в короткий отпечаток фиксированной длины.
Три свойства делают её фундаментом всего web3.
- Детерминированность: одинаковый вход - всегда одинаковый отпечаток
- Лавинный эффект: поменяй один байт - отпечаток изменится неузнаваемо
- Необратимость: из отпечатка нельзя восстановить данные, только проверить совпадение
Знакомо по web2: контрольные суммы файлов, хеши паролей в базе, ETag в HTTP-кеше
Зачем тебе это слово: «каждый блок несёт хеш предыдущего» из поста 2/20 - теперь ты точно знаешь, почему подмена старого блока рассыпает всю цепочку: лавинный эффект не оставляет шансов сделать это незаметно.
Райт · blockwright.eth
Четыре поста мы собирали детали: лог (пост 2), ключи (пост 3), ноды и JSON-RPC (пост 4). Сегодня соединяем всё в 20 строк TypeScript - и отправляем настоящую транзакцию в настоящую сеть.
Подготовка. Нужны: тестовый кошелёк из поста 3, немного Sepolia ETH (фосеты - в репо, docs/faucets.md) и приватный ключ этого кошелька в переменной окружения:
bash
Грабля, о которую споткнёшься первым же запуском: MetaMask экспортирует ключ без префикса
И вторая, из поста 4:
Два правила навсегда: ключ живёт в env или .env-файле (который в .gitignore), и это ключ отдельного тестового кошелька - НИКОГДА основного.
Код целиком:
Запуск:
-
-
Что произошло за эти секунды - по мотивам всего блока:
viem подписал транзакцию локально твоим ключом.
1. Приватный ключ не покинул машину - в сеть ушли только подписанные байты.
2. Подписанные байты улетели на ноду тем самым
3. Транзакция подождала в очереди, валидатор включил её в блок - новая запись в append-only логе из поста 2, навсегда
4.
Открой ссылку из вывода: твоя транзакция лежит в публичном логе, виден блок, газ, подпись. Это уже не туториал - это ончейн-факт, который переживёт нас обоих.
Кстати, «отправить самому себе» - не шутка, а честная транзакция: сеть всё равно проверила подпись, взяла газ и записала её в вечность. Идеальный первый шаг без риска промахнуться адресом.
Задание №5: запусти скрипт и пришли хеш своей транзакции в комменты. Соберём под этим постом первую пачку ончейн-артефактов канала. Если фосет жадничает - вспомни docs/faucets.md, там есть PoW-вариант без лимитов.
Блок «Фундамент» закрыт. Со следующего поста - Solidity: пишем контракт Копилки.
Райт · blockwright.eth
github.com/blockwright/kopilka · tag post-05
Подготовка. Нужны: тестовый кошелёк из поста 3, немного Sepolia ETH (фосеты - в репо, docs/faucets.md) и приватный ключ этого кошелька в переменной окружения:
bash
export SEPOLIA_PRIVATE_KEY=0x... # ключ ТОЛЬКО тестового кошелька
Грабля, о которую споткнёшься первым же запуском: MetaMask экспортирует ключ без префикса
0x- просто 64 hex-символа. Допиши 0x в начало сам, иначе получишь загадочное «invalid private key, expected hex or 32 bytes».И вторая, из поста 4:
http() без аргумента отправит тебя на дефолтную публичную ноду viem - она под таким rate-limit, что чтение ещё переживёт, а отправку транзакции встретит ошибкой 429. Поэтому в коде нода задана явно - та самая из docs/rpc.md. Не выбрал ноду сам - за тебя выбрали, и плохо.Два правила навсегда: ключ живёт в env или .env-файле (который в .gitignore), и это ключ отдельного тестового кошелька - НИКОГДА основного.
Код целиком:
import { createWalletClient, createPublicClient, http,
parseEther, formatEther } from 'viem';
import { privateKeyToAccount } from 'viem/accounts';
import { sepolia } from 'viem/chains';
const account = privateKeyToAccount(
process.env.SEPOLIA_PRIVATE_KEY as `0x${string}`
);
// нода — из docs/rpc.md. Дефолтная у viem — под rate-limit (урок поста 4!)
const RPC = 'https://ethereum-sepolia-rpc.publicnode.com';
const publicClient = createPublicClient({ chain: sepolia, transport: http(RPC) });
const wallet = createWalletClient({ account, chain: sepolia, transport: http(RPC) });
const balance = await publicClient.getBalance({ address: account.address });
console.log('Баланс:', formatEther(balance), 'ETH');
// отправляем 0.001 тестового ETH... самому себе. Для первого раза — идеально
const hash = await wallet.sendTransaction({
to: account.address,
value: parseEther('0.001'),
});
console.log('Отправлена:', hash);
console.log('Смотри: https://sepolia.etherscan.io/tx/' + hash);
const receipt = await publicClient.waitForTransactionReceipt({ hash });
console.log('В блоке:', receipt.blockNumber, '· статус:', receipt.status);Запуск:
-
npx tsx send.ts - если ключ экспортирован в шелле,-
npx tsx --env-file=.env send.ts - если лежит в .env-файлеЧто произошло за эти секунды - по мотивам всего блока:
viem подписал транзакцию локально твоим ключом.
1. Приватный ключ не покинул машину - в сеть ушли только подписанные байты.
2. Подписанные байты улетели на ноду тем самым
eth_sendRawTransaction из поста 43. Транзакция подождала в очереди, валидатор включил её в блок - новая запись в append-only логе из поста 2, навсегда
4.
waitForTransactionReceipt дождался этого блока и принёс квитанциюОткрой ссылку из вывода: твоя транзакция лежит в публичном логе, виден блок, газ, подпись. Это уже не туториал - это ончейн-факт, который переживёт нас обоих.
Кстати, «отправить самому себе» - не шутка, а честная транзакция: сеть всё равно проверила подпись, взяла газ и записала её в вечность. Идеальный первый шаг без риска промахнуться адресом.
Задание №5: запусти скрипт и пришли хеш своей транзакции в комменты. Соберём под этим постом первую пачку ончейн-артефактов канала. Если фосет жадничает - вспомни docs/faucets.md, там есть PoW-вариант без лимитов.
Блок «Фундамент» закрыт. Со следующего поста - Solidity: пишем контракт Копилки.
Райт · blockwright.eth
github.com/blockwright/kopilka · tag post-05
#словарь_райта · №5 - Мемпул
Вчера в посте 5/20 ты отправил первую транзакцию. Между «нажал отправить» и «легла в блок» она жила в мемпуле.
Мемпул - очередь задач перед воркером, только распределённая: каждый узел держит свой список транзакций-кандидатов, которые ещё не попали в блок. Знакомая картина: message queue перед консьюмером, задачи в Redis перед обработчиком.
Одно важное отличие: это не FIFO, а priority queue, где приоритет покупается. Валидатор собирает блок из самых «дорогих» транзакций — кто предложил больше за газ, тот и первый. Заплатил мало - висишь в очереди, пока сеть не разгрузится.
Зачем тебе это слово: «транзакция зависла» почти всегда означает «стоит в мемпуле с низкой ценой газа». Теперь ты знаешь, где именно она стоит.
Райт · blockwright.eth
Вчера в посте 5/20 ты отправил первую транзакцию. Между «нажал отправить» и «легла в блок» она жила в мемпуле.
Мемпул - очередь задач перед воркером, только распределённая: каждый узел держит свой список транзакций-кандидатов, которые ещё не попали в блок. Знакомая картина: message queue перед консьюмером, задачи в Redis перед обработчиком.
Одно важное отличие: это не FIFO, а priority queue, где приоритет покупается. Валидатор собирает блок из самых «дорогих» транзакций — кто предложил больше за газ, тот и первый. Заплатил мало - висишь в очереди, пока сеть не разгрузится.
Зачем тебе это слово: «транзакция зависла» почти всегда означает «стоит в мемпуле с низкой ценой газа». Теперь ты знаешь, где именно она стоит.
Райт · blockwright.eth
#словарь_райта · №6 - Nonce
У каждого аккаунта в Ethereum есть счётчик отправленных транзакций: первая - nonce 0, вторая - nonce 1, и так далее. Обычный автоинкремент, как ID в таблице.
Зачем он нужен? Две вещи
- Порядок: транзакция с nonce 5 не исполнится раньше, чем 4 - как миграции в базе, строго по номерам
- Защита от повтора: без nonce подписанную транзакцию «перевести 100» можно было бы отправить в сеть ещё раз — и ещё. Replay-атака в чистом виде; nonce делает каждую подпись одноразовой.
Побочный эффект, о который спотыкаются все: отправил транзакцию с nonce 4 и низким газом — она застряла, и все следующие (5, 6, 7...) ждут её. Дырка в автоинкременте блокирует очередь.
Зачем тебе это слово: без него не прочитать ни один разбор «почему у меня зависли все транзакции».
Райт · blockwright.eth
У каждого аккаунта в Ethereum есть счётчик отправленных транзакций: первая - nonce 0, вторая - nonce 1, и так далее. Обычный автоинкремент, как ID в таблице.
Зачем он нужен? Две вещи
- Порядок: транзакция с nonce 5 не исполнится раньше, чем 4 - как миграции в базе, строго по номерам
- Защита от повтора: без nonce подписанную транзакцию «перевести 100» можно было бы отправить в сеть ещё раз — и ещё. Replay-атака в чистом виде; nonce делает каждую подпись одноразовой.
Побочный эффект, о который спотыкаются все: отправил транзакцию с nonce 4 и низким газом — она застряла, и все следующие (5, 6, 7...) ждут её. Дырка в автоинкременте блокирует очередь.
Зачем тебе это слово: без него не прочитать ни один разбор «почему у меня зависли все транзакции».
Райт · blockwright.eth
