Flutter приложение для работы с предсказательными рынками Polymarket.
Проект использует Clean Architecture с разделением на слои и Feature-First подход.
lib/
├── app/ # Конфигурация приложения
│ ├── app.dart # Главный виджет приложения
│ ├── di.dart # Dependency Injection (Riverpod)
│ └── router.dart # Навигация (GoRouter)
├── core/ # Общие компоненты
│ ├── network/ # Сетевые утилиты
│ ├── storage/ # Локальное хранилище
│ └── utils/ # Утилиты
├── feature/ # Фичи приложения
│ ├── markets/ # Маркеты
│ ├── portfolio/ # Портфолио
│ └── favorites/ # Избранное
└── shared/ # Общие виджеты
└── widgets/
Каждая фича имеет одинаковую структуру:
feature/
├── domain/ # Бизнес-логика
│ ├── models/ # Доменные модели
│ └── repo/ # Интерфейсы репозиториев
├── data/ # Данные
│ ├── datasources/ # API клиенты
│ ├── models/ # DTO модели
│ ├── mapper/ # Мапперы DTO -> Domain
│ └── repo/ # Реализации репозиториев
└── presentation/ # UI слой
├── controllers/ # StateNotifier (Riverpod)
├── models/ # ViewState модели
├── mappers/ # Мапперы Domain -> ViewState
├── pages/ # Экраны
└── widgets/ # UI компоненты
- Flutter - UI фреймворк
- Riverpod - State Management + DI
- GoRouter - Навигация
- Dio - HTTP клиент
- SharedPreferences - Локальное хранилище
- Clean Architecture - Архитектурный паттерн
- Models - Доменные сущности (Market, Position, Tag)
- Repositories - Интерфейсы для работы с данными
- Не зависит от внешних слоев
- DataSources - API клиенты (GammaApi, ClobPricesApi)
- DTO Models - Модели для API (MarketDto)
- Mappers - Конвертация DTO -> Domain
- Repository Impl - Реализация интерфейсов из Domain
- Controllers - StateNotifier для управления состоянием
- ViewState Models - Модели для UI
- Mappers - Конвертация Domain -> ViewState
- Pages - Экраны приложения
- Widgets - Переиспользуемые UI компоненты
// StateNotifier для управления состоянием
class MarketsNotifier extends StateNotifier<MarketsState> {
MarketsNotifier(this._repo) : super(MarketsState());
Future<void> loadFirst() async {
state = state.copyWith(loading: true);
// ... бизнес-логика
}
}
// Провайдер в DI
final marketsNotifierProvider =
StateNotifierProvider<MarketsNotifier, MarketsState>(
(ref) => MarketsNotifier(ref.read(marketsRepoProvider)),
);// Провайдеры в app/di.dart
final marketsRepoProvider = Provider<MarketsRepo>(
(ref) =>
MarketsRepoImpl(
ref.read(gammaApiProvider),
ref.read(clobPricesApiProvider),
),
);// Интерфейс в domain
abstract class MarketsRepo {
Future<(List<Market>, String?)> getMarketsPage
(
{
...
});
}
// Реализация в data
class MarketsRepoImpl implements MarketsRepo {
MarketsRepoImpl(this._gamma, this._clob);
@override
Future<(List<Market>, String?)> getMarketsPage
(
{
...
}) async {
// ... реализация
}
}# Установка зависимостей
flutter pub get
# Запуск приложения
flutter run- Просмотр списка маркетов
- Фильтрация по категориям (тегам)
- Поиск маркетов
- Детальная информация о маркете
- Просмотр позиций
- История трейдов
- Статистика PnL
- Добавление/удаление из избранного
- Просмотр избранных маркетов
- Создание фичи: Создаем папку в
feature/ - Domain: Определяем модели и интерфейсы
- Data: Реализуем API клиенты и репозитории
- Presentation: Создаем UI и контроллеры
- DI: Регистрируем в
app/di.dart - Router: Добавляем маршруты в
app/router.dart