Прямой запрос к продовой цепочке voskhod (185.70.105.87) показал реальный
on-chain тип программы Благорост — 'capital' (program_id=4), не 'blagorost'.
Прод годами работает с этим значением, ошибок в логах нет. Предыдущий коммит
(5360daa471) поменял константу на 'blagorost' по данным ТОЛЬКО локальной
dev-цепочки mono-ai-2 — для прода это было бы регрессией. Откатываю.
Настоящий источник дрейфа — boot-сидинг: components/boot/src/init/cooperative.ts
createPrograms() и src/scripts/seed-capital/phases/01-programs.ts заводили
новый кооператив (createprog) с type='blagorost', расходясь с давно
задеплоенным продовым значением. Правлю сидинг под реальность, а не наоборот
(та же логика, что 'дрейф стандарт↔код — прав контракт': on-chain состояние
неизменяемо и авторитетно, код подстраивается). Заодно поправлены прочие
литералы 'blagorost' в тестах boot (capital.test.ts, capital-import.test.ts,
08-investments.ts, tests/capital/consts.ts), которые создавали/подписывали
программу под тем же неверным именем.
> monocoop@ reboot /home/admin/mono-ai-2
> cd components/boot/scripts && bash reboot.sh
Останавливаем и удаляем контейнеры с volumes...
Останавливаем blockchain контейнер...
Удаляем blockchain data...
Пересоздаем и запускаем базы данных...
Ждем готовности MongoDB...
MongoDB готов!
Ждем готовности PostgreSQL...
PostgreSQL готов!
Запускаем boot процесс...
> @coopenomics/boot@2026.6.24 boot /home/admin/mono-ai-2/components/boot
> esno src/index.ts boot
Node is healthy. Continue. {
server_version: [32m'ee002f93'[39m,
chain_id: [32m'db79c8409645082749ca50640d6f4ee511575acf26c4e2c8e4748e6bf6a01ed4'[39m,
head_block_num: [33m10[39m,
last_irreversible_block_num: [33m9[39m,
last_irreversible_block_id: [32m'000000093c561104c62b9058c82eab12559686eba92fdbe4bcf4df9bf2600131'[39m,
head_block_id: [32m'0000000ae4bffe027ec2a2c89ca92832422a84ec052649f1a80436fff5c61327'[39m,
head_block_time: [32m'2026-07-19T11:48:57.500'[39m,
head_block_producer: [32m'eosio'[39m,
virtual_block_cpu_limit: [33m1008036[39m,
virtual_block_net_limit: [33m1058054[39m,
block_cpu_limit: [33m1000000[39m,
block_net_limit: [33m1048576[39m,
server_version_string: [32m'v6.0.0'[39m,
fork_db_head_block_num: [33m10[39m,
fork_db_head_block_id: [32m'0000000ae4bffe027ec2a2c89ca92832422a84ec052649f1a80436fff5c61327'[39m,
server_full_version_string: [32m'v6.0.0-ee002f9372237aa07b05879df772a95f9d54867f-dirty'[39m,
total_cpu_weight: [33m0[39m,
total_net_weight: [33m0[39m,
earliest_available_block_num: [33m1[39m,
last_irreversible_block_time: [32m'2026-07-19T11:48:57.000'[39m
}
Created account: eosio.token
Created account: eosio.bpay
Created account: eosio.vpay
Created account: eosio.msig
Created account: eosio.wrap
Created account: eosio.power
Created account: eosio.saving
Created account: registrator
Created account: capital
Created account: loan
Created account: ledger
Created account: ledger2
Created account: test
Created account: meet
Created account: wallet
Created account: soviet
Created account: branch
Created account: marketplace
Created account: draft
Created account: gateway
Created account: fund
Created account: contributor
Created account: apps
Created account: expense
Created account: voskhod
ok -> init activation: { result: [32m'ok'[39m }
on set: {
name: [32m'eosio.boot'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.boot'[39m,
target: [32m'eosio'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.boot/eosio.boot.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.boot/eosio.boot.abi
contract setted: eosio
Фича активирована: ACTION_RETURN_VALUE
Фича активирована: CONFIGURABLE_WASM_LIMITS2
Фича активирована: BLOCKCHAIN_PARAMETERS
Фича активирована: GET_SENDER
Фича активирована: FORWARD_SETCODE
Фича активирована: ONLY_BILL_FIRST_AUTHORIZER
Фича активирована: RESTRICT_ACTION_TO_SELF
Фича активирована: DISALLOW_EMPTY_PRODUCER_SCHEDULE
Фича активирована: FIX_LINKAUTH_RESTRICTION
Фича активирована: REPLACE_DEFERRED
Фича активирована: NO_DUPLICATE_DEFERRED_ID
Фича активирована: ONLY_LINK_TO_EXISTING_PERMISSION
Фича активирована: RAM_RESTRICTIONS
Фича активирована: WEBAUTHN_KEY
Фича активирована: WTMSIG_BLOCK_SIGNATURES
Фича активирована: GET_CODE_HASH
Фича активирована: GET_BLOCK_NUM
Фича активирована: CRYPTO_PRIMITIVES
on set: {
name: [32m'eosio.system'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.system'[39m,
target: [32m'eosio'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.system/eosio.system.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.system/eosio.system.abi
contract setted: eosio
on set: {
name: [32m'eosio.token'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.token'[39m,
target: [32m'eosio.token'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.token/eosio.token.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.token/eosio.token.abi
contract setted: eosio.token
on set: {
name: [32m'eosio.msig'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.msig'[39m,
target: [32m'eosio.msig'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.msig/eosio.msig.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.msig/eosio.msig.abi
contract setted: eosio.msig
on set: {
name: [32m'eosio.wrap'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.wrap'[39m,
target: [32m'eosio.wrap'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.wrap/eosio.wrap.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.wrap/eosio.wrap.abi
contract setted: eosio.wrap
on set: {
name: [32m'registrator'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/registrator'[39m,
target: [32m'registrator'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/registrator/registrator.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/registrator/registrator.abi
contract setted: registrator
on set: {
name: [32m'soviet'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/soviet'[39m,
target: [32m'soviet'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/soviet/soviet.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/soviet/soviet.abi
contract setted: soviet
on set: {
name: [32m'marketplace'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/marketplace'[39m,
target: [32m'marketplace'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/marketplace/marketplace.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/marketplace/marketplace.abi
contract setted: marketplace
on set: {
name: [32m'draft'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/draft'[39m,
target: [32m'draft'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/draft/draft.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/draft/draft.abi
contract setted: draft
on set: {
name: [32m'branch'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/branch'[39m,
target: [32m'branch'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/branch/branch.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/branch/branch.abi
contract setted: branch
on set: {
name: [32m'gateway'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/gateway'[39m,
target: [32m'gateway'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/gateway/gateway.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/gateway/gateway.abi
contract setted: gateway
on set: {
name: [32m'fund'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/fund'[39m,
target: [32m'fund'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/fund/fund.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/fund/fund.abi
contract setted: fund
on set: {
name: [32m'ledger'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/ledger'[39m,
target: [32m'ledger'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/ledger/ledger.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/ledger/ledger.abi
contract setted: ledger
on set: {
name: [32m'ledger2'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/ledger2'[39m,
target: [32m'ledger2'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/ledger2/ledger2.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/ledger2/ledger2.abi
contract setted: ledger2
on set: {
name: [32m'test'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/test'[39m,
target: [32m'test'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/test/test.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/test/test.abi
contract setted: test
on set: {
name: [32m'contributor'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/contributor'[39m,
target: [32m'contributor'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/contributor/contributor.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/contributor/contributor.abi
contract setted: contributor
on set: {
name: [32m'capital'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/capital'[39m,
target: [32m'capital'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/capital/capital.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/capital/capital.abi
contract setted: capital
on set: {
name: [32m'wallet'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/wallet'[39m,
target: [32m'wallet'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/wallet/wallet.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/wallet/wallet.abi
contract setted: wallet
on set: {
name: [32m'loan'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/loan'[39m,
target: [32m'loan'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/loan/loan.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/loan/loan.abi
contract setted: loan
on set: {
name: [32m'meet'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/meet'[39m,
target: [32m'meet'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/meet/meet.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/meet/meet.abi
contract setted: meet
on set: {
name: [32m'apps'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/apps'[39m,
target: [32m'apps'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/apps/apps.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/apps/apps.abi
contract setted: apps
on set: {
name: [32m'expense'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/expense'[39m,
target: [32m'expense'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/expense/expense.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/expense/expense.abi
contract setted: expense
создаём токен
Токен создан: { issuer: [32m'eosio'[39m, maximum_supply: [32m'1000000000.0000 AXON'[39m }
выпускаем токены
Токен выпущен: { to: [32m'eosio'[39m, quantity: [32m'100000.0000 AXON'[39m, memo: [32m''[39m }
Updated account permissions: eosio.saving -> eosio.saving
Updated account permissions: registrator -> registrator
Updated account permissions: capital -> capital
Updated account permissions: loan -> loan
Updated account permissions: ledger -> ledger
Updated account permissions: ledger2 -> ledger2
Updated account permissions: test -> test
Updated account permissions: meet -> meet
Updated account permissions: wallet -> wallet
Updated account permissions: soviet -> soviet
Updated account permissions: branch -> branch
Updated account permissions: marketplace -> marketplace
Updated account permissions: draft -> draft
Updated account permissions: gateway -> gateway
Updated account permissions: fund -> fund
Updated account permissions: contributor -> contributor
Updated account permissions: apps -> apps
Updated account permissions: expense -> expense
Updated account permissions: voskhod -> registrator
Системный контракт инициализирован { version: [33m0[39m, core: [32m'4,AXON'[39m }
Эмиссия инициализирована {
init_supply: [32m'1000.0000 AXON'[39m,
tact_duration: [33m86400[39m,
emission_factor: [33m0.618[39m
}
Система аренды инициализирована { args: { powerup_days: [33m1[39m, min_powerup_fee: [32m'0.0001 AXON'[39m } }
Шаблон создан: 1
Шаблон создан: 2
Шаблон создан: 3
Шаблон создан: 4
Шаблон создан: 50
Шаблон создан: 51
Шаблон создан: 100
Шаблон создан: 101
Шаблон создан: 200
Шаблон создан: 201
Шаблон создан: 300
Шаблон создан: 301
Шаблон создан: 302
Шаблон создан: 303
Шаблон создан: 304
Шаблон создан: 501
Шаблон создан: 599
Шаблон создан: 600
Шаблон создан: 699
Шаблон создан: 700
Шаблон создан: 701
Шаблон создан: 702
Шаблон создан: 800
Шаблон создан: 801
Шаблон создан: 802
Шаблон создан: 900
Шаблон создан: 901
Шаблон создан: 994
Шаблон создан: 995
Шаблон создан: 996
Шаблон создан: 997
Шаблон создан: 998
Шаблон создан: 999
Шаблон создан: 1000
Шаблон создан: 1001
Шаблон создан: 1002
Шаблон создан: 1003
Шаблон создан: 1004
Шаблон создан: 1005
Шаблон создан: 1006
Шаблон создан: 1007
Шаблон создан: 1010
Шаблон создан: 1011
Шаблон создан: 1020
Шаблон создан: 1025
Шаблон создан: 1030
Шаблон создан: 1040
Шаблон создан: 1041
Шаблон создан: 1042
Шаблон создан: 1050
Шаблон создан: 1051
Шаблон создан: 1060
Шаблон создан: 1061
Шаблон создан: 1062
Шаблон создан: 1070
Шаблон создан: 1071
Шаблон создан: 1072
Шаблон создан: 1080
Шаблон создан: 1090
Шаблон создан: 2010
Шаблон создан: 2011
Арендуем ресурсы провайдеру
Аренда ресурсов: {
payer: [32m'eosio'[39m,
receiver: [32m'voskhod'[39m,
days: [33m1[39m,
payment: [32m'10000.0000 AXON'[39m,
transfer: [33mtrue[39m
}
{ from: [32m'eosio'[39m, to: [32m'voskhod'[39m, quantity: [32m'1000.0000 AXON'[39m, memo: [32m''[39m }
Перевод токенов: { from: [32m'eosio'[39m, to: [32m'voskhod'[39m, quantity: [32m'1000.0000 AXON'[39m, memo: [32m''[39m }
Базовая инфраструктура установлена
Провайдер добавлен: {
username: [32m'voskhod'[39m,
type: [32m'coop'[39m,
short_name: [32m'ПК "Восход"'[39m,
full_name: [32m'Потребительский Кооператив "ВОСХОД"'[39m,
represented_by: {
first_name: [32m'Иван'[39m,
last_name: [32m'Иванов'[39m,
middle_name: [32m'Иванович'[39m,
position: [32m'Председатель'[39m,
based_on: [32m'Решение общего собрания №1'[39m
},
country: [32m'Российская Федерация'[39m,
city: [32m'Москва'[39m,
fact_address: [32m'117593 г. Москва, муниципальный округ Ясенево, проезд Соловьиный, дом 1, помещение 1/1'[39m,
full_address: [32m'117593 г. Москва, муниципальный округ Ясенево, проезд Соловьиный, дом 1, помещение 1/1'[39m,
email: [32m'copenomics@yandex.ru'[39m,
phone: [32m'+71234567890'[39m,
details: { inn: [32m'9728130611'[39m, ogrn: [32m'1247700283346'[39m, kpp: [32m'772801001'[39m }
}
Vars сохранены с указанным _id и _created_at
Все документы удалены из коллекции sync
Все документы удалены из коллекции actions
Все документы удалены из коллекции deltas
Добавляем пайщика ant
{
coopname: [32m'voskhod'[39m,
referer: [32m''[39m,
username: [32m'ant'[39m,
type: [32m'individual'[39m,
created_at: [32m'2025-01-15T10:00:00'[39m,
initial: [32m'100.0000 RUB'[39m,
minimum: [32m'200.0000 RUB'[39m,
spread_initial: [33mtrue[39m,
meta: [32m'Основатель кооператива ВОСХОД'[39m,
registration_hash: [32m'1e87d2a7d35f1be95da5a676ae799262e970647d0ba69cd19c0eaff0afd5b488'[39m
}
Добавлен пользователь: ant
Устанавливаем дефолтный публичный ключ для ant
{
coopname: [32m'voskhod'[39m,
changer: [32m'voskhod'[39m,
username: [32m'ant'[39m,
public_key: [32m'EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV'[39m
}
Изменён ключ для пользователя: ant
Инициализируем пользователей в PostgreSQL
Подключение к PostgreSQL установлено для инициализации пользователей
Инициализировано 1 пользователей в PostgreSQL
Инициализируем vault в PostgreSQL
Подключение к PostgreSQL установлено для инициализации vault
Vault инициализирован в PostgreSQL
Создаём совет
{
coopname: [32m'voskhod'[39m,
username: [32m'ant'[39m,
type: [32m'soviet'[39m,
members: [
{
username: [32m'ant'[39m,
is_voting: [33mtrue[39m,
position_title: [32m'Председатель совета'[39m,
position: [32m'chairman'[39m
}
],
name: [32m'Совет'[39m,
description: [32m'Совет кооператива ВОСХОД'[39m
}
Создан совет: {
coopname: [32m'voskhod'[39m,
username: [32m'ant'[39m,
type: [32m'soviet'[39m,
members: [
{
username: [32m'ant'[39m,
is_voting: [33mtrue[39m,
position_title: [32m'Председатель совета'[39m,
position: [32m'chairman'[39m
}
],
name: [32m'Совет'[39m,
description: [32m'Совет кооператива ВОСХОД'[39m
}
Создаём программы и соглашения
params {
coopname: [32m'voskhod'[39m,
username: [32m'voskhod'[39m,
type: [32m'marketplace'[39m,
title: [32m'КООПЛЕЙС'[39m,
announce: [32m''[39m,
description: [32m''[39m,
preview: [32m''[39m,
images: [32m''[39m,
calculation_type: [32m'relative'[39m,
fixed_membership_contribution: [32m'0.0000 RUB'[39m,
membership_percent_fee: [33m10000[39m,
meta: [32m''[39m,
is_can_coop_spend_share_contributions: [33mfalse[39m
}
Программа установлена: {
coopname: [32m'voskhod'[39m,
username: [32m'voskhod'[39m,
type: [32m'marketplace'[39m,
title: [32m'КООПЛЕЙС'[39m,
announce: [32m''[39m,
description: [32m''[39m,
preview: [32m''[39m,
images: [32m''[39m,
calculation_type: [32m'relative'[39m,
fixed_membership_contribution: [32m'0.0000 RUB'[39m,
membership_percent_fee: [33m10000[39m,
meta: [32m''[39m,
is_can_coop_spend_share_contributions: [33mfalse[39m
}
params {
coopname: [32m'voskhod'[39m,
username: [32m'voskhod'[39m,
type: [32m'generator'[39m,
title: [32m'Целевая потребительская программа "Генератор"'[39m,
announce: [32m''[39m,
description: [32m''[39m,
preview: [32m''[39m,
images: [32m''[39m,
calculation_type: [32m'free'[39m,
fixed_membership_contribution: [32m'0.0000 RUB'[39m,
membership_percent_fee: [33m0[39m,
meta: [32m''[39m,
is_can_coop_spend_share_contributions: [33mtrue[39m
}
Программа установлена: {
coopname: [32m'voskhod'[39m,
username: [32m'voskhod'[39m,
type: [32m'generator'[39m,
title: [32m'Целевая потребительская программа "Генератор"'[39m,
announce: [32m''[39m,
description: [32m''[39m,
preview: [32m''[39m,
images: [32m''[39m,
calculation_type: [32m'free'[39m,
fixed_membership_contribution: [32m'0.0000 RUB'[39m,
membership_percent_fee: [33m0[39m,
meta: [32m''[39m,
is_can_coop_spend_share_contributions: [33mtrue[39m
}
params {
coopname: [32m'voskhod'[39m,
username: [32m'voskhod'[39m,
type: [32m'capital'[39m,
title: [32m'Целевая потребительская программа "Благорост"'[39m,
announce: [32m''[39m,
description: [32m''[39m,
preview: [32m''[39m,
images: [32m''[39m,
calculation_type: [32m'free'[39m,
fixed_membership_contribution: [32m'0.0000 RUB'[39m,
membership_percent_fee: [33m0[39m,
meta: [32m''[39m,
is_can_coop_spend_share_contributions: [33mtrue[39m
}
[41m[30m ELIFECYCLE [39m[49m [31mCommand failed with exit code 1.[39m
Запускаем parser...
Запускаем контроллер...
Перезапуск завершен! пересоздаёт blockchain-data с нуля и гоняет
> monocoop@ boot /home/admin/mono-ai-2
> lerna run boot --scope @coopenomics/boot
[2m> [22m@coopenomics/boot:boot
> @coopenomics/boot@2026.6.24 boot /home/admin/mono-ai-2/components/boot
> esno src/index.ts boot
Node is healthy. Continue. {
server_version: [32m'ee002f93'[39m,
chain_id: [32m'db79c8409645082749ca50640d6f4ee511575acf26c4e2c8e4748e6bf6a01ed4'[39m,
head_block_num: [33m123[39m,
last_irreversible_block_num: [33m122[39m,
last_irreversible_block_id: [32m'0000007adc2e2215250e7ffbd9c7961faa675f57c3134be365b336292fda7e72'[39m,
head_block_id: [32m'0000007bf4fa5276948ff1ea2dce877a2032ac28be3a753271efd198ed5f79d5'[39m,
head_block_time: [32m'2026-07-19T11:49:54.000'[39m,
head_block_producer: [32m'eosio'[39m,
virtual_block_cpu_limit: [33m1128638[39m,
virtual_block_net_limit: [33m1184640[39m,
block_cpu_limit: [33m1000000[39m,
block_net_limit: [33m1048576[39m,
server_version_string: [32m'v6.0.0'[39m,
fork_db_head_block_num: [33m123[39m,
fork_db_head_block_id: [32m'0000007bf4fa5276948ff1ea2dce877a2032ac28be3a753271efd198ed5f79d5'[39m,
server_full_version_string: [32m'v6.0.0-ee002f9372237aa07b05879df772a95f9d54867f-dirty'[39m,
total_cpu_weight: [33m999999997[39m,
total_net_weight: [33m999999997[39m,
earliest_available_block_num: [33m1[39m,
last_irreversible_block_time: [32m'2026-07-19T11:49:53.500'[39m
}
error -> init activation: AxiosError: Request failed with status code 500
at settle (file:///home/admin/mono-ai-2/node_modules/[4m.pnpm[24m/axios@1.13.6/node_modules/[4maxios[24m/lib/core/settle.js:20:7)
at IncomingMessage.handleStreamEnd (file:///home/admin/mono-ai-2/node_modules/[4m.pnpm[24m/axios@1.13.6/node_modules/[4maxios[24m/lib/adapters/http.js:844:13)
[90m at IncomingMessage.emit (node:events:531:35)[39m
[90m at endReadableNT (node:internal/streams/readable:1698:12)[39m
[90m at process.processTicksAndRejections (node:internal/process/task_queues:89:21)[39m
at Axios.request (file:///home/admin/mono-ai-2/node_modules/[4m.pnpm[24m/axios@1.13.6/node_modules/[4maxios[24m/lib/core/Axios.js:46:41)
[90m at process.processTicksAndRejections (node:internal/process/task_queues:103:5)[39m
at async startInfra [90m(/home/admin/mono-ai-2/components/boot/[39msrc/init/infra.ts:45:22[90m)[39m
at async boot [90m(/home/admin/mono-ai-2/components/boot/[39msrc/init/booter.ts:6:22[90m)[39m
at async Command.<anonymous> [90m(/home/admin/mono-ai-2/components/boot/[39msrc/index.ts:144:7[90m)[39m {
isAxiosError: [33mtrue[39m,
code: [32m'ERR_BAD_RESPONSE'[39m,
config: {
transitional: {
silentJSONParsing: [33mtrue[39m,
forcedJSONParsing: [33mtrue[39m,
clarifyTimeoutError: [33mfalse[39m,
legacyInterceptorReqResOrdering: [33mtrue[39m
},
adapter: [ [32m'xhr'[39m, [32m'http'[39m, [32m'fetch'[39m ],
transformRequest: [ [36m[Function: transformRequest][39m ],
transformResponse: [ [36m[Function: transformResponse][39m ],
timeout: [33m0[39m,
xsrfCookieName: [32m'XSRF-TOKEN'[39m,
xsrfHeaderName: [32m'X-XSRF-TOKEN'[39m,
maxContentLength: [33m-1[39m,
maxBodyLength: [33m-1[39m,
env: { FormData: [36m[Function][39m, Blob: [36m[class Blob][39m },
validateStatus: [36m[Function: validateStatus][39m,
headers: Object [AxiosHeaders] {
Accept: [32m'application/json, text/plain, */*'[39m,
[32m'Content-Type'[39m: [32m'application/json'[39m,
[32m'User-Agent'[39m: [32m'axios/1.13.6'[39m,
[32m'Content-Length'[39m: [32m'102'[39m,
[32m'Accept-Encoding'[39m: [32m'gzip, compress, deflate, br'[39m
},
method: [32m'post'[39m,
url: [32m'http://127.0.0.1:8898/v1/producer/schedule_protocol_feature_activations'[39m,
data: [32m'{"protocol_features_to_activate":["0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd"]}'[39m,
allowAbsoluteUrls: [33mtrue[39m
},
request: [36m<ref *1>[39m ClientRequest {
_events: [Object: null prototype] {
abort: [36m[Function (anonymous)][39m,
aborted: [36m[Function (anonymous)][39m,
connect: [36m[Function (anonymous)][39m,
error: [36m[Function (anonymous)][39m,
socket: [36m[Function (anonymous)][39m,
timeout: [36m[Function (anonymous)][39m,
finish: [36m[Function: requestOnFinish][39m
},
_eventsCount: [33m7[39m,
_maxListeners: [90mundefined[39m,
outputData: [],
outputSize: [33m0[39m,
writable: [33mtrue[39m,
destroyed: [33mtrue[39m,
_last: [33mfalse[39m,
chunkedEncoding: [33mfalse[39m,
shouldKeepAlive: [33mtrue[39m,
maxRequestsOnConnectionReached: [33mfalse[39m,
_defaultKeepAlive: [33mtrue[39m,
useChunkedEncodingByDefault: [33mtrue[39m,
sendDate: [33mfalse[39m,
_removedConnection: [33mfalse[39m,
_removedContLen: [33mfalse[39m,
_removedTE: [33mfalse[39m,
strictContentLength: [33mfalse[39m,
_contentLength: [33m102[39m,
_hasBody: [33mtrue[39m,
_trailer: [32m''[39m,
finished: [33mtrue[39m,
_headerSent: [33mtrue[39m,
_closed: [33mtrue[39m,
_header: [32m'POST /v1/producer/schedule_protocol_feature_activations HTTP/1.1\r\n'[39m +
[32m'Accept: application/json, text/plain, */*\r\n'[39m +
[32m'Content-Type: application/json\r\n'[39m +
[32m'User-Agent: axios/1.13.6\r\n'[39m +
[32m'Content-Length: 102\r\n'[39m +
[32m'Accept-Encoding: gzip, compress, deflate, br\r\n'[39m +
[32m'Host: 127.0.0.1:8898\r\n'[39m +
[32m'Connection: keep-alive\r\n'[39m +
[32m'\r\n'[39m,
_keepAliveTimeout: [33m0[39m,
_onPendingData: [36m[Function: nop][39m,
agent: Agent {
_events: [36m[Object: null prototype][39m,
_eventsCount: [33m2[39m,
_maxListeners: [90mundefined[39m,
options: [36m[Object: null prototype][39m,
defaultPort: [33m80[39m,
protocol: [32m'http:'[39m,
requests: [Object: null prototype] {},
sockets: [Object: null prototype] {},
freeSockets: [36m[Object: null prototype][39m,
keepAliveMsecs: [33m1000[39m,
keepAlive: [33mtrue[39m,
maxSockets: [33mInfinity[39m,
maxFreeSockets: [33m256[39m,
scheduling: [32m'lifo'[39m,
maxTotalSockets: [33mInfinity[39m,
totalSocketCount: [33m1[39m,
agentKeepAliveTimeoutBuffer: [33m1000[39m,
[[32mSymbol(shapeMode)[39m]: [33mfalse[39m,
[[32mSymbol(kCapture)[39m]: [33mfalse[39m
},
socketPath: [90mundefined[39m,
method: [32m'POST'[39m,
maxHeaderSize: [90mundefined[39m,
insecureHTTPParser: [90mundefined[39m,
joinDuplicateHeaders: [90mundefined[39m,
path: [32m'/v1/producer/schedule_protocol_feature_activations'[39m,
_ended: [33mtrue[39m,
res: IncomingMessage {
_events: [36m[Object][39m,
_readableState: [36m[ReadableState][39m,
_maxListeners: [90mundefined[39m,
socket: [1mnull[22m,
httpVersionMajor: [33m1[39m,
httpVersionMinor: [33m1[39m,
httpVersion: [32m'1.1'[39m,
complete: [33mtrue[39m,
rawHeaders: [36m[Array][39m,
rawTrailers: [],
joinDuplicateHeaders: [90mundefined[39m,
aborted: [33mfalse[39m,
upgrade: [33mfalse[39m,
url: [32m''[39m,
method: [1mnull[22m,
statusCode: [33m500[39m,
statusMessage: [32m'Internal Server Error'[39m,
client: [36m[Socket][39m,
_consuming: [33mfalse[39m,
_dumped: [33mfalse[39m,
req: [36m[Circular *1][39m,
_eventsCount: [33m4[39m,
responseUrl: [32m'http://127.0.0.1:8898/v1/producer/schedule_protocol_feature_activations'[39m,
redirects: [],
[[32mSymbol(shapeMode)[39m]: [33mtrue[39m,
[[32mSymbol(kCapture)[39m]: [33mfalse[39m,
[[32mSymbol(kHeaders)[39m]: [36m[Object][39m,
[[32mSymbol(kHeadersCount)[39m]: [33m8[39m,
[[32mSymbol(kTrailers)[39m]: [1mnull[22m,
[[32mSymbol(kTrailersCount)[39m]: [33m0[39m
},
aborted: [33mfalse[39m,
timeoutCb: [1mnull[22m,
upgradeOrConnect: [33mfalse[39m,
parser: [1mnull[22m,
maxHeadersCount: [1mnull[22m,
reusedSocket: [33mtrue[39m,
host: [32m'127.0.0.1'[39m,
protocol: [32m'http:'[39m,
_redirectable: Writable {
_events: [36m[Object][39m,
_writableState: [36m[WritableState][39m,
_maxListeners: [90mundefined[39m,
_options: [36m[Object][39m,
_ended: [33mtrue[39m,
_ending: [33mtrue[39m,
_redirectCount: [33m0[39m,
_redirects: [],
_requestBodyLength: [33m102[39m,
_requestBodyBuffers: [],
_eventsCount: [33m3[39m,
_onNativeResponse: [36m[Function (anonymous)][39m,
_currentRequest: [36m[Circular *1][39m,
_currentUrl: [32m'http://127.0.0.1:8898/v1/producer/schedule_protocol_feature_activations'[39m,
_timeout: [1mnull[22m,
[[32mSymbol(shapeMode)[39m]: [33mtrue[39m,
[[32mSymbol(kCapture)[39m]: [33mfalse[39m
},
[[32mSymbol(shapeMode)[39m]: [33mfalse[39m,
[[32mSymbol(kCapture)[39m]: [33mfalse[39m,
[[32mSymbol(kBytesWritten)[39m]: [33m0[39m,
[[32mSymbol(kNeedDrain)[39m]: [33mfalse[39m,
[[32mSymbol(corked)[39m]: [33m0[39m,
[[32mSymbol(kChunkedBuffer)[39m]: [],
[[32mSymbol(kChunkedLength)[39m]: [33m0[39m,
[[32mSymbol(kSocket)[39m]: Socket {
connecting: [33mfalse[39m,
_hadError: [33mfalse[39m,
_parent: [1mnull[22m,
_host: [1mnull[22m,
_closeAfterHandlingError: [33mfalse[39m,
_events: [36m[Object][39m,
_readableState: [36m[ReadableState][39m,
_writableState: [36m[WritableState][39m,
allowHalfOpen: [33mfalse[39m,
_maxListeners: [90mundefined[39m,
_eventsCount: [33m6[39m,
_sockname: [1mnull[22m,
_pendingData: [1mnull[22m,
_pendingEncoding: [32m''[39m,
server: [1mnull[22m,
_server: [1mnull[22m,
timeout: [33m5000[39m,
parser: [1mnull[22m,
_httpMessage: [1mnull[22m,
[[32mSymbol(async_id_symbol)[39m]: [33m-1[39m,
[[32mSymbol(kHandle)[39m]: [36m[TCP][39m,
[[32mSymbol(lastWriteQueueSize)[39m]: [33m0[39m,
[[32mSymbol(timeout)[39m]: Timeout {
_idleTimeout: [33m5000[39m,
_idlePrev: [36m[TimersList][39m,
_idleNext: [36m[TimersList][39m,
_idleStart: [33m11165[39m,
_onTimeout: [36m[Function: bound ][39m,
_timerArgs: [90mundefined[39m,
_repeat: [1mnull[22m,
_destroyed: [33mfalse[39m,
[[32mSymbol(refed)[39m]: [33mfalse[39m,
[[32mSymbol(kHasPrimitive)[39m]: [33mfalse[39m,
[[32mSymbol(asyncId)[39m]: [33m3415[39m,
[[32mSymbol(triggerId)[39m]: [33m3413[39m,
[[32mSymbol(kAsyncContextFrame)[39m]: [90mundefined[39m
},
[[32mSymbol(kBuffer)[39m]: [1mnull[22m,
[[32mSymbol(kBufferCb)[39m]: [1mnull[22m,
[[32mSymbol(kBufferGen)[39m]: [1mnull[22m,
[[32mSymbol(shapeMode)[39m]: [33mtrue[39m,
[[32mSymbol(kCapture)[39m]: [33mfalse[39m,
[[32mSymbol(kSetNoDelay)[39m]: [33mtrue[39m,
[[32mSymbol(kSetKeepAlive)[39m]: [33mtrue[39m,
[[32mSymbol(kSetKeepAliveInitialDelay)[39m]: [33m1[39m,
[[32mSymbol(kBytesRead)[39m]: [33m0[39m,
[[32mSymbol(kBytesWritten)[39m]: [33m0[39m
},
[[32mSymbol(kOutHeaders)[39m]: [Object: null prototype] {
accept: [36m[Array][39m,
[32m'content-type'[39m: [36m[Array][39m,
[32m'user-agent'[39m: [36m[Array][39m,
[32m'content-length'[39m: [36m[Array][39m,
[32m'accept-encoding'[39m: [36m[Array][39m,
host: [36m[Array][39m
},
[[32mSymbol(errored)[39m]: [1mnull[22m,
[[32mSymbol(kHighWaterMark)[39m]: [33m65536[39m,
[[32mSymbol(kRejectNonStandardBodyWrites)[39m]: [33mfalse[39m,
[[32mSymbol(kUniqueHeaders)[39m]: [1mnull[22m
},
response: {
status: [33m500[39m,
statusText: [32m'Internal Server Error'[39m,
headers: Object [AxiosHeaders] {
server: [32m'nodeos/v6.0.0'[39m,
[32m'access-control-allow-origin'[39m: [32m'*'[39m,
[32m'content-type'[39m: [32m'application/json'[39m,
[32m'content-length'[39m: [32m'371'[39m
},
config: {
transitional: [36m[Object][39m,
adapter: [36m[Array][39m,
transformRequest: [36m[Array][39m,
transformResponse: [36m[Array][39m,
timeout: [33m0[39m,
xsrfCookieName: [32m'XSRF-TOKEN'[39m,
xsrfHeaderName: [32m'X-XSRF-TOKEN'[39m,
maxContentLength: [33m-1[39m,
maxBodyLength: [33m-1[39m,
env: [36m[Object][39m,
validateStatus: [36m[Function: validateStatus][39m,
headers: [36m[Object [AxiosHeaders]][39m,
method: [32m'post'[39m,
url: [32m'http://127.0.0.1:8898/v1/producer/schedule_protocol_feature_activations'[39m,
data: [32m'{"protocol_features_to_activate":["0ec7e080177b2c02b278d5088611686b49d739925a92d9bfcacd7fc6b74053bd"]}'[39m,
allowAbsoluteUrls: [33mtrue[39m
},
request: [36m<ref *1>[39m ClientRequest {
_events: [36m[Object: null prototype][39m,
_eventsCount: [33m7[39m,
_maxListeners: [90mundefined[39m,
outputData: [],
outputSize: [33m0[39m,
writable: [33mtrue[39m,
destroyed: [33mtrue[39m,
_last: [33mfalse[39m,
chunkedEncoding: [33mfalse[39m,
shouldKeepAlive: [33mtrue[39m,
maxRequestsOnConnectionReached: [33mfalse[39m,
_defaultKeepAlive: [33mtrue[39m,
useChunkedEncodingByDefault: [33mtrue[39m,
sendDate: [33mfalse[39m,
_removedConnection: [33mfalse[39m,
_removedContLen: [33mfalse[39m,
_removedTE: [33mfalse[39m,
strictContentLength: [33mfalse[39m,
_contentLength: [33m102[39m,
_hasBody: [33mtrue[39m,
_trailer: [32m''[39m,
finished: [33mtrue[39m,
_headerSent: [33mtrue[39m,
_closed: [33mtrue[39m,
_header: [32m'POST /v1/producer/schedule_protocol_feature_activations HTTP/1.1\r\n'[39m +
[32m'Accept: application/json, text/plain, */*\r\n'[39m +
[32m'Content-Type: application/json\r\n'[39m +
[32m'User-Agent: axios/1.13.6\r\n'[39m +
[32m'Content-Length: 102\r\n'[39m +
[32m'Accept-Encoding: gzip, compress, deflate, br\r\n'[39m +
[32m'Host: 127.0.0.1:8898\r\n'[39m +
[32m'Connection: keep-alive\r\n'[39m +
[32m'\r\n'[39m,
_keepAliveTimeout: [33m0[39m,
_onPendingData: [36m[Function: nop][39m,
agent: [36m[Agent][39m,
socketPath: [90mundefined[39m,
method: [32m'POST'[39m,
maxHeaderSize: [90mundefined[39m,
insecureHTTPParser: [90mundefined[39m,
joinDuplicateHeaders: [90mundefined[39m,
path: [32m'/v1/producer/schedule_protocol_feature_activations'[39m,
_ended: [33mtrue[39m,
res: [36m[IncomingMessage][39m,
aborted: [33mfalse[39m,
timeoutCb: [1mnull[22m,
upgradeOrConnect: [33mfalse[39m,
parser: [1mnull[22m,
maxHeadersCount: [1mnull[22m,
reusedSocket: [33mtrue[39m,
host: [32m'127.0.0.1'[39m,
protocol: [32m'http:'[39m,
_redirectable: [36m[Writable][39m,
[[32mSymbol(shapeMode)[39m]: [33mfalse[39m,
[[32mSymbol(kCapture)[39m]: [33mfalse[39m,
[[32mSymbol(kBytesWritten)[39m]: [33m0[39m,
[[32mSymbol(kNeedDrain)[39m]: [33mfalse[39m,
[[32mSymbol(corked)[39m]: [33m0[39m,
[[32mSymbol(kChunkedBuffer)[39m]: [],
[[32mSymbol(kChunkedLength)[39m]: [33m0[39m,
[[32mSymbol(kSocket)[39m]: [36m[Socket][39m,
[[32mSymbol(kOutHeaders)[39m]: [36m[Object: null prototype][39m,
[[32mSymbol(errored)[39m]: [1mnull[22m,
[[32mSymbol(kHighWaterMark)[39m]: [33m65536[39m,
[[32mSymbol(kRejectNonStandardBodyWrites)[39m]: [33mfalse[39m,
[[32mSymbol(kUniqueHeaders)[39m]: [1mnull[22m
},
data: { code: [33m500[39m, message: [32m'Internal Service Error'[39m, error: [36m[Object][39m }
},
status: [33m500[39m
}
on set: {
name: [32m'eosio.boot'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.boot'[39m,
target: [32m'eosio'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.boot/eosio.boot.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.boot/eosio.boot.abi
contract setted: eosio
on set: {
name: [32m'eosio.system'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.system'[39m,
target: [32m'eosio'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.system/eosio.system.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.system/eosio.system.abi
contract setted: eosio
on set: {
name: [32m'eosio.token'[39m,
path: [32m'/home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.token'[39m,
target: [32m'eosio.token'[39m
}
wasm_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.token/eosio.token.wasm
abi_path /home/admin/mono-ai-2/components/contracts/build/contracts/system/contracts/eosio.token/eosio.token.abi
[41m[30m ELIFECYCLE [39m[49m [31mCommand failed with exit code 1.[39m
[0m[7m[1m[31m Lerna (powered by Nx) [39m[22m[27m[0m [31mRunning target [1mboot[22m for project @coopenomics/boot failed[39m
[2mFailed tasks:[22m
[2m-[22m @coopenomics/boot:boot
[2mHint: run the command with[22m --verbose [2mfor more details.[22m
[41m[30m ELIFECYCLE [39m[49m [31mCommand failed with exit code 1.[39m
(booter.ts → cooperative.ts createPrograms) — именно так локальная dev-цепочка
получила 'blagorost' вместо 'capital' и воспроизвела баг, которого на проде
никогда не было.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
🚀 @coopenomics/boot
CLI-утилита для инициализации блокчейн-инфраструктуры кооператива. Создаёт системные аккаунты, устанавливает смарт-контракты, настраивает токены и разворачивает кооперативную среду. Включает интеграционные тесты для основных подсистем платформы.
Основные возможности
- Полный цикл развёртывания блокчейна EOSIO — от запуска ноды до создания кооператива
- Установка системных и прикладных смарт-контрактов
- Инициализация токенов и создание тестовых данных
- Управление Docker-контейнерами блокчейн-ноды
- Интеграционные тесты: паевые взносы (capital), кошелёк (wallet), регистрация участников (registrator)
- Поддержка нескольких режимов загрузки: стандартный, чистый и расширенный
Установка
Компонент является частью монорепозитория. Установка зависимостей из корня проекта:
pnpm install
Или только для этого компонента:
pnpm install --filter @coopenomics/boot
Скрипты
| Скрипт | Команда | Описание |
|---|---|---|
boot |
pnpm run boot |
Запуск блокчейна и установка контрактов |
boot:clean |
pnpm run boot:clean |
Чистый запуск с полной переустановкой |
boot:extra |
pnpm run boot:extra |
Расширенная инициализация с дополнительными данными |
deploy |
pnpm run deploy |
Развёртывание контрактов на запущенной ноде |
cli |
pnpm run cli |
Интерактивный командный интерфейс (Commander.js) |
clear |
pnpm run clear |
Очистка данных блокчейна |
start |
pnpm run start |
Перезапуск ноды |
stop |
pnpm run stop |
Остановка ноды |
test |
pnpm run test |
Интеграционные тесты (capital) |
test:all |
pnpm run test:all |
Все интеграционные тесты |
Конфигурация
Скопируйте .env-example в .env и настройте переменные окружения:
- Endpoint блокчейн-ноды (API)
- Строка подключения к MongoDB
- Строка подключения к реляционной БД
- Приватные ключи для развёртывания контрактов
Подробное описание переменных — в файле .env-example.
Запуск bootstrap'а в стороннем проекте (sideboot)
Для проектов, которым нужна только цепь + контракты (без mongo/pg/mono-инфры),
есть готовый docker-образ dicoop/bootcoop:<branch>. Он one-shot job'ом
накатывает на удалённую ноду все системные и кооперативные контракты,
активирует протокол-фичи, создаёт системный токен.
Минимальный docker-compose.yaml для стороннего репозитория:
services:
node:
image: dicoop/blockchain:latest
ports:
- "8888:8888"
- "9876:9876"
volumes:
- ./blockchain-data:/mnt/dev/data
command: >
/bin/bash -c "/usr/local/bin/nodeos -d /mnt/dev/data
--config-dir /mnt/dev/config
--genesis-json /mnt/dev/config/genesis.json"
bootcoop:
image: dicoop/bootcoop:dev # или :testnet / :main / :latest
depends_on: [node]
restart: "no"
environment:
CHAIN_URL: http://node:8888
EOSIO_PUB_KEY: EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV
EOSIO_PRV_KEY: 5KQwrPbwdL6PhXujxW37FSSQZ1JiwsST4cqQzDeyXtP79zkvFD3
RPC_WAIT_TIMEOUT_MS: "180000"
Запуск:
docker compose up -d node
docker compose up bootcoop # one-shot, выходит после успеха
Bootcoop ждёт ${CHAIN_URL}/v1/chain/get_info, затем катит контракты на ноду.
По выходу с кодом 0 — цепь готова к работе.
Версионирование
dicoop/bootcoop:<tag> всегда multi-stage'ится из dicoop/contracts:<tag> с
тем же <tag> (dev/testnet/main). Контракты и bootstrap синхронны по sha
коммита mono-репо — no skew.
Точный пин по коммиту: dicoop/bootcoop:dev-<short-sha> (тегается каждой сборкой).
Дополнительные данные (опционально)
Если в стороннем проекте всё же нужны mono-данные (voskhod, ant, совет) — выставить флаги, и поднять рядом mongo + postgres:
environment:
CHAIN_URL: http://node:8888
MONGO_URI: mongodb://mongo:27017/cooperative-x
POSTGRES_HOST: postgres
POSTGRES_USERNAME: postgres
POSTGRES_PASSWORD: postgres!23!23
POSTGRES_DATABASE: voskhod
INSTALL_INITIAL_DATA: "1" # voskhod + ant + совет
INSTALL_EXTRA_DATA: "1" # + расширенный совет (5 пайщиков)
Без этих флагов запускается чистый chain-only сценарий.
Тестирование
Перед запуском тестов необходима работающая инфраструктура (см. docker-compose.yaml в корне проекта):
pnpm --filter @coopenomics/boot run test
pnpm --filter @coopenomics/boot run test:all
Тесты используют Vitest с таймаутом 240 секунд — это связано с ожиданием подтверждения блокчейн-транзакций.
Архитектура
src/
├── index.ts # Точка входа CLI (Commander.js)
├── init/ # Логика инициализации
│ ├── booter.ts # Загрузчик блокчейна
│ ├── cooperative.ts # Настройка кооператива
│ ├── infra.ts # Инфраструктурная инициализация
│ └── participant.ts # Создание участников
├── blockchain/ # Взаимодействие с EOSIO (eosjs)
├── docker/ # Управление Docker-контейнерами
├── configs/ # Конфигурация ноды и протокол-фичи
├── tests/ # Интеграционные тесты
│ ├── capital.test.ts # Тесты паевых взносов
│ ├── wallet.test.ts # Тесты кошелька
│ └── registrator.test.ts # Тесты регистрации
└── utils/ # Вспомогательные утилиты
scripts/
├── reboot.sh # Полный перезапуск
├── clean_reboot.sh # Чистый перезапуск
└── extra_reboot.sh # Расширенный перезапуск
Ключевые зависимости
- eosjs — взаимодействие с блокчейном EOSIO
- commander — CLI-фреймворк
- dockerode — управление Docker-контейнерами из Node.js
- mongoose — работа с MongoDB
- pg — работа с реляционной БД
- vitest — тестирование