Аккаунт в Waves: сид, ключи, адрес
Зачем это нужно
В прошлой главе сеть Waves поднялась в контейнерах, и мы посмотрели на неё снаружи. Теперь начинается работа изнутри, и первое, что нужно, — аккаунт.
В Waves это устроено не так, как в Ethereum, и совсем не так, как в Fabric. Аккаунт здесь начинается не с ключа и не с сертификата, а с фразы. Из неё математикой выводится всё остальное: закрытый ключ, публичный ключ и адрес. Никакой регистрации нет: адрес существует в тот же момент, как придумана фраза.
Эта глава — про эту цепочку, про то, почему адрес зависит от сети, и про то, как выглядят балансы. Всё ниже снято на локальном узле Waves 1.6.4, поднятом в контейнере.
Поднимаем узел для опытов
Для главы хватит одного контейнера — готового узла с собственной цепочкой и богатым счётом:
docker run -d --name waves-priv -p 6869:6869 wavesplatform/waves-private-node:latest
Проверяем через полминуты:
curl http://127.0.0.1:6869/blocks/height
curl http://127.0.0.1:6869/node/version
{"height":13}
{"version":"Waves v1.6.4"}
Высота растёт сама: узел выпускает блоки, даже когда в них нечего класть.
API Waves — это обычный REST. Всё, что делается кодом, можно сделать curl-ом, и наоборот. Это удобно на отладке: любой ответ библиотеки можно проверить прямым запросом.
Цепочка: сид → ключи → адрес
Ставим библиотеку и получаем аккаунт:
npm install @waves/ts-lib-crypto @waves/waves-transactions
const { address, publicKey } = require('@waves/ts-lib-crypto');
const seed = 'olegs test seed for pgk champs course 2026';
console.log('адрес: ', address(seed, 'R'));
console.log('публичный:', publicKey(seed));
сид: olegs test seed for pgk champs course 2026
адрес: 3MDKRTnd5H6zoscVfvSBiazwQaNmwDouJDx
публичный: BHXwGxyKaih2YKD8c7MQgtACk4zZSQR19e926GQfxeZ9
Запустим ещё раз — адрес тот же:
повтор: 3MDKRTnd5H6zoscVfvSBiazwQaNmwDouJDx
Это не кеш. Адрес — результат вычисления, а не запись в базе.
Сид — единственный пароль. Его нельзя восстановить: ни разработчики сети, ни владелец узла не знают о нём ничего. Потеряли — доступ пропал навсегда. Показали — отдали деньги.
Почему адрес зависит от сети
Тот же сид в другой сети даёт другой адрес:
адрес в сети R: 3MDKRTnd5H6zoscVfvSBiazwQaNmwDouJDx
адрес в сети W: 3PE1SPL7Wq1KBxnC73XrK1dJLiu4em1e7BM
Буква сети участвует в вычислении адреса, поэтому по началу адреса видно, где он живёт: 3P — основная сеть, 3N — тестовая, 3M — локальный узел.
Смысл в защите от дорогой ошибки: перевод в основной сети на адрес из тестовой не уйдёт в никуда, а будет отвергнут узлом ещё на проверке.
В Ethereum такого нет: адрес там одинаков во всех сетях, и деньги, отправленные «не в ту сеть», действительно теряются. Отсюда бесконечные предупреждения на биржах. Waves решает это на уровне формата адреса.
Смотрим баланс
Аккаунт только что придуман, на нём ничего нет:
curl http://127.0.0.1:6869/addresses/balance/3MDKRTnd5H6zoscVfvSBiazwQaNmwDouJDx
{"address":"3MDKRTnd5H6zoscVfvSBiazwQaNmwDouJDx","confirmations":0,"balance":0}
Обратите внимание: узел ответил спокойно, без «аккаунт не найден». Для сети любой адрес существует всегда, вопрос только в остатке.
У образа waves-private-node есть заранее пополненный счёт с известной фразой:
const rich = 'waves private node seed with waves tokens';
// адрес 3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF
{"address":"3M4qwDomRabJKLZxuXhwfqLApQkU592nWxF","confirmations":0,"balance":10000008650000000}
10000008650000000 — это 100 000 086,5 WAVES. У WAVES восемь знаков после запятой, и в сети хранится целое число «копеек». Дробных чисел в блокчейне нет вообще: любая попытка считать деньги дробями рано или поздно даст расхождение в последнем знаке.
Два разных счёта
Счёт в основной валюте и счёт в выпущенном токене — это разные вещи и разные запросы:
curl http://127.0.0.1:6869/addresses/balance/<адрес>
curl http://127.0.0.1:6869/assets/balance/<адрес>/<id актива>
{"address":"3M5HPFG1r9q79uxff6rm1Z3UFZcXXXHX32p","balance":500000000}
{"address":"3M5HPFG1r9q79uxff6rm1Z3UFZcXXXHX32p","assetId":"3fyDK2Da…","balance":100000}
Первое — 5 WAVES (восемь знаков). Второе — 1000,00 токена, у которого два знака. Одно и то же число 100000 означает разное в зависимости от актива, и число знаков надо смотреть в сведениях об активе.
Комиссия всегда списывается в WAVES, даже когда переводят токен. Аккаунт без WAVES не может пошевелиться, сколько бы токенов на нём ни лежало. Это первое, обо что спотыкаются при разборе «почему перевод не уходит».
Что ещё знает узел об аккаунте
curl http://127.0.0.1:6869/addresses/scriptInfo/<адрес>
{"address":"3MKM4xe4YSkkdKftqQwSp5GpYySBPxvhqd7","script":null,"scriptText":null,
"version":null,"complexity":0,"verifierComplexity":0,"callableComplexities":{},
"extraFee":0,"publicKey":null}
Пока на аккаунте нет скрипта, всё пусто. Это не ошибка, а обычное состояние: скрипт на аккаунте — необязательная надстройка, и именно ею Waves отличается от Ethereum. Там контракт живёт по собственному адресу; здесь код навешивают на обычный аккаунт, и тот превращается в смарт-аккаунт или в dApp.
К этому вернёмся через несколько глав. Пока достаточно запомнить: аккаунт — один, а поведение у него бывает разное.
Типичные ошибки
Ошибка 1. Придумывать сид руками.
test test test — рабочая фраза, и адрес по ней получится. В основной сети такой аккаунт опустошат за минуты: словарные фразы перебирают автоматически. Настоящий сид генерируют из словаря библиотекой:
const { randomSeed } = require('@waves/ts-lib-crypto');
const seed = randomSeed(); // 15 слов
Ошибка 2. Забыть букву сети.
address(seed); // адрес основной сети — по умолчанию 'W'
address(seed, 'R'); // адрес локального узла
Первый вариант молча даст адрес не той сети, и перевод отвергнется с невнятной жалобой на адрес.
Ошибка 3. Считать деньги дробями.
const skolko = 1.5 * 100000000; // 150000000.00000001 в иных случаях
Считать надо в целых: 150000000. Дробная арифметика в деньгах — классический источник расхождений в последнем знаке.
Ошибка 4. Держать сид в коде.
Сид в исходнике попадёт в репозиторий, а оттуда — куда угодно. В учебных примерах это допустимо, в рабочем коде — нет: только переменная окружения или хранилище секретов.
Ошибка 5. Путать публичный ключ и адрес.
Оба выглядят как строка из base58. Адрес короче и начинается с 3. Публичный ключ нужен для проверки подписи, адрес — для перевода; подставить один вместо другого узел не даст.
Шпаргалка по главе
| Что нужно | Как |
|---|---|
| Поднять узел | docker run -d --name waves-priv -p 6869:6869 wavesplatform/waves-private-node |
| Высота цепочки | curl .../blocks/height |
| Версия узла | curl .../node/version |
| Новый сид | randomSeed() из @waves/ts-lib-crypto |
| Адрес из сида | address(seed, 'R') |
| Публичный ключ | publicKey(seed) |
| Баланс WAVES | curl .../addresses/balance/<адрес> |
| Баланс токена | curl .../assets/balance/<адрес>/<id> |
| Скрипт на аккаунте | curl .../addresses/scriptInfo/<адрес> |
Словарь главы
| Термин | Что это |
|---|---|
| Сид-фраза | Текст, из которого выводится закрытый ключ; единственный пароль аккаунта |
| Закрытый ключ | 32 байта, которыми подписывают транзакции |
| Публичный ключ | Пара к закрытому; им проверяют подпись |
| Адрес | Короткая строка в base58, начинается с 3; её показывают для перевода |
| base58 | Кодировка без похожих знаков: нет 0, O, l, I |
| Буква сети | W основная, T тестовая, R локальный узел; участвует в адресе |
| «Копейки» | Целое число, в котором сеть хранит сумму; у WAVES восемь знаков |
| Смарт-аккаунт | Обычный аккаунт, на который навесили скрипт |
Цель: скорость ≥ 95 зн/мин, точность ≥ 88%
docker run -d --name waves-priv -p 6869:6869 wavesplatform/waves-private-node
Что должен уметь после главы
- поднять локальный узел Waves и проверить, что он живой;
- получить адрес и публичный ключ из сид-фразы;
- объяснить, почему цепочка работает только в одну сторону;
- объяснить, зачем буква сети вшита в адрес;
- прочитать баланс в WAVES и в токене и правильно поставить запятую;
- назвать пять типичных ошибок при работе с аккаунтом.
Проверка по главе
Сводная проверка по всей главе: 10 вопросов, 5:00 на всё, без подсказок по ходу. Вопросы показываются по одному, ответ изменить нельзя. Если время выйдет — экзамен завершится с тем, что успел ответить. Пересдавать можно сколько угодно раз.
Куда дальше: проверенные ресурсы
- Документация Waves: аккаунты — адрес, ключи, сид на русском языке.
- Waves node REST API — интерактивный справочник всех запросов.
- @waves/ts-lib-crypto — библиотека ключей и подписи.
- Образ waves-private-node — узел с собственной цепочкой для опытов.
Комментарии
Обсуждение живёт в GitHub Discussions и грузится с чужого домена — поэтому только по нажатию.