Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions ARCHITECTURE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# NotifyChain Architecture

This file is the architecture documentation entry point for contributors who
look for `ARCHITECTURE.md` at the repository root.

- [Architecture Overview](ARCHITECTURE_OVERVIEW.md) explains the system layers,
data flow, and module responsibilities.
- [System Architecture](SYSTEM_ARCHITECTURE.md) provides visual Mermaid
architecture diagrams for the on-chain, listener, and presentation layers.
- [API Sequence Diagrams](docs/api-sequence-diagrams.md) documents the
notification request flow, event processing lifecycle, and scheduled
notification lifecycle.
- [TaskBounty Architecture](Documents/Task%20Bounty/ARCHITECTURE.md) covers the
TaskBounty contract internals.
7 changes: 7 additions & 0 deletions ARCHITECTURE_OVERVIEW.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ repository implement each piece.
> [`SYSTEM_ARCHITECTURE.md`](SYSTEM_ARCHITECTURE.md) for a visual overview
> with Mermaid architecture diagrams, then return here for the detailed
> walkthrough.
> For request-level sequence diagrams, see
> [`docs/api-sequence-diagrams.md`](docs/api-sequence-diagrams.md).

It does **not** replace the deeper subsystem docs linked at the end — read it
first, then dive into the linked material as needed.
Expand Down Expand Up @@ -160,6 +162,11 @@ event stream into three concrete things:

### 4.1 Internal Pipeline

The sequence-level version of this flow is documented in
[`docs/api-sequence-diagrams.md`](docs/api-sequence-diagrams.md), including the
notification request path, event processing lifecycle, and scheduled delivery
path.

```
Stellar RPC
│ getEvents()
Expand Down
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ The project enables developers to build reactive decentralized applications with
> **Listener service docs**:
> - [API Contract and Event Reference](listener/API_CONTRACT_EVENT_REFERENCE.md)
> - [API Usage Cookbook](listener/API_USAGE_COOKBOOK.md)
> - [API Sequence Diagrams](docs/api-sequence-diagrams.md) - notification request flow, event processing lifecycle, and scheduled delivery flow.
> - [Notification Failure Recovery](NOTIFICATION_FAILURE_RECOVERY.md) — retry lifecycle, configuration, and troubleshooting.
> [Notification Lifecycle](NOTIFICATION_LIFECYCLE.md) — creation, delivery, acknowledgment semantics, retries, and archival.
> [Notification Failure Recovery](NOTIFICATION_FAILURE_RECOVERY.md) — retry lifecycle, configuration, and troubleshooting.
Expand Down Expand Up @@ -205,6 +206,10 @@ Notify-Chain/

## Event Flow

For GitHub-rendered Mermaid sequence diagrams of the listener API and
notification delivery paths, see
[`docs/api-sequence-diagrams.md`](docs/api-sequence-diagrams.md).

### End-to-End Notification Flow

This is how a single on-chain action becomes a delivered notification:
Expand Down
154 changes: 154 additions & 0 deletions docs/api-sequence-diagrams.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
# API Sequence Diagrams

This document shows how NotifyChain moves notification data between callers,
Soroban contracts, the listener service, delivery targets, and API consumers.
The diagrams use Mermaid `sequenceDiagram` blocks so they render directly in
GitHub Markdown.

## Notification Request Flow

```mermaid
sequenceDiagram
autonumber
participant Caller as User or dApp
participant Contract as Soroban contract
participant Stellar as Stellar RPC
participant Subscriber as EventSubscriber
participant Dedup as EventDeduplicationService
participant Registry as EventRegistry
participant Delivery as DiscordNotificationService
participant Target as Discord or webhook target
participant API as Events API
participant Dashboard as Dashboard

Caller->>Contract: Invoke contract function
Contract->>Contract: Update on-chain state
Contract-->>Stellar: Emit typed contract event
Subscriber->>Stellar: getEvents(contract filter, cursor)
Stellar-->>Subscriber: Event batch and next cursor
Subscriber->>Subscriber: Validate payload and event filter
Subscriber->>Dedup: Check event id and contract address
Dedup-->>Subscriber: New event
Subscriber->>Registry: Store normalized display event
Subscriber->>Delivery: Format and send notification
Delivery->>Target: POST delivery payload
Target-->>Delivery: Delivery status
Subscriber->>Dedup: Record processed event and cursor
Dashboard->>API: GET /api/events
API->>Registry: Read recent events
Registry-->>API: Event feed
API-->>Dashboard: JSON event list
```

## Event Processing Lifecycle

```mermaid
sequenceDiagram
autonumber
participant Timer as Poll timer
participant Subscriber as EventSubscriber
participant Stellar as Stellar RPC
participant Validator as Event utils
participant Queue as EventProcessingQueue
participant Dedup as Persistent dedup
participant Registry as EventRegistry
participant Prefs as PreferenceStore
participant Delivery as Delivery service
participant Retry as NotificationRetryQueue

Timer->>Subscriber: Start poll cycle
Subscriber->>Stellar: getEvents() for each configured contract
Stellar-->>Subscriber: Raw Soroban events
Subscriber->>Validator: validateEventPayload() and matchesEventFilter()
Validator-->>Subscriber: Processable events
Subscriber->>Queue: Enqueue event, if queue is configured
Queue->>Subscriber: processEvent(event)
Subscriber->>Dedup: isDuplicate(event.id, contract)
alt Duplicate or reorg replay
Dedup-->>Subscriber: Duplicate
Subscriber->>Dedup: Record skipped duplicate
else New event
Dedup-->>Subscriber: Not seen
Subscriber->>Registry: addFromInput()
Subscriber->>Prefs: Check channel preferences
alt Channel enabled
Subscriber->>Delivery: sendEventNotification()
alt Delivery succeeds
Delivery-->>Subscriber: Success
else Delivery fails
Delivery-->>Subscriber: Failure
Subscriber->>Retry: Enqueue for retry
end
else Channel disabled
Prefs-->>Subscriber: Skip outbound delivery
end
Subscriber->>Dedup: recordProcessedEvent()
end
Subscriber->>Subscriber: Persist latest cursor and finish cycle
```

## Scheduled Notification Lifecycle

```mermaid
sequenceDiagram
autonumber
participant Client as API client
participant Server as events-server.ts
participant API as NotificationAPI
participant Repo as ScheduledNotificationRepository
participant DB as SQLite
participant Scheduler as NotificationScheduler
participant Delivery as Delivery service
participant Target as Discord or webhook target
participant Dashboard as Dashboard

Client->>Server: POST /api/schedule
Server->>API: Validate schedule request
API->>Repo: create(notification)
Repo->>DB: Insert PENDING row
DB-->>Repo: Scheduled id
Repo-->>API: Scheduled notification
API-->>Server: Created response
Server-->>Client: 201 Created

loop Background tick
Scheduler->>Repo: fetchAndLockPendingNotifications()
Repo->>DB: Atomic UPDATE PENDING to PROCESSING
DB-->>Repo: Locked due rows
Repo-->>Scheduler: Batch to execute
end

Scheduler->>Delivery: Send scheduled payload
Delivery->>Target: POST notification
alt Target accepts delivery
Target-->>Delivery: 2xx
Delivery-->>Scheduler: Success
Scheduler->>Repo: markCompleted()
Repo->>DB: Store execution log and COMPLETED status
else Target rejects or times out
Target-->>Delivery: Error
Delivery-->>Scheduler: Failure
Scheduler->>Repo: markFailedOrRetry()
Repo->>DB: Store retry metadata or FAILED status
end

Dashboard->>Server: GET /api/schedule/stats
Server->>Repo: Read scheduler statistics
Repo->>DB: Aggregate schedule states
DB-->>Repo: Counts and timestamps
Server-->>Dashboard: Scheduler status JSON
```

## Reading Guide

- Contract events are defined in
`contract/contracts/hello-world/src/base/events.rs` and
`Documents/Task Bounty/src/events.rs`.
- Event ingestion and cursor handling live in
`listener/src/services/event-subscriber.ts`.
- Persistent duplicate tracking lives in
`listener/src/services/event-deduplication-service.ts`.
- The public event and scheduler endpoints are implemented in
`listener/src/api/events-server.ts`.
- Dashboard clients consume the listener through `GET /api/events` and related
scheduler endpoints.