Skip to content

Commit e51c689

Browse files
Merge pull request #257 from blockful/feat/anticapture_client
Feat/anticapture client
2 parents cd2c629 + 573cf82 commit e51c689

200 files changed

Lines changed: 5642 additions & 16795 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: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Copy this file to .env and configure your settings
33

44
# === REQUIRED CONFIGURATION ===
5-
ANTICAPTURE_GRAPHQL_ENDPOINT=https://api-gateway-production-0879.up.railway.app/graphql
5+
ANTICAPTURE_API_URL=https://api-gateway-production-0879.up.railway.app
66
BLOCKFUL_API_TOKEN=
77

88
# === NOTIFICATION PLATFORMS ===
@@ -16,7 +16,9 @@ TOKEN_ENCRYPTION_KEY= # Generate: openssl rand -hex 32
1616
# === LOCAL DEV CONFIGURATION ===
1717
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/postgres
1818
RABBITMQ_URL=amqp://admin:admin@localhost:5672
19-
PORT=3003
20-
TRIGGER_INTERVAL=30000 # ms
21-
PROPOSAL_STATUS=ACTIVE
22-
PORT=3002
19+
TRIGGER_INTERVAL=30000 # ms (logic-system)
20+
PROPOSAL_STATUS=ACTIVE # (logic-system)
21+
22+
# Per-service PORT — use per-app .env files for cleaner separation
23+
# subscription-server PORT=3002
24+
# logic-system PORT=3003

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ jobs:
1818
- uses: actions/checkout@v3
1919
- uses: actions/setup-node@v3
2020
with:
21-
node-version: "20"
21+
node-version: "22"
2222
- uses: pnpm/action-setup@v2
2323
with:
2424
version: 10.14.0

.gitignore

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ coverage
2626
out/
2727
build
2828
dist
29-
!packages/anticapture-client/dist
3029

3130
# Generated GraphQL files
3231
**/src/generated/

AGENTS.md

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,12 +6,12 @@
66

77
Event-driven notification system for DAO governance, built as a **pnpm monorepo** with 4 microservices connected via RabbitMQ:
88

9-
1. **Logic System** (`apps/logic-system/`) - Polls AntiCapture GraphQL API every Xs, detects governance events, publishes trigger events
9+
1. **Logic System** (`apps/logic-system/`) - Polls AntiCapture REST API every Xs, detects governance events, publishes trigger events
1010
2. **Dispatcher** (`apps/dispatcher/`) - Consumes trigger events, fetches subscribers with temporal filtering, routes notifications
1111
3. **Subscription Server** (`apps/subscription-server/`) - Fastify REST API for user preferences, PostgreSQL persistence, Slack OAuth
1212
4. **Consumer** (`apps/consumers/`) - Delivers notifications via Telegram (telegraf) and Slack (@slack/bolt) bots
1313

14-
Supporting packages: `anticapture-client` (GraphQL), `messages` (templates), `rabbitmq-client` (AMQP wrapper).
14+
Supporting packages: `anticapture-client` (REST SDK wrapper), `messages` (templates), `rabbitmq-client` (AMQP wrapper).
1515

1616
Dashboard (`apps/dashboard/`) provides read-only metrics via Next.js.
1717

@@ -37,9 +37,6 @@ NODE_ENV=test pnpm --filter @notification-system/integrated-tests test
3737
# Type checking and linting
3838
pnpm consumer check-types
3939
pnpm logic-system lint
40-
41-
# GraphQL code generation (requires ANTICAPTURE_GRAPHQL_ENDPOINT)
42-
pnpm client codegen
4340
```
4441

4542
## Notification Pipeline
@@ -123,7 +120,7 @@ Required `.env` variables:
123120
```
124121
DATABASE_URL=postgresql://user:pass@localhost/dbname
125122
RABBITMQ_URL=amqp://localhost
126-
ANTICAPTURE_GRAPHQL_ENDPOINT=https://...
123+
ANTICAPTURE_API_URL=https://...
127124
TELEGRAM_BOT_TOKEN=...
128125
SLACK_SIGNING_SECRET=...
129126
TOKEN_ENCRYPTION_KEY=... # 64-char hex for AES-256-CBC
@@ -134,7 +131,7 @@ TOKEN_ENCRYPTION_KEY=... # 64-char hex for AES-256-CBC
134131
- **Language:** TypeScript (strict mode) across all services
135132
- **Validation:** Zod schemas for environment variables and API inputs
136133
- **Monorepo:** pnpm workspaces + Turbo for builds
137-
- **Testing:** Jest with ts-jest (most services), Node.js test runner (dashboard)
134+
- **Testing:** Vitest (all apps + packages), MSW for HTTP/JSON stubs in integrated-tests, Node.js test runner (dashboard)
138135
- **Package manager:** pnpm 10.x, Node.js >= 18
139136

140137
## Deployment
@@ -250,8 +247,6 @@ VALUES (
250247
- `state = 'closed'` (not `'active'`)
251248
- `end` = recent past (within last 24h so trigger cursor picks it up)
252249

253-
**Gateway note:** If the production gateway returns a GraphQL error for DAOs with `null` in non-nullable fields (e.g. `supportOffchainData`), `getDAOs()` may return an empty list and skip all offchain queries. To avoid this during local testing, run the API gateway locally pointing only to the ENS API and set `ANTICAPTURE_GRAPHQL_ENDPOINT=http://host.docker.internal:4000/graphql` in `.env`.
254-
255250
### New Offchain Proposal Insert (Snapshot)
256251
```sql
257252
-- No triggers on snapshot.proposals, safe to insert directly

apps/consumers/AGENTS.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,7 @@ src/
7777
| `TELEGRAM_BOT_TOKEN` | Yes | Telegram BotFather token |
7878
| `SLACK_SIGNING_SECRET` | Yes | Slack app signing secret |
7979
| `TOKEN_ENCRYPTION_KEY` | Yes | 64-char hex for workspace token decryption |
80-
| `ANTICAPTURE_GRAPHQL_ENDPOINT` | Yes | GraphQL API endpoint |
80+
| `ANTICAPTURE_API_URL` | Yes | REST API base URL |
8181
| `SUBSCRIPTION_SERVER_URL` | Yes | Subscription Server base URL |
8282
| `RABBITMQ_URL` | Yes | RabbitMQ connection string |
8383
| `PORT` | No | Slack HTTP receiver port (default: 3002) |
@@ -88,7 +88,7 @@ src/
8888
pnpm consumer test
8989
```
9090

91-
Uses ts-jest. Type checking: `pnpm consumer check-types`.
91+
Uses Vitest. Type checking: `pnpm consumer check-types`.
9292

9393
## Key Implementation Details
9494

apps/consumers/README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,14 +53,14 @@ src/
5353
| Variable | Required | Description |
5454
|----------|----------|-------------|
5555
| `TELEGRAM_BOT_TOKEN` || Telegram bot authentication token |
56-
| `ANTICAPTURE_GRAPHQL_ENDPOINT` || GraphQL API endpoint for DAO data |
56+
| `ANTICAPTURE_API_URL` || REST API endpoint for DAO data |
5757
| `SUBSCRIPTION_SERVER_URL` || Subscription management API URL |
5858
| `RABBITMQ_URL` || RabbitMQ connection string |
5959

6060
### Example Configuration
6161
```bash
6262
TELEGRAM_BOT_TOKEN=123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11
63-
ANTICAPTURE_GRAPHQL_ENDPOINT=https://api.anticapture.xyz/graphql
63+
ANTICAPTURE_API_URL=https://api.anticapture.xyz
6464
SUBSCRIPTION_SERVER_URL=http://subscription-server:3001
6565
RABBITMQ_URL=amqp://user:pass@rabbitmq:5672
6666
```

apps/consumers/example.env

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
TELEGRAM_BOT_TOKEN=your_telegram_bot_token
2-
ANTICAPTURE_GRAPHQL_ENDPOINT=https://api-gateway/graphql
2+
ANTICAPTURE_API_URL=https://api-gateway
33
BLOCKFUL_API_TOKEN=
44
SUBSCRIPTION_SERVER_URL=http://localhost:3001
55
API_PORT=3000

apps/consumers/jest.config.js

Lines changed: 0 additions & 10 deletions
This file was deleted.

apps/consumers/package.json

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,24 +8,23 @@
88
"dev": "nodemon --exec 'ts-node' src/index.ts",
99
"build": "tsc",
1010
"check-types": "tsc --noEmit",
11-
"test": "jest"
11+
"test": "vitest run"
1212
},
1313
"keywords": [],
1414
"author": "",
1515
"license": "ISC",
1616
"description": "",
1717
"devDependencies": {
18-
"@jest/globals": "^29.7.0",
19-
"@types/jest": "^29.5.11",
2018
"@types/node": "^20.17.46",
21-
"jest": "^29.7.0",
19+
"msw": "^2.12.10",
2220
"nodemon": "^3.1.0",
23-
"ts-jest": "^29.1.1",
2421
"ts-node": "^10.9.2",
25-
"typescript": "^5.8.3"
22+
"typescript": "^5.8.3",
23+
"vitest": "^4.1.5"
2624
},
2725
"dependencies": {
2826
"@anticapture/observability": "^1.0.0",
27+
"@fastify/cors": "^11.0.1",
2928
"@notification-system/anticapture-client": "workspace:*",
3029
"@notification-system/messages": "workspace:*",
3130
"@notification-system/rabbitmq-client": "workspace:*",
@@ -34,10 +33,9 @@
3433
"@slack/web-api": "^7.10.0",
3534
"axios": "^1.7.2",
3635
"dotenv": "^16.4.7",
37-
"telegraf": "^4.16.3",
3836
"fastify": "^5.3.2",
39-
"@fastify/cors": "^11.0.1",
4037
"fastify-type-provider-zod": "^4.0.2",
38+
"telegraf": "^4.16.3",
4139
"viem": "^2.34.0",
4240
"zod": "^3.24.3"
4341
}

apps/consumers/src/app.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
import { AxiosInstance } from 'axios';
21
import { TelegramBotService } from './services/bot/telegram-bot.service';
32
import { SlackBotService } from './services/bot/slack-bot.service';
43
import { WebhookService } from './services/webhook/webhook.service';
@@ -11,7 +10,7 @@ import { TelegramDAOService } from './services/dao/telegram-dao.service';
1110
import { TelegramWalletService } from './services/wallet/telegram-wallet.service';
1211
import { TelegramSettingsService } from './services/settings/telegram-settings.service';
1312
import { ExplorerService } from '@notification-system/messages';
14-
import { EnsResolverService } from './services/ens-resolver.service';
13+
import { IEnsResolver } from './services/ens-resolver.service';
1514
import { AnticaptureClient } from '@notification-system/anticapture-client';
1615
import { SubscriptionAPIService } from './services/subscription-api.service';
1716
import { RabbitMQNotificationConsumerService } from './services/rabbitmq-notification-consumer.service';
@@ -34,15 +33,19 @@ export class App {
3433

3534
constructor(
3635
subscriptionServerUrl: string,
37-
httpClient: AxiosInstance,
36+
anticaptureBaseURL: string,
3837
rabbitmqUrl: string,
39-
ensResolver: EnsResolverService,
38+
ensResolver: IEnsResolver,
4039
telegramClient: TelegramClientInterface,
4140
slackClient: SlackClientInterface,
42-
webhookPort: number
41+
webhookPort: number,
42+
anticaptureHeaders?: Record<string, string>
4343
) {
4444
const subscriptionApi = wrapWithTracing(new SubscriptionAPIService(subscriptionServerUrl, logger));
45-
const anticaptureClient = wrapWithTracing(new AnticaptureClient(httpClient));
45+
const anticaptureClient = wrapWithTracing(new AnticaptureClient({
46+
baseURL: anticaptureBaseURL,
47+
defaultHeaders: anticaptureHeaders,
48+
}));
4649
const explorerService = new ExplorerService();
4750

4851
// Telegram services

0 commit comments

Comments
 (0)