feat(marketplace): drop blocked-механику в ledger2 — резерв под Order через отдельный кошелёк w.mkt.order #41
Reference in New Issue
Block a user
Delete Branch "feat/marketplace2-drop-blocked"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Цель
Переводит marketplace2-сторону ledger2 на ту же модель, что dev уже сделал для wallet/withdraw (
w.wal.wpend): убрать механикуBLOCK/UNBLOCK/BURN_BLOCKEDна одном кошельке, ввести отдельный USER_SHARED-кошелёк-резервw.mkt.orderпод Order, переписать 3 marketplace-операции наTRANSFER/BURN.Подготовка к merge
dev→marketplace2. Архитектурное решение согласовано с тобой 2026-05-28 — это marketplace-аналог dev-коммитаfeat(ledger2): убрать механику blocked из L3-кошельков.Что меняется
C++ ledger2
wallets.hpp: новый USER_SHARED-кошелёкMARKETPLACE_ORDER_LOCK = "w.mkt.order"_n; реестр 15→16; mapping 7→8 (program_id=2 Marketplace).operations.hpp: 3 операции marketplace переписаны:BLOCK_FOR_ORDER(o.mkt.block):BLOCK→TRANSFER w.mkt.member → w.mkt.orderUNBLOCK_ON_CANCEL(o.mkt.unblk):UNBLOCK→TRANSFER w.mkt.order → w.mkt.memberCONSUME_BY_MEMBER(o.mkt.consum):BURN_BLOCKED→BURNнаw.mkt.orderOperation_id'ы сохранены (
o.mkt.block/o.mkt.unblk/o.mkt.consum) — изменилась только реализация вOPERATION_REGISTRY, не имена; внешние op_code в blockchain_actions читаются без сдвига смысла.Enum
WalletOpНЕ модифицируется — значенияBLOCK/UNBLOCK/BURN_BLOCKEDостаются в enum для legacywallet/withdrawflow, который мигрирует следующим mergedev→marketplace2.C++ marketplace .cpp (5 файлов)
Комментарии в
p.mkt.supply/{createorder,cancelorder,declineorder,expireorder,signiss2}.cppобновлены под reserve-flow. Сами вызовыLedger2::apply(coopname, op, ...)идентичны — сигнатура не меняется.Controller / GraphQL DTO
MarketplaceMemberWallet.wallets: теперь 4 кошелька (был 3) — добавленw.mkt.orderс label «Резерв | Стол Заказов»..blockedостаётся в DTO (для wallet/withdraw + legacy), но для marketplace-кошельков всегда0— резерв выражается через.availableотдельного кошелька.Cooptypes / SDK / Zeus
Regen:
cooptypes/ledger2/wallets.generated.ts: wallets=16, mapping=8 (из C++).controller/schema.gql,controller/zeus/index.ts,sdk/zeus/index.ts: только description-only diff, никаких breaking changes в типах GraphQL/Zeus.Invariants
I5(BlockedConsistency→ReserveConsistency): сверяетΣ TRANSFER(member→order) − Σ TRANSFER(order→member) − Σ BURN(order) = balance(w.mkt.order).I6(NoOrphanedBlocks→NoOrphanedReserves): проверка парности по process_hash (consum без block, unblk без block, block+unblk+consum = двойное закрытие) — логика та же, op_code'ы те же.YAML standards
p.mkt.supply.standard.yaml: обновлены описания операций block/unblk/consum под reserve-модель. Бизнес-словарь: «блокировка» → «резерв», «разблокировка» → «снятие резерва», «заблокированная сумма списывается» → «резерв сжигается».Desktop
Не требует правок — единственное место (
OnSiteDecisionDialog.vue) использует только текстовый комментарий сw.mkt.member.available, который семантически корректен после миграции (возврат черезo.mkt.returnвосстанавливает именно.availableчленского, не резерв).Что НЕ требует ledger2::migrate-свёртки
marketplace2 ещё не на проде — на prod-блокчейне нет живых данных с
w.mkt.member.blocked > 0. Свёртка не нужна (подтверждено).Что НЕ входит в scope (отдельные задачи)
cooptypes/ledger2/operations.tsсодержит только 2 legacy marketplace операции (o.mkt.supply/o.mkt.recv) вместо 13 новых. Это известный блокер Эпика 4. 4 теста вmarketplace-ledger2-invariants.spec.ts+ весьmarketplace-process-trace-coverage.spec.tsпадают из-за этого pre-existing baseline.w.wal.wpend); придёт следующим merge dev → marketplace2.BLOCK/UNBLOCK/BURN_BLOCKEDиз enum WalletOp — это работа dev (см. dev-коммит0969505a71c); enum чистится одновременно при merge dev → marketplace2 после этого PR.Проверки
tsc --noEmit(controller): 0 ошибокjest tests/unit/marketplace/marketplace-member-wallet-resolver.test.ts: 4/4 passedjest src/application/ledger2/invariants/marketplace-ledger2-invariants.spec.ts: 32/36 passed (4 fail — pre-existing baseline, см. п.1 выше; те же тесты падали до этого PR)vue-tsc --noEmit --skipLibCheck(desktop): 0 новых ошибок (2 pre-existing q-tab:name="null")Коммиты
Жду ревью.
Семантика in-code не меняется: Ledger2::apply(coopname, op, amount, ...) вызывается с теми же operation_id (o.mkt.block / o.mkt.unblk / o.mkt.consum), изменения только в doc-блоках и inline-комментариях: - createorder.cpp: "BLOCK на w.mkt.member" → "TRANSFER w.mkt.member → w.mkt.order" - cancelorder.cpp: "сумма остаётся на .available" → уточнено, что снятие резерва - declineorder.cpp: "резерв возвращается заказчику" → уточнено через TRANSFER - expireorder.cpp: тот же flow - signiss2.cpp: actual<ordered → снятие части резерва (UNBLOCK_ON_CANCEL), actual>ordered → доп. резерв (BLOCK_FOR_ORDER), CONSUME_BY_MEMBER теперь BURN с w.mkt.order Поведенческих изменений в C++ нет — вся семантика выражена через изменения в OPERATION_REGISTRY (предыдущий коммит). Этот коммит — только документация точки вызовов, чтоб не путать читателя. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>Инвариант I5 переименован: `BlockedConsistency` → `ReserveConsistency`. Считает резерв через пары TRANSFER + BURN в новой модели: Σ TRANSFER(w.mkt.member → w.mkt.order) // o.mkt.block — резерв входит − Σ TRANSFER(w.mkt.order → w.mkt.member) // o.mkt.unblk — резерв снят − Σ BURN(w.mkt.order) // o.mkt.consum — резерв сожжён = Σ balance(w.mkt.order у пайщиков) Раньше I5 сверялся с suma blocked у w.mkt.member-кошельков (поле `.blocked`). Поле `.blocked` для marketplace-кошельков теперь deprecated (всегда 0) — резерв выражается через `.available` отдельного кошелька w.mkt.order. Инвариант I6 переименован: `NoOrphanedBlocks` → `NoOrphanedReserves`. Логика парности по process_hash (consum без block, unblk без block, block+unblk+consum = двойное закрытие) не меняется — op_code'ы o.mkt.block/unblk/consum сохранены. Фикстуры в spec.ts переписаны под новую модель: walletFrom/walletTo для block теперь w.mkt.member → w.mkt.order, для unblk наоборот, для consum — walletFrom=w.mkt.order (BURN). ВНИМАНИЕ — pre-existing baseline: `marketplace-process-trace-coverage.spec.ts` и 4 теста в `*-invariants.spec.ts`, которые опираются на `MARKETPLACE_OPERATION_CODES` (фильтр через `Ledger2.LEDGER2_OPERATION_REGISTRY.contract === 'marketplace'`), падают с pre-existing проблемой: `cooptypes/ledger2/operations.ts` содержит только 2 legacy marketplace-операции (`o.mkt.supply`/`o.mkt.recv`) вместо 13 новых. Это известный блокер Эпика 11 Story 11.1 (синхронизация TS-стороны cooptypes с C++ operations.hpp) — выходит за scope этого PR. Проверено: 32/36 тестов в marketplace-ledger2-invariants.spec.ts passed (те же 4 теста были сломаны на pre-state baseline). Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>@@ -92,2 +92,2 @@inline constexpr eosio::name BLOCK_FOR_ORDER = "o.mkt.block"_n; ///< Блокировка членского взноса заказчика под конкретный Order (BLOCK на MARKETPLACE_MEMBER, без Dr/Cr).inline constexpr eosio::name UNBLOCK_ON_CANCEL = "o.mkt.unblk"_n; ///< Разблокировка членского взноса при отмене Order'а (UNBLOCK на MARKETPLACE_MEMBER, без Dr/Cr). Сумма остаётся на .available и может быть потрачена на следующий заказ в программе.inline constexpr eosio::name BLOCK_FOR_ORDER = "o.mkt.block"_n; ///< Резервирование членского взноса заказчика под конкретный Order (TRANSFER MARKETPLACE_MEMBER → MARKETPLACE_ORDER_LOCK, без Dr/Cr — оба кошелька на 86). Имя o.mkt.block сохранено для совместимости op_code в blockchain_actions; семантика — резерв через отдельный кошелёк, не BLOCK.inline constexpr eosio::name UNBLOCK_ON_CANCEL = "o.mkt.unblk"_n; ///< Снятие резерва при отмене Order'а (TRANSFER MARKETPLACE_ORDER_LOCK → MARKETPLACE_MEMBER, без Dr/Cr). Сумма возвращается на .available членского и может быть потрачена на следующий заказ в программе. Имя o.mkt.unblk сохранено для совместимости op_code.Надо чуть-чуть упростить всю эту механику. Во-первых, по самому процессу, пользуясь случаем, да, и в рамках этого пиара надо будет стандарт поправить. То есть первое, мы не используем 91-й счет для транзита, мы используем сразу 86-й. То есть без 91-го проводка проводится, то есть упрощается процесс. Это что касается поставщика, когда носит имущество. А, нет, когда заказчик получает имущество. Ну, короче, без. 91-го там идет. Где он там есть, он без него. И без транзита, без этого, который там. Короче, попроще. Второй момент. Значит, здесь у нас, когда идет блокировказ, она идет сразу же на кошелек Marketplace. Вот этот вот блог, который ты написал. Сразу же туда. То есть, по сути, не так, как в стандарте написано. В стандарте у нас там вообще три операции. Сперва на кошелек главных членских, потом главного Marketplace, а потом уже дальше блокируем. Сейчас мы не блокируем, и мы не переводим сквозь главный членский, мы сразу же отправляем на блок. Затем, в случае отмены блока, мы возвращаем обратно на главный членский. Вот в этом случае мы идем на w.wal.member. То есть, обратно. Только на членский. Вот таким образом мы все это упрощаем. Поэтому от BLOCK ON CANCEL, ну, здесь не надо вообще этого. Она возвращается, сумма возвращается на AVAILABLE кошелька w.wal.member, то есть, главный членский. Вот туда. А когда поступает, она идет не сквозь него, а сразу же на market block. Надо внести все эти изменения и в стандарты, и в код.
@@ -25,6 +25,7 @@ export const LEDGER2_WALLET_REGISTRY: readonly WalletMeta[] = [{ name: "w.cap.blago", human_name: "ЦПП «Благорост» — единый кошелёк программы у пайщика", kind: "USER_SHARED" },{ name: "w.cap.preimp", human_name: "Первичный учёт РИД-взносов до перехода на электронный учёт", kind: "USER_SHARED" },{ name: "w.mkt.member", human_name: "ЦПП «Стол Заказов» — программный членский у пайщика", kind: "USER_SHARED" },{ name: "w.mkt.order", human_name: "ЦПП «Стол Заказов» — резерв под заказ у пайщика", kind: "USER_SHARED" },Не пойму, у тебя здесь w.mkt.order написано!!! А НА КОНТРАКТАХ w.mkt.block. КАК ТАК?"?!?!??! Этот файл АВТО_ГЕНЕРИРУЕМЫЙ! ВОТ И ГЕНЕРИРУЙ ЕГО! Меняй на w.mkt.order в файлах везде чтоб было как ясказал сразу. Не w.mkt.block а w.mkt.order - везде.
@@ -17,4 +17,4 @@# кошелёк пайщика. Сюда стекаются возвраты из всех# программ (Стол заказов / Благорост / и т.п.); пайщик# тратит как «баллы» — может направить на следующий заказ# в любой программе либо вывести обратно на паевой черезНЕ МОЖЕТ ОН ВЫВЕСТИ ОБРАТНо на ПАеВОЙ!!!!
@@ -7,1 +5,3 @@* - Ledger2::apply(o.mkt.wroff2, item.amount, …, hash=proposal.hash) — Дт 86 / Кт 91.* Per-item операция:* - Ledger2::apply(o.mkt.wroff, item.amount, …, hash=proposal.hash) — Дт 86 / Кт 10* (списание со склада через целевое финансирование, одной операцией без транзита 91).да убери ты отсюда и от всех мест где ты вот пишешь без транзита 91 просто забудь это похуй всем какой-то он транзит 91 был раньше если его сейчас нет вот мне тоже он мне нужен и никого не путай убери просто без транзита 91 и прекрасно будет