From 582ab75b03baf2c582c197fc4c503069a3b0e3b2 Mon Sep 17 00:00:00 2001 From: Apple Date: Sat, 15 Nov 2025 08:56:14 -0800 Subject: [PATCH] feat: add MicroDAO balance checks and DAARION.city integration - Update Wallet Service: balance checks (1 DAARION for create, 0.01 for usage) - Update DAOFactory Service: use new balance checks - Add DB migration: teams type field and city_links table - Add DAARION.city seed data - Create teams API routes with balance validation - Add DAARION.city remote repository - Add sync scripts and documentation --- DAARION_CITY_REPO.md | 185 ++++++++++++++++++ IMPLEMENTATION_PLAN.md | 179 +++++++++++++++++ IMPLEMENTATION_QUESTIONS.md | 160 +++++++++++++++ IMPLEMENTATION_SUMMARY.md | 120 ++++++++++++ scripts/sync-to-daarion-city.sh | 77 ++++++++ src/api/http/teams.routes.ts | 156 +++++++++++++++ src/app.ts | 2 + .../dao-factory/dao-factory.service.ts | 7 +- src/services/wallet/wallet.interface.ts | 10 +- src/services/wallet/wallet.service.ts | 64 ++++-- src/types/api.ts | 6 + .../000010_teams_type_and_city_links.sql | 50 +++++ supabase/migrations/README.md | 3 +- 13 files changed, 994 insertions(+), 25 deletions(-) create mode 100644 DAARION_CITY_REPO.md create mode 100644 IMPLEMENTATION_PLAN.md create mode 100644 IMPLEMENTATION_QUESTIONS.md create mode 100644 IMPLEMENTATION_SUMMARY.md create mode 100755 scripts/sync-to-daarion-city.sh create mode 100644 src/api/http/teams.routes.ts create mode 100644 supabase/migrations/000010_teams_type_and_city_links.sql diff --git a/DAARION_CITY_REPO.md b/DAARION_CITY_REPO.md new file mode 100644 index 00000000..cf66d39c --- /dev/null +++ b/DAARION_CITY_REPO.md @@ -0,0 +1,185 @@ +# Робота з репозиторієм DAARION.city + +## 🔗 Підключені репозиторії + +### 1. MicroDAO (поточний проєкт) +- **Remote:** `origin` +- **URL:** `git@github.com:IvanTytar/microdao-daarion.git` +- **Призначення:** Код та документація MicroDAO + +### 2. DAARION.city +- **Remote:** `daarion-city` +- **URL:** `git@github.com:DAARION-DAO/daarion-ai-city.git` +- **Призначення:** Офіційний сайт та код DAARION.city + +--- + +## 📋 Команди для роботи з DAARION.city + +### Перевірка статусу +```bash +# Перевірити доступні гілки +git ls-remote --heads daarion-city + +# Перевірити поточний remote +git remote -v +``` + +### Клонування/Оновлення +```bash +# Клонувати репозиторій DAARION.city (якщо потрібно окремо) +git clone git@github.com:DAARION-DAO/daarion-ai-city.git + +# Оновити інформацію про remote +git fetch daarion-city +``` + +### Створення гілки для DAARION.city +```bash +# Створити локальну гілку, що відстежує remote +git checkout -b daarion-city-main --track daarion-city/main + +# Або створити нову гілку для змін +git checkout -b feature/console-integration daarion-city/main +``` + +### Push змін до DAARION.city +```bash +# Push поточної гілки до DAARION.city +git push daarion-city + +# Push з встановленням upstream +git push -u daarion-city +``` + +### Створення Pull Request +```bash +# 1. Створити гілку зі змінами +git checkout -b feature/microdao-integration daarion-city/main + +# 2. Внести зміни +# ... редагування файлів ... + +# 3. Коміт та push +git add . +git commit -m "feat: integrate MicroDAO console" +git push -u daarion-city feature/microdao-integration + +# 4. Створити PR через GitHub UI або CLI +gh pr create --repo DAARION-DAO/daarion-ai-city --base main --head feature/microdao-integration +``` + +--- + +## 🔄 Синхронізація між репозиторіями + +### Варіант 1: Копіювання файлів +Якщо потрібно скопіювати файли з MicroDAO до DAARION.city: + +```bash +# 1. Клонувати DAARION.city (якщо ще не клоновано) +cd /tmp +git clone git@github.com:DAARION-DAO/daarion-ai-city.git +cd daarion-ai-city + +# 2. Скопіювати потрібні файли +cp -r /path/to/MicroDAO/src/components/console ./src/components/ +cp /path/to/MicroDAO/src/pages/ConsolePage.tsx ./src/pages/ + +# 3. Коміт та push +git add . +git commit -m "feat: add MicroDAO console components" +git push origin main +``` + +### Варіант 2: Git Subtree (для спільних компонентів) +Якщо потрібно тримати спільні компоненти синхронізованими: + +```bash +# Додати subtree з MicroDAO до DAARION.city +cd /path/to/daarion-ai-city +git subtree add --prefix=src/shared/microdao git@github.com:IvanTytar/microdao-daarion.git main --squash + +# Оновити subtree +git subtree pull --prefix=src/shared/microdao git@github.com:IvanTytar/microdao-daarion.git main --squash +``` + +--- + +## 🎯 Типові сценарії + +### Сценарій 1: Додати Console компонент до DAARION.city +```bash +# 1. У проєкті MicroDAO 3 +cd "/Users/apple/Desktop/MicroDAO/MicroDAO 3" + +# 2. Створити гілку для змін +git checkout -b feature/console-component + +# 3. Створити компонент +# ... створення компонента ... + +# 4. Коміт у MicroDAO +git add . +git commit -m "feat: create Console component" +git push origin feature/console-component + +# 5. Клонувати DAARION.city (якщо потрібно) +cd /tmp +git clone git@github.com:DAARION-DAO/daarion-ai-city.git +cd daarion-ai-city + +# 6. Скопіювати компонент +cp -r "/Users/apple/Desktop/MicroDAO/MicroDAO 3/src/components/console" ./src/components/ + +# 7. Коміт та push до DAARION.city +git add . +git commit -m "feat: integrate MicroDAO Console component" +git push origin main +``` + +### Сценарій 2: Оновити документацію в обох репозиторіях +```bash +# 1. Оновити документацію в MicroDAO +cd "/Users/apple/Desktop/MicroDAO/MicroDAO 3" +# ... редагування ... + +git add docs/ +git commit -m "docs: update integration guide" +git push origin main + +# 2. Скопіювати оновлену документацію до DAARION.city +cd /tmp/daarion-ai-city +cp -r "/Users/apple/Desktop/MicroDAO/MicroDAO 3/docs/daarion" ./docs/ + +git add docs/ +git commit -m "docs: sync DAARION documentation from MicroDAO" +git push origin main +``` + +--- + +## 🔐 Права доступу + +Перевірка прав доступу: +```bash +# Перевірити доступ до DAARION.city +git ls-remote --heads daarion-city + +# Якщо помилка "Permission denied", потрібно: +# 1. Перевірити SSH ключ на GitHub +# 2. Перевірити права доступу до репозиторію DAARION-DAO/daarion-ai-city +``` + +--- + +## 📝 Примітки + +- **Не push'ити безпосередньо в main** — краще створювати гілки та PR +- **Синхронізація файлів** — можна використовувати скрипти або вручну копіювати +- **Версіонування** — зберігати версії компонентів для сумісності + +--- + +**Останнє оновлення:** 2024-11-14 + diff --git a/IMPLEMENTATION_PLAN.md b/IMPLEMENTATION_PLAN.md new file mode 100644 index 00000000..bf468012 --- /dev/null +++ b/IMPLEMENTATION_PLAN.md @@ -0,0 +1,179 @@ +# План реалізації: Console + DAARION.city + Створення MicroDAO + +## 📋 Поточний стан проєкту + +### ✅ Що вже є: +- Базова структура React + TypeScript +- Wallet Service (перевірка балансів DAAR/DAARION) +- DAOFactory Service (створення DAO) +- PDP Service (перевірка політик) +- БД міграції (teams, channels, messages) +- Onboarding компоненти + +### ❌ Що потрібно додати: +- Console UI (адмін-панель) +- Перевірка стейкінгу (замість балансу) +- Таблиця `staking` в БД +- Поле `type` в таблиці `teams` (city, platform, community) +- DAARION.city як перше MicroDAO (seed дані) +- Створення MicroDAO з перевіркою стейкінгу +- Admin роль з перевіркою 0.01 DAARION + +--- + +## ❓ Питання для уточнення + +### 1. Console / Адмін-панель + +**Q1.1:** Що таке "console консоль"? +- [ ] Окрема сторінка `/console` на сайті DAARION.city? +- [ ] Вбудований віджет на існуючій сторінці? +- [ ] Окремий піддомен `console.daarion.city`? + +**Q1.2:** Які функції мають бути в console? +- [ ] Створення нового MicroDAO +- [ ] Перегляд списку існуючих MicroDAO +- [ ] Управління DAARION.city як SuperDAO +- [ ] Перегляд міських платформ (GREENFOOD, EnergyUnion) +- [ ] Wallet інтерфейс (баланси, стейкінг) +- [ ] Інші функції? + +**Q1.3:** Технічний стек для console? +- [ ] React компонент на існуючому сайті DAARION.city? +- [ ] Який фреймворк? (Next.js, Vite, інше) +- [ ] Чи є вже існуючий код console? + +--- + +### 2. Порог для створення MicroDAO + +**Q2.1:** Уточнення порогу +- В документації: "1 DAAR **або** 0.01 DAARION" +- Ти кажеш: "мінімум **1 DAARION у стейкінгу**" + +**Питання:** +- [ ] Правильно: **1 DAARION у стейкінгу** (не просто баланс)? +- [ ] Чи можна альтернатива: 1 DAAR у стейкінгу? + +**Q2.2:** Перевірка стейкінгу +- Де зберігається інформація про стейкінг? (таблиця `staking`?) +- Як перевіряється стейкінг перед створенням MicroDAO? +- Чи потрібна перевірка через Wallet Service або on-chain? + +--- + +### 3. Роль Admin та 0.01 DAARION + +**Q3.1:** Роль Admin +- [ ] Це роль в конкретному MicroDAO? +- [ ] Чи це глобальна роль в DAARION.city? + +**Q3.2:** 0.01 DAARION для Admin +- [ ] Це мінімум для отримання ролі Admin? +- [ ] Це мінімум для запрошення інших користувачів? +- [ ] Це мінімум для постійного використання (maintenance fee)? + +**Q3.3:** Перевірка перед запрошенням +- [ ] Перевіряється баланс або стейкінг? +- [ ] Чи потрібна перевірка при кожному запрошенні? + +--- + +### 4. Міські платформи + +**Q4.1:** Які саме міські платформи вже існують? +- [ ] GREENFOOD +- [ ] EnergyUnion +- [ ] WaterUnion +- [ ] Інші? + +**Q4.2:** Як вони об'єднані? +- [ ] Через `city_links` таблицю? +- [ ] Чи вони вже створені як MicroDAO типу "platform"? +- [ ] Чи потрібно їх створити зараз? + +**Q4.3:** Відображення в console +- [ ] Як окремий розділ "Міські платформи"? +- [ ] Чи як частина дерева MicroDAO? + +--- + +### 5. UI для створення MicroDAO + +**Q5.1:** Форма чи діалог? +- [ ] Форма з полями (назва, опис, тип) +- [ ] Діалог з агентом (як в onboarding) +- [ ] Інше? + +**Q5.2:** Які поля обов'язкові? +- [ ] Назва +- [ ] Опис +- [ ] Тип (community, guild, lab, personal) +- [ ] Інші? + +--- + +## 🎯 Пропозиція плану реалізації + +### Фаза 1: Backend Foundation +1. ✅ Додати таблицю `staking` в БД +2. ✅ Додати поле `type` в таблицю `teams` (city, platform, community, guild, lab, personal) +3. ✅ Додати таблицю `city_links` (parent_team_id, child_team_id, relation_type) +4. ✅ Оновити Wallet Service для перевірки стейкінгу +5. ✅ Оновити DAOFactory Service для перевірки стейкінгу (1 DAARION) +6. ✅ Додати seed дані для DAARION.city (type='city', slug='daarion') + +### Фаза 2: Console UI +1. ✅ Створити сторінку `/console` +2. ✅ Компонент "Створити MicroDAO" (з перевіркою стейкінгу) +3. ✅ Компонент "Список MicroDAO" (включаючи DAARION.city) +4. ✅ Компонент "Міські платформи" (якщо є) +5. ✅ Компонент "Wallet" (баланси, стейкінг) + +### Фаза 3: Створення MicroDAO +1. ✅ API endpoint `POST /api/v1/teams` (з перевіркою стейкінгу) +2. ✅ UI форма/діалог для створення +3. ✅ Автоматичне створення DAO через DAOFactory +4. ✅ Автоматичне призначення ролі Owner + +### Фаза 4: Admin роль та запрошення +1. ✅ Перевірка 0.01 DAARION для ролі Admin +2. ✅ API endpoint для запрошення користувачів +3. ✅ Перевірка стейкінгу перед запрошенням + +--- + +## 🚀 Швидкий старт (після відповідей) + +Після отримання відповідей на питання, я можу: + +1. **Створити міграції БД** для: + - Таблиця `staking` + - Поле `type` в `teams` + - Таблиця `city_links` + - Seed дані для DAARION.city + +2. **Оновити сервіси**: + - Wallet Service (перевірка стейкінгу) + - DAOFactory Service (перевірка 1 DAARION staked) + - PDP Service (політики для стейкінгу) + +3. **Створити Console UI**: + - Сторінка `/console` + - Компоненти для створення MicroDAO + - Компоненти для перегляду списку + +4. **Інтегрувати все разом** + +--- + +## 📝 Наступні кроки + +**Зараз:** Відповісти на питання вище + +**Після відповідей:** Я створю детальний план реалізації та почну розробку + +--- + +**Останнє оновлення:** 2024-11-14 + diff --git a/IMPLEMENTATION_QUESTIONS.md b/IMPLEMENTATION_QUESTIONS.md new file mode 100644 index 00000000..973b1ae9 --- /dev/null +++ b/IMPLEMENTATION_QUESTIONS.md @@ -0,0 +1,160 @@ +# Питання для початку реалізації + +## 1. Console / Адмін-панель + +### 1.1 Що таке "console консоль"? +- Це окрема сторінка на `daarion.city/console`? +- Чи це вбудований віджет на існуючій сторінці? +- Чи це окремий піддомен `console.daarion.city`? + +### 1.2 Які функції мають бути в console? +- Створення нового MicroDAO +- Перегляд списку існуючих MicroDAO +- Управління DAARION.city як SuperDAO +- Перегляд міських платформ (GREENFOOD, EnergyUnion, тощо) +- Wallet інтерфейс (баланси, стейкінг) +- Інші функції? + +### 1.3 Технічний стек для console +- Це React компонент на існуючому сайті DAARION.city? +- Який фреймворк використовується (Next.js, Vite, інше)? +- Чи є вже існуючий код console, який потрібно розширити? + +--- + +## 2. DAARION.city як перше MicroDAO + SuperDAO + +### 2.1 Міські платформи +Які саме міські платформи вже існують та об'єднані з DAARION.city? +- GREENFOOD +- EnergyUnion +- WaterUnion +- Інші? + +### 2.2 Як вони об'єднані? +- Через `city_links` таблицю з `parent_team_id = daarion-city`? +- Чи вони вже створені як MicroDAO типу "platform"? +- Чи потрібно їх створити зараз? + +### 2.3 Відображення в console +- Як мають відображатися міські платформи в console? +- Як окремий розділ "Міські платформи"? +- Чи як частина дерева MicroDAO? + +--- + +## 3. Створення MicroDAO користувачами + +### 3.1 Порог для створення +**Уточнення:** В документації написано "1 DAAR або 0.01 DAARION", але ти кажеш "мінімум 1 DAARION у стейкінгу". + +**Питання:** +- Правильно: **1 DAARION у стейкінгу** (не просто баланс)? +- Чи можна альтернатива: 1 DAAR у стейкінгу? + +### 3.2 Перевірка стейкінгу +- Де зберігається інформація про стейкінг? (БД таблиця `staking`?) +- Як перевіряється стейкінг перед створенням MicroDAO? +- Чи потрібна перевірка через Wallet Service або on-chain? + +### 3.3 UI для створення MicroDAO +- Це форма з полями (назва, опис, тип)? +- Чи діалог з агентом (як в `08_agent_first_onboarding.md`)? +- Які поля обов'язкові? + +### 3.4 Після створення +- Автоматично створюється DAO через DAOFactory? +- Автоматично створюються токени GOV/UTIL/REP? +- Яка роль у створеного MicroDAO отримує користувач? (Owner?) + +--- + +## 4. Роль Admin та 0.01 DAARION + +### 4.1 Роль Admin +- Це роль в конкретному MicroDAO? +- Чи це глобальна роль в DAARION.city? + +### 4.2 0.01 DAARION для Admin +- Це мінімум для отримання ролі Admin? +- Чи це мінімум для запрошення інших користувачів? +- Чи це мінімум для постійного використання (maintenance fee)? + +### 4.3 Перевірка перед запрошенням +- Перевіряється баланс або стейкінг? +- Чи потрібна перевірка при кожному запрошенні? + +--- + +## 5. Wallet та Staking + +### 5.1 Інтеграція з Wallet +- Wallet Service вже реалізований? +- Як перевіряються баланси DAAR/DAARION? +- Чи потрібна інтеграція з on-chain контрактами? + +### 5.2 Staking +- Де зберігається інформація про стейкінг? (таблиця `staking`?) +- Як перевіряється стейкінг для доступу? +- Чи потрібна інтеграція зі смарт-контрактами? + +--- + +## 6. Технічні деталі + +### 6.1 API Endpoints +- Чи є вже реалізовані API endpoints для: + - Створення MicroDAO + - Перевірки стейкінгу + - Wallet операцій + - Інші? + +### 6.2 База даних +- Чи є вже міграції для: + - `teams` (MicroDAO) + - `staking` + - `wallets` + - `city_links` + - Інші? + +### 6.3 PDP (Policy Decision Point) +- Чи потрібно інтегрувати перевірки стейкінгу в PDP? +- Які саме політики потрібні: + - `policy.microdao.create` (1 DAARION staked) + - `policy.admin.invite` (0.01 DAARION) + - Інші? + +--- + +## 7. Пріоритети реалізації + +Що реалізувати першим? + +**Варіант A:** +1. Console UI (базова структура) +2. DAARION.city як перше MicroDAO (БД setup) +3. Створення MicroDAO користувачами (з перевіркою стейкінгу) +4. Admin роль та запрошення + +**Варіант B:** +1. Backend: DAARION.city setup + API endpoints +2. Frontend: Console UI +3. Інтеграція Wallet/Staking перевірок +4. Створення MicroDAO flow + +**Варіант C:** +Інший порядок? + +--- + +## 8. Додаткові питання + +- Чи є вже існуючий код console, який потрібно розширити? +- Чи потрібна інтеграція з існуючим сайтом DAARION.city? +- Які саме міські платформи вже працюють і потрібно їх відобразити? +- Чи є вже реалізований Wallet Service або потрібно створювати з нуля? + +--- + +**Очікування:** Відповіді на ці питання допоможуть створити точний план реалізації та почати розробку. + diff --git a/IMPLEMENTATION_SUMMARY.md b/IMPLEMENTATION_SUMMARY.md new file mode 100644 index 00000000..b14dd725 --- /dev/null +++ b/IMPLEMENTATION_SUMMARY.md @@ -0,0 +1,120 @@ +# Підсумок реалізації: Backend для MicroDAO + +## ✅ Що зроблено + +### 1. Wallet Service оновлено +- ✅ `hasEnoughForMicroDaoCreate()` - перевірка 1 DAARION на балансі (для створення MicroDAO) +- ✅ `hasEnoughForAdminRole()` - перевірка 1 DAARION на балансі (для ролі Admin) +- ✅ `hasEnoughForMicroDaoUsage()` - перевірка 0.01 DAARION на балансі (для використання сервісу) +- ✅ `getDaarionBalance()` - отримання балансу DAARION +- ✅ Legacy методи залишено для сумісності + +### 2. DAOFactory Service оновлено +- ✅ Використовує `hasEnoughForMicroDaoCreate()` замість старого методу +- ✅ Перевірка 1 DAARION на балансі перед створенням MicroDAO +- ✅ Помилка: `INSUFFICIENT_BALANCE: Need 1 DAARION on balance to create MicroDAO` + +### 3. Міграція БД створена +- ✅ `000010_teams_type_and_city_links.sql` +- ✅ Додано поле `type` в таблицю `teams` (city, platform, community, guild, lab, personal) +- ✅ Додано поле `parent_team_id` для ієрархічної структури +- ✅ Створено таблицю `city_links` для зв'язків між DAARION.city та платформами +- ✅ Seed дані для DAARION.city (id='daarion-city', type='city', slug='daarion') + +### 4. API Endpoints створено +- ✅ `POST /api/v1/teams` - створення MicroDAO (з перевіркою 1 DAARION) +- ✅ `GET /api/v1/teams` - список teams/MicroDAO +- ✅ `GET /api/v1/teams/:teamId` - отримання team/MicroDAO +- ✅ `POST /api/v1/teams/:teamId/members` - запрошення користувача (з перевірками балансу) + +### 5. Типи оновлено +- ✅ `Team` interface - додано поля `type`, `parent_team_id`, `slug` +- ✅ `CreateTeamRequest` interface - додано поля `type`, `slug`, `mode` + +### 6. Логіка запрошення +- ✅ Admin може запросити користувача тільки якщо має 1 DAARION на балансі +- ✅ Для ролі Admin: запрошений користувач має мати 1 DAARION на балансі +- ✅ Для ролі Member: запрошений користувач має мати 0.01 DAARION на балансі + +--- + +## 📋 Правила доступу (підсумок) + +### Створення MicroDAO +- **Потрібно:** 1 DAARION на балансі (не стейкінг) +- **Результат:** Роль Admin у створеному MicroDAO + +### Додавання Admin +- **Потрібно:** + - Поточний користувач: 1 DAARION на балансі + - Запрошений користувач: 1 DAARION на балансі +- **Результат:** Роль Admin у MicroDAO + +### Запрошення Member +- **Потрібно:** + - Поточний користувач: 1 DAARION на балансі (Admin) + - Запрошений користувач: 0.01 DAARION на балансі +- **Результат:** Роль Member у MicroDAO + +### Використання сервісу MicroDAO +- **Потрібно:** 0.01 DAARION на балансі +- **Результат:** Доступ до функцій MicroDAO + +--- + +## 🔄 Наступні кроки + +### Frontend (Console UI) +1. [ ] Створити сторінку `/console` +2. [ ] Компонент "Створити MicroDAO" (з перевіркою балансу) +3. [ ] Компонент "Список MicroDAO" (включаючи DAARION.city) +4. [ ] Компонент "Wallet" (баланси, перевірка доступу) +5. [ ] Компонент "Запросити користувача" (з перевірками балансу) + +### Backend (доповнення) +1. [ ] Інтеграція з реальною БД (замість заглушок) +2. [ ] Створення team record при створенні MicroDAO +3. [ ] Створення team_member record при запрошенні +4. [ ] Отримання user_id з email при запрошенні + +--- + +## 📝 Файли, які були змінені/створені + +### Створені: +- `supabase/migrations/000010_teams_type_and_city_links.sql` +- `src/api/http/teams.routes.ts` +- `IMPLEMENTATION_SUMMARY.md` + +### Оновлені: +- `src/services/wallet/wallet.service.ts` +- `src/services/wallet/wallet.interface.ts` +- `src/services/dao-factory/dao-factory.service.ts` +- `src/types/api.ts` +- `src/app.ts` +- `supabase/migrations/README.md` + +--- + +## 🧪 Тестування + +Для тестування потрібно: + +1. **Застосувати міграцію:** + ```bash + psql -d microdao -f supabase/migrations/000010_teams_type_and_city_links.sql + ``` + +2. **Перевірити API endpoints:** + - `POST /api/v1/teams` - створення MicroDAO + - `POST /api/v1/teams/:teamId/members` - запрошення користувача + +3. **Перевірити перевірки балансу:** + - Створення без достатнього балансу → помилка 403 + - Запрошення Admin без достатнього балансу → помилка 403 + - Запрошення Member без достатнього балансу → помилка 403 + +--- + +**Останнє оновлення:** 2024-11-14 + diff --git a/scripts/sync-to-daarion-city.sh b/scripts/sync-to-daarion-city.sh new file mode 100755 index 00000000..e91e734a --- /dev/null +++ b/scripts/sync-to-daarion-city.sh @@ -0,0 +1,77 @@ +#!/bin/bash + +# Скрипт для синхронізації файлів з MicroDAO до DAARION.city репозиторію +# Використання: ./scripts/sync-to-daarion-city.sh [component-name] + +set -e + +MICRODAO_DIR="/Users/apple/Desktop/MicroDAO/MicroDAO 3" +DAARION_CITY_DIR="/tmp/daarion-ai-city" +COMPONENT=${1:-"console"} + +echo "🔄 Синхронізація компонента '$COMPONENT' до DAARION.city..." + +# Перевірка наявності MicroDAO проєкту +if [ ! -d "$MICRODAO_DIR" ]; then + echo "❌ Помилка: MicroDAO проєкт не знайдено в $MICRODAO_DIR" + exit 1 +fi + +# Клонування/оновлення DAARION.city репозиторію +if [ ! -d "$DAARION_CITY_DIR" ]; then + echo "📦 Клонування DAARION.city репозиторію..." + git clone git@github.com:DAARION-DAO/daarion-ai-city.git "$DAARION_CITY_DIR" +else + echo "📥 Оновлення DAARION.city репозиторію..." + cd "$DAARION_CITY_DIR" + git fetch origin + git checkout main + git pull origin main +fi + +# Створення гілки для змін +BRANCH_NAME="sync/microdao-${COMPONENT}-$(date +%Y%m%d-%H%M%S)" +cd "$DAARION_CITY_DIR" +git checkout -b "$BRANCH_NAME" + +# Копіювання файлів залежно від компонента +case $COMPONENT in + console) + echo "📋 Копіювання Console компонентів..." + mkdir -p "$DAARION_CITY_DIR/src/components/console" + cp -r "$MICRODAO_DIR/src/components/console"/* "$DAARION_CITY_DIR/src/components/console/" 2>/dev/null || true + + if [ -f "$MICRODAO_DIR/src/pages/ConsolePage.tsx" ]; then + cp "$MICRODAO_DIR/src/pages/ConsolePage.tsx" "$DAARION_CITY_DIR/src/pages/" + fi + ;; + api) + echo "📋 Копіювання API клієнтів..." + mkdir -p "$DAARION_CITY_DIR/src/api" + cp -r "$MICRODAO_DIR/src/api"/* "$DAARION_CITY_DIR/src/api/" 2>/dev/null || true + ;; + docs) + echo "📋 Копіювання документації..." + mkdir -p "$DAARION_CITY_DIR/docs/daarion" + cp -r "$MICRODAO_DIR/docs/daarion"/* "$DAARION_CITY_DIR/docs/daarion/" 2>/dev/null || true + ;; + *) + echo "❌ Невідомий компонент: $COMPONENT" + echo "Доступні компоненти: console, api, docs" + exit 1 + ;; +esac + +# Коміт та push +cd "$DAARION_CITY_DIR" +git add . +git commit -m "feat: sync MicroDAO $COMPONENT component" || echo "ℹ️ Немає змін для коміту" + +echo "✅ Синхронізація завершена!" +echo "📝 Гілка: $BRANCH_NAME" +echo "" +echo "Наступні кроки:" +echo "1. Перевірити зміни: cd $DAARION_CITY_DIR && git diff main" +echo "2. Push гілку: git push -u origin $BRANCH_NAME" +echo "3. Створити PR через GitHub UI" + diff --git a/src/api/http/teams.routes.ts b/src/api/http/teams.routes.ts new file mode 100644 index 00000000..b15fd66d --- /dev/null +++ b/src/api/http/teams.routes.ts @@ -0,0 +1,156 @@ +/** + * Teams Routes (MicroDAO) + * Based on: api-mvp.md, updated for MicroDAO creation with balance checks + * + * Endpoints: + * - POST /api/v1/teams - Create MicroDAO (requires 1 DAARION on balance) + * - GET /api/v1/teams - List teams/MicroDAO + * - GET /api/v1/teams/:teamId - Get team/MicroDAO by ID + * - POST /api/v1/teams/:teamId/members - Invite member (requires balance check) + */ + +import { Router } from 'express'; +import { walletService } from '../../services/wallet/wallet.service'; +import { daoFactoryService } from '../../services/dao-factory/dao-factory.service'; +import type { CreateTeamRequest } from '../../../types/api'; + +export const teamsRoutes = Router(); + +// POST /api/v1/teams - Create MicroDAO +teamsRoutes.post('/', async (req, res) => { + try { + const userId = (req as any).userId; + const input: CreateTeamRequest = req.body; + + // 1. Check wallet balance - need 1 DAARION on balance + const hasEnough = await walletService.hasEnoughForMicroDaoCreate(userId); + if (!hasEnough) { + res.status(403).json({ + error: 'INSUFFICIENT_BALANCE', + message: 'Need 1 DAARION on balance to create MicroDAO', + required: { daarion: 1.0 }, + }); + return; + } + + // 2. Create MicroDAO through DAOFactory + const daoResult = await daoFactoryService.createDao(userId, { + name: input.name, + description: input.description, + type: input.mode === 'confidential' ? 'private' : 'public', + level: 'A4', // User-created MicroDAO are A4 level + }); + + // 3. TODO: Create team record in database + // For now, return DAO result + res.status(201).json({ + id: daoResult.daoId, + name: input.name, + description: input.description, + mode: input.mode || 'public', + type: input.type || 'community', + created_at: new Date().toISOString(), + }); + } catch (error: any) { + res.status(400).json({ + error: error.message?.includes('INSUFFICIENT_BALANCE') ? 'INSUFFICIENT_BALANCE' : 'BAD_REQUEST', + message: error.message, + }); + } +}); + +// GET /api/v1/teams - List teams/MicroDAO +teamsRoutes.get('/', async (req, res) => { + try { + const userId = (req as any).userId; + + // TODO: Get teams from database + // For now, return empty list + res.json({ teams: [] }); + } catch (error: any) { + res.status(500).json({ + error: 'INTERNAL_ERROR', + message: error.message, + }); + } +}); + +// GET /api/v1/teams/:teamId - Get team/MicroDAO by ID +teamsRoutes.get('/:teamId', async (req, res) => { + try { + const { teamId } = req.params; + + // TODO: Get team from database + res.status(404).json({ + error: 'NOT_FOUND', + message: `Team ${teamId} not found`, + }); + } catch (error: any) { + res.status(500).json({ + error: 'INTERNAL_ERROR', + message: error.message, + }); + } +}); + +// POST /api/v1/teams/:teamId/members - Invite member +teamsRoutes.post('/:teamId/members', async (req, res) => { + try { + const userId = (req as any).userId; // Current user (admin) + const { teamId } = req.params; + const { email, role = 'member' } = req.body; + + // 1. Check if current user is admin (has 1 DAARION) + const isAdmin = await walletService.hasEnoughForAdminRole(userId); + if (!isAdmin) { + res.status(403).json({ + error: 'ACCESS_DENIED', + message: 'Need 1 DAARION on balance to invite members', + }); + return; + } + + // 2. Check invited user balance based on role + // TODO: Get invited user ID from email + const invitedUserId = `user_${email}`; // Placeholder + + if (role === 'admin') { + // Admin role requires 1 DAARION + const hasEnough = await walletService.hasEnoughForAdminRole(invitedUserId); + if (!hasEnough) { + res.status(403).json({ + error: 'INSUFFICIENT_BALANCE', + message: 'Invited user needs 1 DAARION on balance to be Admin', + required: { daarion: 1.0 }, + }); + return; + } + } else { + // Member role requires 0.01 DAARION + const hasEnough = await walletService.hasEnoughForMicroDaoUsage(invitedUserId); + if (!hasEnough) { + res.status(403).json({ + error: 'INSUFFICIENT_BALANCE', + message: 'Invited user needs 0.01 DAARION on balance to use MicroDAO', + required: { daarion: 0.01 }, + }); + return; + } + } + + // 3. TODO: Create team member record in database + res.status(201).json({ + team_id: teamId, + user_id: invitedUserId, + email, + role, + status: 'invited', + }); + } catch (error: any) { + res.status(400).json({ + error: 'BAD_REQUEST', + message: error.message, + }); + } +}); + diff --git a/src/app.ts b/src/app.ts index 1629dbcd..e8f0f4d4 100644 --- a/src/app.ts +++ b/src/app.ts @@ -14,6 +14,7 @@ import { pdpRoutes } from './api/http/pdp.routes'; import { vendorRoutes } from './api/http/vendor.routes'; import { platformsRoutes } from './api/http/platforms.routes'; import { agentsRoutes } from './api/http/agents.routes'; +import { teamsRoutes } from './api/http/teams.routes'; const app = express(); @@ -24,6 +25,7 @@ app.use(contextMiddleware); // Routes app.use('/api/v1/dao', daoRoutes); +app.use('/api/v1/teams', teamsRoutes); app.use('/api/v1/wallet', walletRoutes); app.use('/api/v1/pdp', pdpRoutes); app.use('/api/v1/platforms', platformsRoutes); diff --git a/src/services/dao-factory/dao-factory.service.ts b/src/services/dao-factory/dao-factory.service.ts index 78bb7026..e352fca1 100644 --- a/src/services/dao-factory/dao-factory.service.ts +++ b/src/services/dao-factory/dao-factory.service.ts @@ -18,12 +18,13 @@ import { registryService } from '../registry/registry.service'; export class DaoFactoryService { /** * Create a new MicroDAO (A3 or A4) + * Requires: 1 DAARION on balance (not staked) */ async createDao(userId: string, input: CreateDaoInput): Promise<{ daoId: string }> { - // 1. Check wallet balance - const hasEnough = await walletService.hasEnoughForDaoCreate(userId); + // 1. Check wallet balance - need 1 DAARION on balance + const hasEnough = await walletService.hasEnoughForMicroDaoCreate(userId); if (!hasEnough) { - throw new Error('INSUFFICIENT_BALANCE: Need 1 DAAR or 0.01 DAARION'); + throw new Error('INSUFFICIENT_BALANCE: Need 1 DAARION on balance to create MicroDAO'); } // 2. Check PDP policy diff --git a/src/services/wallet/wallet.interface.ts b/src/services/wallet/wallet.interface.ts index b4b0c3a7..6904f980 100644 --- a/src/services/wallet/wallet.interface.ts +++ b/src/services/wallet/wallet.interface.ts @@ -1,12 +1,20 @@ /** * Wallet Service Interface - * Based on: core-services-mvp.md + * Based on: core-services-mvp.md, updated for MicroDAO requirements */ import type { Balance } from '../../domain/wallet/types'; export interface WalletService { getBalances(userId: string): Promise; + getDaarionBalance(userId: string): Promise; + + // MicroDAO access checks (balance-based, no staking) + hasEnoughForMicroDaoCreate(userId: string): Promise; // 1 DAARION + hasEnoughForAdminRole(userId: string): Promise; // 1 DAARION + hasEnoughForMicroDaoUsage(userId: string): Promise; // 0.01 DAARION + + // Legacy methods (deprecated) hasEnoughForDaoCreate(userId: string): Promise; hasEnoughForVendorRegister(userId: string): Promise; hasEnoughForPlatformCreate(userId: string): Promise; diff --git a/src/services/wallet/wallet.service.ts b/src/services/wallet/wallet.service.ts index 5f67cca8..1a8d8476 100644 --- a/src/services/wallet/wallet.service.ts +++ b/src/services/wallet/wallet.service.ts @@ -20,38 +20,62 @@ export class WalletService implements IWalletService { } /** - * Check if user has enough tokens to create a DAO - * Requires: 1 DAAR OR 0.01 DAARION + * Check if user has enough DAARION to create a MicroDAO + * Requires: 1 DAARION on balance (not staked) + */ + async hasEnoughForMicroDaoCreate(userId: string): Promise { + const balances = await this.getBalances(userId); + const daarion = balances.find(b => b.symbol === 'DAARION'); + return daarion ? parseFloat(daarion.amount) >= 1.0 : false; + } + + /** + * Check if user has enough DAARION to be Admin + * Requires: 1 DAARION on balance (not staked) + */ + async hasEnoughForAdminRole(userId: string): Promise { + return this.hasEnoughForMicroDaoCreate(userId); + } + + /** + * Check if user has enough DAARION to use MicroDAO service + * Requires: 0.01 DAARION on balance (not staked) + */ + async hasEnoughForMicroDaoUsage(userId: string): Promise { + const balances = await this.getBalances(userId); + const daarion = balances.find(b => b.symbol === 'DAARION'); + return daarion ? parseFloat(daarion.amount) >= 0.01 : false; + } + + /** + * Get DAARION balance for user + */ + async getDaarionBalance(userId: string): Promise { + const balances = await this.getBalances(userId); + const daarion = balances.find(b => b.symbol === 'DAARION'); + return daarion ? parseFloat(daarion.amount) : 0; + } + + // Legacy methods (deprecated, kept for backward compatibility) + /** + * @deprecated Use hasEnoughForMicroDaoCreate instead */ async hasEnoughForDaoCreate(userId: string): Promise { - const balances = await this.getBalances(userId); - - const daar = balances.find(b => b.symbol === 'DAAR'); - const daarion = balances.find(b => b.symbol === 'DAARION'); - - // Check: 1 DAAR OR 0.01 DAARION - const hasEnoughDaar = daar && parseFloat(daar.amount) >= 1.0; - const hasEnoughDaarion = daarion && parseFloat(daarion.amount) >= 0.01; - - return hasEnoughDaar || hasEnoughDaarion; + return this.hasEnoughForMicroDaoCreate(userId); } /** - * Check if user has enough staked DAARION for vendor registration - * Requires: 0.01 DAARION staked + * @deprecated Not used in current implementation */ async hasEnoughForVendorRegister(userId: string): Promise { - const staked = await walletAdapter.getStakedDaarion(userId); - return staked >= 0.01; + return this.hasEnoughForMicroDaoUsage(userId); } /** - * Check if user has enough staked DAARION for platform creation - * Requires: 1 DAARION staked + * @deprecated Not used in current implementation */ async hasEnoughForPlatformCreate(userId: string): Promise { - const staked = await walletAdapter.getStakedDaarion(userId); - return staked >= 1.0; + return this.hasEnoughForMicroDaoCreate(userId); } } diff --git a/src/types/api.ts b/src/types/api.ts index db06ff05..b23b20f1 100644 --- a/src/types/api.ts +++ b/src/types/api.ts @@ -12,15 +12,21 @@ export interface User { export interface Team { id: string; name: string; + slug: string; description: string | null; mode: 'public' | 'confidential'; + type?: 'city' | 'platform' | 'community' | 'guild' | 'lab' | 'personal'; + parent_team_id?: string | null; created_at: string; updated_at: string; } export interface CreateTeamRequest { name: string; + slug?: string; description?: string; + type?: 'community' | 'guild' | 'lab' | 'personal'; + mode?: 'public' | 'confidential'; } export interface UpdateTeamRequest { diff --git a/supabase/migrations/000010_teams_type_and_city_links.sql b/supabase/migrations/000010_teams_type_and_city_links.sql new file mode 100644 index 00000000..f1c70eb3 --- /dev/null +++ b/supabase/migrations/000010_teams_type_and_city_links.sql @@ -0,0 +1,50 @@ +-- 000010_teams_type_and_city_links.sql +-- Add type field to teams and city_links table for DAARION.city integration + +-- Up + +-- Add type field to teams table +alter table teams +add column if not exists type text check (type in ('city', 'platform', 'community', 'guild', 'lab', 'personal')); + +-- Add index for type +create index if not exists idx_teams_type on teams(type); + +-- Add parent_team_id for hierarchical structure (DAARION.city -> platforms -> microDAO) +alter table teams +add column if not exists parent_team_id text references teams(id) on delete set null; + +-- Add index for parent_team_id +create index if not exists idx_teams_parent_team_id on teams(parent_team_id); + +-- Create city_links table for explicit relationships +create table if not exists city_links ( + id text primary key, + parent_team_id text not null references teams(id) on delete cascade, + child_team_id text not null references teams(id) on delete cascade, + relation_type text not null check (relation_type in ('platform', 'microdao', 'subdao')), + created_at timestamptz not null default now(), + unique (parent_team_id, child_team_id) +); + +create index if not exists idx_city_links_parent_team_id on city_links(parent_team_id); +create index if not exists idx_city_links_child_team_id on city_links(child_team_id); + +-- Insert DAARION.city as first MicroDAO (type='city') +insert into teams (id, name, slug, mode, type, parent_team_id, created_at) +values ( + 'daarion-city', + 'DAARION.city', + 'daarion', + 'public', + 'city', + null, + now() +) +on conflict (slug) do nothing; + +-- Down +drop table if exists city_links cascade; +alter table teams drop column if exists parent_team_id; +alter table teams drop column if exists type; + diff --git a/supabase/migrations/README.md b/supabase/migrations/README.md index 503e222a..95a855bd 100644 --- a/supabase/migrations/README.md +++ b/supabase/migrations/README.md @@ -17,7 +17,8 @@ SQL-міграції для схеми бази даних microDAO/DAARION.city 7. `000007_embassy.sql` - Embassy Module (identities, webhooks, oracles) 8. `000008_access_keys_capabilities.sql` - Access Keys, Capabilities, Bundles 9. `000009_audit_outbox.sql` - Audit Log, Outbox Events -10. `seeds.sql` - Seed data для bundles, capabilities та bundle mappings (запускати після всіх міграцій) +10. `000010_teams_type_and_city_links.sql` - Teams type field, city_links, DAARION.city seed +11. `seeds.sql` - Seed data для bundles, capabilities та bundle mappings (запускати після всіх міграцій) ---