Skip to content

Commit 6656cbe

Browse files
Merge pull request #184 from blockful/dev
Dev
2 parents e3be731 + 724ded0 commit 6656cbe

142 files changed

Lines changed: 9840 additions & 1514 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.env.example

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Notification System Environment Variables
2+
# Copy this file to .env and configure your settings
3+
4+
# === REQUIRED CONFIGURATION ===
5+
ANTICAPTURE_GRAPHQL_ENDPOINT=https://api-gateway-production-0879.up.railway.app/graphql
6+
7+
# === NOTIFICATION PLATFORMS ===
8+
TELEGRAM_BOT_TOKEN=
9+
SLACK_CLIENT_ID=
10+
SLACK_CLIENT_SECRET=
11+
SLACK_REDIRECT_URI=https://your-domain.com/slack/oauth/callback
12+
SLACK_APP_TOKEN=xapp-
13+
SLACK_SIGNING_SECRET=
14+
TOKEN_ENCRYPTION_KEY= # Generate: openssl rand -hex 32
15+
16+
# === LOCAL DEV CONFIGURATION ===
17+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
18+
RABBITMQ_URL=amqp://admin:admin@localhost:5672
19+
PORT=3003
20+
TRIGGER_INTERVAL=30000 # ms
21+
PROPOSAL_STATUS=ACTIVE

.github/workflows/test.yaml

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
name: Test
2+
3+
on:
4+
pull_request:
5+
6+
jobs:
7+
test:
8+
runs-on: ubuntu-latest
9+
strategy:
10+
fail-fast: false
11+
matrix:
12+
package:
13+
- dispatcher
14+
- logic-system
15+
- consumer
16+
- subscription-server
17+
steps:
18+
- uses: actions/checkout@v3
19+
- uses: actions/setup-node@v3
20+
with:
21+
node-version: "18"
22+
- uses: pnpm/action-setup@v2
23+
with:
24+
version: latest
25+
- name: Get pnpm store directory
26+
shell: bash
27+
run: |
28+
echo "STORE_PATH=$(pnpm store path --silent)" >> $GITHUB_ENV
29+
- name: Setup pnpm cache
30+
uses: actions/cache@v3
31+
with:
32+
path: ${{ env.STORE_PATH }}
33+
key: ${{ runner.os }}-pnpm-store-${{ hashFiles('**/pnpm-lock.yaml') }}
34+
restore-keys: |
35+
${{ runner.os }}-pnpm-store-
36+
- name: Install dependencies
37+
run: pnpm install
38+
- name: Build workspace packages
39+
run: pnpm build
40+
- name: Test ${{ matrix.package }}
41+
run: |
42+
pnpm ${{ matrix.package }} test

CLAUDE.md

Lines changed: 102 additions & 184 deletions
Original file line numberDiff line numberDiff line change
@@ -2,218 +2,136 @@
22

33
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
44

5-
## Recent Changes (2025-08-15)
5+
## Recent Changes
66

7-
### Migration from proposalsOnchains to proposals query
8-
- **GraphQL Queries Updated**: Migrated from `proposalsOnchains` to new `proposals` query endpoint
9-
- **New Features**:
10-
- Added native `title` field support (no longer extracting from description)
11-
- Simplified response structure (direct array instead of `items` wrapper)
12-
- **API Changes**:
13-
- Query parameters: `where` filters replaced with `status`, `fromDate`, `skip`, `limit`
14-
- Response format: `proposals` returns array directly, not `{ items: [...] }`
15-
- Field `proposalsOnchain` renamed to `proposal` for single queries
16-
- **Removed Fields**: `targets`, `values`, `signatures`, `calldatas` (not used by notification system)
7+
### Slack OAuth Multi-Workspace Support (2025-09-18)
8+
- OAuth 2.0 flow implementation in Subscription Server (`/slack/install`, `/slack/oauth/callback`)
9+
- Workspace token storage with AES-256-CBC encryption in `slack_workspaces` table
10+
- Dynamic token distribution via RabbitMQ messages (bot_token field)
11+
- Backward compatible with workspace:user ID format (T_DEFAULT for legacy)
12+
- See `docs/slack-oauth-setup.md` for configuration guide
1713

18-
## Repository Overview
14+
### Slack Integration (2025-09-17)
15+
- Added Socket Mode support for interactive Slack features in Consumer service
16+
- New service classes: SlackDAOService, SlackWalletService for command handling
17+
- Session management using InMemorySessionStorage (consider Redis for production)
18+
- Slack Block Kit UI implementation for rich interactive messages
1919

20-
This is an event-driven notification system for DAO governance built with microservices architecture. The system monitors blockchain proposals and delivers notifications via Telegram (with extensibility for other channels).
20+
### GraphQL Migration (2025-08-15)
21+
- **IMPORTANT**: Currently reverting some changes - `proposals` query now returns `{ items: [], totalCount }` structure
22+
- Native `title` field support (no longer extracted from description)
23+
- Query parameters: `status`, `fromDate`, `skip`, `limit` replaced `where` filters
24+
- Field `proposalsOnchain` renamed to `proposal` for single queries
2125

22-
## Architecture
26+
## Architecture Overview
2327

24-
The system consists of 4 microservices connected via RabbitMQ:
28+
Event-driven notification system with 4 microservices connected via RabbitMQ:
2529

26-
1. **Logic System** - Monitors AntiCapture API for proposal events and triggers notifications
27-
2. **Dispatcher** - Processes events, fetches subscribers, and creates notification messages
28-
3. **Subscription Server** - REST API for managing user preferences and tracking notifications
29-
4. **Consumer** - Telegram bot that delivers notifications and handles user interactions
30+
1. **Logic System** (`apps/logic-system/`) - Monitors AntiCapture API, triggers events every 30 seconds
31+
2. **Dispatcher** (`apps/dispatcher/`) - Processes events, fetches subscribers, creates notifications
32+
3. **Subscription Server** (`apps/subscription-server/`) - REST API for user preferences, PostgreSQL persistence
33+
4. **Consumer** (`apps/consumers/`) - Delivers notifications via Telegram/Slack bots
3034

31-
## Key Commands
35+
## Essential Commands
3236

33-
### Development
3437
```bash
35-
# Install dependencies (requires pnpm)
36-
pnpm install
37-
38-
# Start all services with Docker Compose
39-
pnpm dev
40-
41-
# Build all services
42-
pnpm build
38+
# Development
39+
pnpm install # Install all dependencies
40+
pnpm dev # Start all services with Docker Compose
41+
pnpm build # Build all services
42+
pnpm test # Run all tests
43+
44+
# Service-specific shortcuts
45+
pnpm logic-system <cmd> # Run commands in logic-system
46+
pnpm dispatcher <cmd> # Run commands in dispatcher
47+
pnpm subscription-server <cmd> # Run commands in subscription-server
48+
pnpm consumer <cmd> # Run commands in consumer
49+
50+
# Testing patterns
51+
pnpm --filter @notification-system/logic-system test
52+
pnpm --filter @notification-system/integrated-tests test -- --testNamePattern="voting"
53+
NODE_ENV=test pnpm --filter @notification-system/integrated-tests test
4354

44-
# Run tests across all services
45-
pnpm test
55+
# Type checking and linting
56+
pnpm consumer check-types
57+
pnpm logic-system lint
4658

47-
# Format code
48-
pnpm format
59+
# GraphQL code generation
60+
pnpm client codegen
61+
ANTICAPTURE_GRAPHQL_ENDPOINT="https://api-gateway-production-0879.up.railway.app/graphql" pnpm client codegen
4962
```
5063

51-
### Service-Specific Commands
52-
```bash
53-
# Run commands for specific services
54-
pnpm logic-system <command>
55-
pnpm dispatcher <command>
56-
pnpm subscription-server <command>
57-
pnpm consumer <command>
64+
## Message Flow Patterns
5865

59-
# Example: Run tests for logic-system
60-
pnpm logic-system test
66+
### Notification Pipeline
67+
1. Logic System polls AntiCapture API → publishes `TriggerEvent` to RabbitMQ
68+
2. Dispatcher consumes trigger → fetches subscribers with temporal filtering → publishes notifications
69+
3. Consumer delivers via Telegram/Slack → tracks delivery in Subscription Server
6170

62-
# Example: Start a single service in dev mode
63-
pnpm logic-system dev
64-
```
71+
### Adding New Trigger Types
72+
1. Extend base `Trigger` class in `apps/logic-system/src/triggers/`
73+
2. Implement `fetchData()` and `process()` methods
74+
3. Register in `App.setupTriggers()` in Logic System
75+
4. Create handler in `apps/dispatcher/src/trigger-handlers/`
76+
5. Register handler in `TriggerProcessorService`
6577

66-
### Testing
67-
```bash
68-
# Run all tests
69-
pnpm test
78+
## Service Architectures
7079

71-
# Run tests for a specific service
72-
pnpm --filter @notification-system/logic-system test
80+
### Consumer Service (Telegram/Slack Bot)
81+
- **Telegram**: Uses telegraf with session management via telegraf-session-local
82+
- **Slack**: Uses @slack/bolt with Socket Mode for interactive features
83+
- **Pattern**: Service classes (TelegramBotService, SlackBotService) implement BotServiceInterface
84+
- **Session Storage**: InMemorySessionStorage for Slack (needs Redis for production scale)
7385

74-
# Run a single test file
75-
pnpm --filter @notification-system/logic-system test -- path/to/test.spec.ts
76-
```
86+
### Subscription Server API
87+
- **Framework**: Fastify with Swagger documentation
88+
- **Database**: PostgreSQL with Knex.js migrations in `db/migrations/`
89+
- **Deduplication**: Tracks notifications in `user_notifications` table
90+
- **Temporal Filtering**: Only notifies users subscribed before event timestamp
7791

78-
## Project Structure
92+
### Logic System Triggers
93+
- **Base Class**: `Trigger` abstract class with `fetchData()` and `process()` lifecycle
94+
- **Polling**: 30-second intervals configured per trigger
95+
- **State Management**: Tracks last processed items to avoid duplicates
7996

80-
```
81-
apps/
82-
├── logic-system/ # Event monitoring and triggering
83-
├── dispatcher/ # Message processing and routing
84-
├── subscription-server/ # User preference API
85-
├── consumers/ # Telegram bot delivery
86-
└── integrated-tests/ # End-to-end testing
87-
88-
packages/
89-
├── anticapture-client/ # GraphQL client for DAO data
90-
└── rabbitmq-client/ # Shared RabbitMQ utilities
91-
```
92-
93-
## Key Technologies
97+
## Database Schema
9498

95-
- **Runtime**: Node.js 18+, TypeScript 5.8.2
96-
- **Frameworks**: Fastify (APIs), Express (legacy)
97-
- **Database**: PostgreSQL with Knex.js migrations
98-
- **Message Queue**: RabbitMQ for service communication
99-
- **Testing**: Jest with ts-jest
100-
- **Build**: Turbo monorepo with pnpm workspaces
99+
Key tables in Subscription Server:
100+
- `users`: User profiles with platform-specific IDs (telegram_id, slack_id)
101+
- `user_dao_subscriptions`: Many-to-many subscriptions with created_at for temporal filtering
102+
- `user_notifications`: Delivery tracking for deduplication
103+
- `user_wallets`: Wallet addresses for personalized notifications
101104

102-
## Message Flow
105+
## Testing Strategies
103106

104-
1. Logic System polls AntiCapture API every 30 seconds
105-
2. On new proposals, sends `TriggerEvent` to dispatcher queue
106-
3. Dispatcher fetches relevant subscribers and creates notifications
107-
4. Consumer receives notifications and delivers via Telegram
108-
5. Delivery status tracked in Subscription Server
107+
### Unit Tests
108+
- Mock RabbitMQ connections with `jest.mock('@notification-system/rabbitmq-client')`
109+
- Mock GraphQL responses in `integrated-tests/src/mocks/graphql-mock-setup.ts`
109110

110-
## Database Schema
111+
### Integration Tests
112+
- Test helpers in `integrated-tests/src/helpers/` for each platform
113+
- Use `waitForMessage()` pattern for async message verification
114+
- Environment: `NODE_ENV=test` for test database isolation
111115

112-
The Subscription Server manages:
113-
- `users`: User profiles with Telegram/Discord IDs
114-
- `daos`: DAO registry from AntiCapture
115-
- `user_dao_subscriptions`: Many-to-many subscription relationships
116-
- `user_notifications`: Notification delivery tracking for deduplication
116+
### End-to-End Tests
117+
- Full service orchestration tests in `apps/integrated-tests/tests/`
118+
- Docker Compose setup mimics production environment
117119

118120
## Environment Configuration
119121

120-
Each service requires specific environment variables:
121-
- Copy `env.example` to `.env` at project root
122-
- Key variables: `DATABASE_URL`, `RABBITMQ_URL`, `TELEGRAM_BOT_TOKEN`
123-
- AntiCapture API endpoint configuration
124-
125-
## Testing Strategy
126-
127-
- Unit tests for business logic in each service
128-
- Integration tests for API endpoints
129-
- End-to-end tests in `integrated-tests` app
130-
- Jest configuration in each service's `jest.config.js`
122+
Required variables in `.env`:
123+
```
124+
DATABASE_URL=postgresql://user:pass@localhost/dbname
125+
RABBITMQ_URL=amqp://localhost
126+
TELEGRAM_BOT_TOKEN=your_bot_token
127+
SLACK_BOT_TOKEN=xoxb-your-token
128+
SLACK_APP_TOKEN=xapp-your-app-token # For Socket Mode
129+
SLACK_SIGNING_SECRET=your-signing-secret
130+
ANTICAPTURE_GRAPHQL_ENDPOINT=https://api-gateway-production-0879.up.railway.app/graphql
131+
```
131132

132133
## Deployment
133134

134-
- GitHub Actions workflow in `.github/workflows/`
135-
- Deploys to Railway on push to `dev` or `main`
136-
- Path-based deployment triggers for specific services
137-
- Docker Compose for local development mimics production
138-
=======
139-
## Project Overview
140-
141-
This is an event-driven notification system for DAO governance built with microservices architecture. The system monitors blockchain data for DAO proposals and delivers real-time notifications to users via Telegram. It uses RabbitMQ for message queuing and PostgreSQL for persistence.
142-
143-
## Architecture
144-
145-
The system consists of 4 main microservices:
146-
147-
1. **Logic System** (`apps/logic-system/`) - Monitors AntiCapture GraphQL API and triggers events
148-
2. **Dispatcher** (`apps/dispatcher/`) - Processes trigger events and coordinates notification delivery
149-
3. **Subscription Server** (`apps/subscription-server/`) - REST API for user preferences and subscription management
150-
4. **Consumer** (`apps/consumers/`) - Telegram bot and notification delivery service
151-
152-
## Development Commands
153-
154-
### Root Level Commands
155-
- `pnpm dev` - Start all services with Docker Compose
156-
- `pnpm build` - Build all apps using Turbo
157-
- `pnpm test` - Run tests across all apps
158-
- `pnpm format` - Format code with Prettier
159-
160-
### Per-Service Commands
161-
Use the filter pattern to run commands in specific services:
162-
- `pnpm --filter @notification-system/logic-system <command>`
163-
- `pnpm --filter @notification-system/dispatcher <command>`
164-
- `pnpm --filter @notification-system/subscription-server <command>`
165-
- `pnpm --filter @notification-system/consumer <command>`
166-
167-
### Testing and Quality
168-
- **Tests**: Each service uses Jest with TypeScript (`jest.config.js` or `jest.config.ts`)
169-
- **Linting**: Logic system has ESLint configured (`pnpm logic-system lint`)
170-
- **Type Checking**: Consumers service has type checking (`pnpm consumer check-types`)
171-
172-
## Message Flow Architecture
173-
174-
1. **Logic System** polls AntiCapture API → sends trigger events to RabbitMQ
175-
2. **Dispatcher** consumes trigger events → fetches subscribers → creates notifications → publishes to Consumer queue
176-
3. **Consumer** delivers notifications via Telegram → tracks delivery status in Subscription Server
177-
178-
## Key Implementation Patterns
179-
180-
### Trigger System
181-
New trigger types follow this pattern:
182-
- Extend base `Trigger` class in Logic System
183-
- Implement `fetchData()` and `process()` methods
184-
- Register in Logic System's `App` class
185-
- Create corresponding handler in Dispatcher's trigger handlers
186-
- Register handler in `TriggerProcessorService`
187-
188-
### RabbitMQ Integration
189-
- Logic System publishes trigger events
190-
- Dispatcher consumes trigger events and publishes notification events
191-
- Consumer consumes notification events for delivery
192-
193-
### Database Migrations
194-
Subscription Server uses Knex.js for database operations with migrations in `db/migrations/`
195-
196-
## Technology Stack
197-
198-
- **Runtime**: Node.js 18+ with pnpm workspaces
199-
- **Build Tool**: Turbo for monorepo builds
200-
- **Messaging**: RabbitMQ with custom client abstractions
201-
- **Database**: PostgreSQL with Knex.js migrations
202-
- **API**: Fastify for REST endpoints
203-
- **GraphQL**: Custom AntiCapture client in packages/
204-
- **Testing**: Jest with ts-jest preset
205-
- **Containerization**: Docker with multi-service compose
206-
207-
## Environment Requirements
208-
209-
Essential environment variables:
210-
- `TELEGRAM_BOT_TOKEN` - Telegram bot authentication
211-
- `ANTICAPTURE_GRAPHQL_ENDPOINT` - DAO data source
212-
- `DATABASE_URL` - PostgreSQL connection
213-
- `RABBITMQ_URL` - Message broker connection
214-
215-
## Extension Points
216-
217-
- **New Trigger Types**: Follow the pattern documented in `apps/logic-system/add-trigger-logic.md`
218-
- **Notification Channels**: Add new delivery mechanisms in Consumer service
219-
- **DAO Data Sources**: Extend AntiCapture client or add new data providers
135+
- GitHub Actions deploys to Railway on push to `dev` or `main`
136+
- Path-based triggers for selective service deployment
137+
- Docker Compose configuration in `docker-compose.yml` for local development

0 commit comments

Comments
 (0)