feat(contracts): add structured event schema with actor+timestamp - #827
Conversation
- Add actor and timestamp base fields to all 8 event structs (StreamCreated, StreamClaimed, StreamCanceled, StreamPaused, StreamResumed, StreamTransferred, ClawbackExecuted) - Add new StreamCompleted event emitted when a stream is fully drained - Update all env.events().publish() calls with new fields - Add refunded_amount field to StreamCanceled - Add claimed_amount field to StreamClaimed - Update indexer to parse actor field from all event types - Add Completed and Clawback handlers to indexer processEvent() - Create docs/CONTRACT_EVENTS.md with full event schema reference
|
@ezekielcyclops-ux is attempting to deploy a commit to the ritik4ever's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@ezekielcyclops-ux Great news! 🎉 Based on an automated assessment of this PR, the linked Wave issue(s) no longer count against your application limits. You can now already apply to more issues while waiting for a review of this PR. Keep up the great work! 🚀 |
📝 WalkthroughWalkthroughThe contract event schemas now share ChangesStructured contract events
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant StellarStreamContract
participant StellarRPC
participant Indexer
participant stream_events
StellarStreamContract->>StellarRPC: Emit structured event
StellarRPC->>Indexer: Read event topics and values
Indexer->>stream_events: Persist mapped event history
Possibly related PRs
Suggested reviewers: 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Actionable comments posted: 3
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@backend/src/services/indexer.ts`:
- Around line 251-254: Update the Claimed event handling near the
recordEventWithDb call to pass value.claimed_amount as the canonical positional
amount instead of value.amount, while preserving value.claimed_amount in the
claimed_amount metadata field and the existing actor/recipient fallback.
In `@docs/CONTRACT_EVENTS.md`:
- Around line 193-204: Update the cancel entry in the Event Ordering Guarantees
section to state that a successful first-time cancel emits exactly one
StreamCanceled event, while canceling an already-canceled stream returns
successfully without publishing another event.
- Around line 16-18: Add the text language identifier to the fenced code block
containing the `(Symbol("Stream"), Symbol("<EventName>"))` example, changing the
opening fence to use ```text while preserving the example content.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: b180bd78-1cb2-421b-b371-789b1f5a1633
📒 Files selected for processing (3)
backend/src/services/indexer.tscontracts/src/lib.rsdocs/CONTRACT_EVENTS.md
| // actor == recipient for Claimed events | ||
| value.actor ?? value.recipient, | ||
| value.amount, | ||
| { claimed_amount: value.claimed_amount }, |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Persist claimed_amount in the canonical amount column.
Line 253 passes value.amount, while the new claim schema provides value.claimed_amount on Line 254. Because recordEventWithDb stores the positional amount field directly and converts undefined to NULL, claim history will lose its canonical amount even though metadata contains it.
Proposed fix
- value.amount,
+ value.claimed_amount,📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| // actor == recipient for Claimed events | |
| value.actor ?? value.recipient, | |
| value.amount, | |
| { claimed_amount: value.claimed_amount }, | |
| // actor == recipient for Claimed events | |
| value.actor ?? value.recipient, | |
| value.claimed_amount, | |
| { claimed_amount: value.claimed_amount }, |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@backend/src/services/indexer.ts` around lines 251 - 254, Update the Claimed
event handling near the recordEventWithDb call to pass value.claimed_amount as
the canonical positional amount instead of value.amount, while preserving
value.claimed_amount in the claimed_amount metadata field and the existing
actor/recipient fallback.
| ``` | ||
| (Symbol("Stream"), Symbol("<EventName>")) | ||
| ``` |
There was a problem hiding this comment.
📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win
Add a language identifier to the fenced block.
This violates MD040 and can fail the documentation lint job.
Proposed fix
-```
+```text
(Symbol("Stream"), Symbol("<EventName>"))</details>
<!-- suggestion_start -->
<details>
<summary>📝 Committable suggestion</summary>
> ‼️ **IMPORTANT**
> Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
```suggestion
🧰 Tools
🪛 markdownlint-cli2 (0.23.1)
[warning] 16-16: Fenced code blocks should have a language specified
(MD040, fenced-code-language)
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/CONTRACT_EVENTS.md` around lines 16 - 18, Add the text language
identifier to the fenced code block containing the `(Symbol("Stream"),
Symbol("<EventName>"))` example, changing the opening fence to use ```text while
preserving the example content.
Source: Linters/SAST tools
| ## Event Ordering Guarantees | ||
|
|
||
| Within a single transaction: | ||
|
|
||
| - `create_stream` → exactly one `StreamCreated` | ||
| - `create_split_stream` → exactly one `StreamCreated` per child stream, in allocation order | ||
| - `claim` → exactly one `StreamClaimed`, followed by at most one `StreamCompleted` (only when the stream is fully drained) | ||
| - `cancel` → exactly one `StreamCanceled` | ||
| - `pause_stream` → exactly one `StreamPaused` | ||
| - `resume_stream` → exactly one `StreamResumed` | ||
| - `transfer_stream` → exactly one `StreamTransferred` | ||
| - `clawback` → exactly one `ClawbackExecuted` (only when `actual_clawback > 0`) |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Qualify the cancel ordering guarantee.
Line 200 says every cancel emits an event, but an already-canceled stream returns without publishing one. Document this as a successful first-time cancellation.
Proposed fix
-- `cancel` → exactly one `StreamCanceled`
+- successful first-time `cancel` → exactly one `StreamCanceled`📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| ## Event Ordering Guarantees | |
| Within a single transaction: | |
| - `create_stream` → exactly one `StreamCreated` | |
| - `create_split_stream` → exactly one `StreamCreated` per child stream, in allocation order | |
| - `claim` → exactly one `StreamClaimed`, followed by at most one `StreamCompleted` (only when the stream is fully drained) | |
| - `cancel` → exactly one `StreamCanceled` | |
| - `pause_stream` → exactly one `StreamPaused` | |
| - `resume_stream` → exactly one `StreamResumed` | |
| - `transfer_stream` → exactly one `StreamTransferred` | |
| - `clawback` → exactly one `ClawbackExecuted` (only when `actual_clawback > 0`) | |
| ## Event Ordering Guarantees | |
| Within a single transaction: | |
| - `create_stream` → exactly one `StreamCreated` | |
| - `create_split_stream` → exactly one `StreamCreated` per child stream, in allocation order | |
| - `claim` → exactly one `StreamClaimed`, followed by at most one `StreamCompleted` (only when the stream is fully drained) | |
| - successful first-time `cancel` → exactly one `StreamCanceled` | |
| - `pause_stream` → exactly one `StreamPaused` | |
| - `resume_stream` → exactly one `StreamResumed` | |
| - `transfer_stream` → exactly one `StreamTransferred` | |
| - `clawback` → exactly one `ClawbackExecuted` (only when `actual_clawback > 0`) |
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@docs/CONTRACT_EVENTS.md` around lines 193 - 204, Update the cancel entry in
the Event Ordering Guarantees section to state that a successful first-time
cancel emits exactly one StreamCanceled event, while canceling an
already-canceled stream returns successfully without publishing another event.
What changed
Testing done
Related issues
Closes #
Checklist
closes #596
Summary by CodeRabbit
New Features
Bug Fixes
Documentation