Skip to content

Commit 3876d24

Browse files
authored
Merge pull request Soroban-Pulse#769 from Faisat-Creator/main
feat: webhook retry queue, Prometheus monitoring, and supporting docs
2 parents 1c94522 + 66f3e0a commit 3876d24

6 files changed

Lines changed: 439 additions & 2 deletions

docker-compose.yml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,5 +35,21 @@ services:
3535
retries: 5
3636
start_period: 30s
3737

38+
prometheus:
39+
image: prom/prometheus:v2.52.0
40+
command:
41+
- "--config.file=/etc/prometheus/prometheus.yml"
42+
- "--storage.tsdb.path=/prometheus"
43+
- "--web.enable-lifecycle"
44+
ports:
45+
- "9090:9090"
46+
volumes:
47+
- ./prometheus.yml:/etc/prometheus/prometheus.yml:ro
48+
- promdata:/prometheus
49+
depends_on:
50+
app:
51+
condition: service_healthy
52+
3853
volumes:
3954
pgdata:
55+
promdata:

docs/contract-event-schemas.md

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
# Contract Event Schemas
2+
3+
Reference for Soroban contract event patterns and their XDR representations.
4+
5+
## Event Structure
6+
7+
Every event emitted by a Soroban contract is captured by SorobanPulse with the following fields:
8+
9+
| Field | Type | Description |
10+
|-------|------|-------------|
11+
| `contract_id` | `string` | Strkey-encoded contract address (`C…`) |
12+
| `event_type` | `string` | `contract`, `system`, or `diagnostic` |
13+
| `tx_hash` | `string` | Hex-encoded transaction hash |
14+
| `ledger` | `integer` | Ledger sequence number |
15+
| `ledger_closed_at` | `string` | RFC 3339 timestamp of ledger close |
16+
| `ledger_hash` | `string \| null` | Hex-encoded ledger hash (when tracked) |
17+
| `in_successful_call` | `boolean` | Whether the event came from a successful invocation |
18+
| `value` | `object` | Decoded event data (JSON) |
19+
| `topic` | `array \| null` | Array of XDR-encoded topic segments |
20+
| `tenant_id` | `string \| null` | Tenant identifier (multi-tenant deployments) |
21+
22+
## Common Contract Event Patterns
23+
24+
### Transfer Event
25+
26+
Emitted by SEP-41 compliant token contracts when tokens move between accounts.
27+
28+
**Topics:**
29+
```
30+
[Symbol("transfer"), Address(from), Address(to)]
31+
```
32+
33+
**Data:**
34+
```json
35+
{
36+
"amount": "1000000000",
37+
"asset": "native"
38+
}
39+
```
40+
41+
**Full example:**
42+
```json
43+
{
44+
"contract_id": "CDLZFC3SYJYDZT7K67VZ75HPJVIEUVNIXF47ZG2FB2RMQQVU2HHGCYSC",
45+
"event_type": "contract",
46+
"tx_hash": "3389e9f0f1a65f19736cacf544c2e825313e8447f569233bb8db39aa607c8889",
47+
"ledger": 5432100,
48+
"ledger_closed_at": "2026-06-29T12:00:00Z",
49+
"in_successful_call": true,
50+
"value": {
51+
"amount": "1000000000",
52+
"asset": "native"
53+
},
54+
"topic": [
55+
"AAAADwAAAAh0cmFuc2Zlcg==",
56+
"AAAABQAAAAAAAAAA...",
57+
"AAAABQAAAAAAAAAB..."
58+
]
59+
}
60+
```
61+
62+
### Mint Event
63+
64+
Emitted when new tokens are minted.
65+
66+
**Topics:**
67+
```
68+
[Symbol("mint"), Address(admin), Address(to)]
69+
```
70+
71+
**Data:**
72+
```json
73+
{
74+
"amount": "500000000"
75+
}
76+
```
77+
78+
### Burn Event
79+
80+
Emitted when tokens are destroyed.
81+
82+
**Topics:**
83+
```
84+
[Symbol("burn"), Address(from)]
85+
```
86+
87+
**Data:**
88+
```json
89+
{
90+
"amount": "250000000"
91+
}
92+
```
93+
94+
### Approve Event
95+
96+
Emitted when a spender allowance is set.
97+
98+
**Topics:**
99+
```
100+
[Symbol("approve"), Address(owner), Address(spender)]
101+
```
102+
103+
**Data:**
104+
```json
105+
{
106+
"amount": "10000000000",
107+
"expiration_ledger": 5532100
108+
}
109+
```
110+
111+
## XDR Format
112+
113+
Soroban contract events use XDR (External Data Representation) to encode topics and data. SorobanPulse decodes these into JSON but also exposes the raw base64-encoded XDR in the `topic` array.
114+
115+
### ScVal Types
116+
117+
The most common XDR `ScVal` types and their JSON equivalents:
118+
119+
| XDR Type | JSON representation |
120+
|----------|---------------------|
121+
| `ScvSymbol` | `"string_value"` |
122+
| `ScvI128` | `"123456789"` (string to avoid precision loss) |
123+
| `ScvU128` | `"123456789"` |
124+
| `ScvBool` | `true` / `false` |
125+
| `ScvAddress` | Strkey string (`G…` or `C…`) |
126+
| `ScvBytes` | Base64-encoded string |
127+
| `ScvMap` | JSON object |
128+
| `ScvVec` | JSON array |
129+
130+
### Decoding Topics Manually
131+
132+
Topics are base64-encoded XDR `ScVal` values. To decode them:
133+
134+
```bash
135+
# Decode a single topic segment
136+
echo "AAAADwAAAAh0cmFuc2Zlcg==" | base64 -d | xxd
137+
138+
# Using the Stellar SDK (JavaScript)
139+
const xdr = StellarSdk.xdr;
140+
const val = xdr.ScVal.fromXDR(Buffer.from(base64Topic, 'base64'));
141+
console.log(val.value().toString()); // "transfer"
142+
```
143+
144+
```rust
145+
// Using stellar-xdr crate
146+
use stellar_xdr::curr::{ScVal, ReadXdr};
147+
148+
let bytes = base64::decode(topic_b64).unwrap();
149+
let val = ScVal::from_xdr_base64(topic_b64, stellar_xdr::curr::Limits::none()).unwrap();
150+
```
151+
152+
### Topic Filtering
153+
154+
SorobanPulse indexes `topic[0]` as `topic_0_sym` for fast equality filtering. Use the `topic_0` query parameter to filter by event name:
155+
156+
```bash
157+
# Fetch all transfer events for a contract
158+
GET /v1/events?contract_id=C...&topic_0=transfer
159+
160+
# Fetch all mint and burn events
161+
GET /v1/events?contract_id=C...&topic_0=mint
162+
GET /v1/events?contract_id=C...&topic_0=burn
163+
```
164+
165+
## System Events
166+
167+
System events are emitted by the Stellar network itself rather than user contracts.
168+
169+
| `event_type` | Trigger |
170+
|---|---|
171+
| `system` | Protocol-level operations (e.g., fee bumps) |
172+
| `diagnostic` | Debug events emitted during contract execution |
173+
174+
Filter out diagnostic events in most production integrations:
175+
```bash
176+
GET /v1/events?event_type=contract
177+
```
178+
179+
## Event Data Size Limits
180+
181+
- Maximum `event_data` JSON size: `MAX_EVENT_DATA_BYTES` (default 64 KiB)
182+
- Events exceeding this limit are logged and skipped
183+
- The `soroban_pulse_events_oversized_total` counter tracks skipped events
184+
185+
## Versioning
186+
187+
The event schema is tied to the Soroban protocol version. Breaking changes are announced in `CHANGELOG.md` and the `schema_version` column in the database tracks the protocol version in effect when each event was stored.

0 commit comments

Comments
 (0)