Skip to content

feat: implement StreamCreated handler - #43

Merged
pragmaticAweds merged 3 commits into
Fundable-Protocol:devfrom
d3vobed:feat/stream-created-handler
Jun 29, 2026
Merged

pragmaticAweds merged 3 commits into
Fundable-Protocol:devfrom
d3vobed:feat/stream-created-handler

Conversation

@d3vobed

@d3vobed d3vobed commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Summary

Implements the StreamCreated event handler for the payment streams domain as specified in #34.

Changes

  • Parse: parseStreamCreatedPayload validates the event topic matches StreamCreated and extracts the structured payload (streamId, sender, recipient, amount, startTime, endTime)
  • Map: mapStreamCreatedToRecord combines the parsed payload with event identity metadata into a StreamRecord
  • Identity: getEventIdentity produces a deterministic string from contractId:ledger:txHash:eventIndex for idempotency checks
  • Handler: handleStreamCreated composes the above into a single call, returning both the stream record and identity

Testing

  • Payload parsing with valid and invalid topics
  • Identity derivation and uniqueness across all identity fields
  • Record mapping correctness
  • Handler idempotency (same input → same output)
  • Multiple stream ID handling

Verification

  • bun run indexer:type-check
  • bun run indexer:test ✅ (10 tests)
  • bun run indexer:lint

Closes #34

Summary by CodeRabbit

  • New Features
    • Added stream-created event handling to produce stream records plus deterministic event identity.
    • Introduced stream-created payload/event and stream record types, and re-exported handler utilities and topic constant for integration.
  • Bug Fixes
    • Improved robustness with strict payload validation and descriptive errors for malformed topics/data and missing/invalid fields.
    • Ensured idempotent outputs for identical inputs and different outputs when the embedded stream ID changes.
  • Tests
    • Added Vitest coverage for parsing, identity generation, record mapping, and handler behavior.

- Add StreamCreated event handler for parsing Soroban events
- Map event payload to Stream record with event identity tracking
- Add deterministic event identity for idempotency checks
- Add mocked payload tests covering:
  - Payload parsing and validation
  - Event identity derivation
  - Record mapping
  - Handler idempotency
  - Multiple stream ID handling
@drips-wave

drips-wave Bot commented Jun 26, 2026

Copy link
Copy Markdown

@d3vobed 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! 🚀

Learn more about application limits

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

📝 Walkthrough

Walkthrough

Adds StreamCreated event types, payload validation, identity generation, record mapping, handler composition, package exports, and Vitest coverage for parsing and handler behavior.

Changes

StreamCreated handler

Layer / File(s) Summary
Event contract and parsing
indexer/streams/src/handlers/types.ts, indexer/streams/src/handlers/streamCreated.ts, indexer/streams/src/handlers/streamCreated.test.ts
StreamCreatedEvent and StreamRecord are defined, STREAM_CREATED_TOPIC and StreamCreatedPayload are added, and parseStreamCreatedPayload() validates the topic and payload fields; tests cover valid parsing and validation failures.
Identity and record mapping
indexer/streams/src/handlers/streamCreated.ts, indexer/streams/src/handlers/streamCreated.test.ts
getEventIdentity() builds a deterministic identity from contract, ledger, transaction hash, and event index, and mapStreamCreatedToRecord() converts payload data and event metadata into a stream record; tests cover identity stability and record field mapping.
Handler composition and exports
indexer/streams/src/handlers/streamCreated.ts, indexer/streams/src/handlers/index.ts, indexer/streams/src/index.ts, indexer/streams/src/handlers/streamCreated.test.ts
handleStreamCreated() combines parsing, mapping, and identity generation, and the stream index modules re-export the handler API; tests cover the composed return value, repeated-input behavior, and differing stream IDs.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

I hopped through payloads, thump thump thump,
Found stream IDs in a tidy lump.
JSON carrots, crisp and bright,
Identities now line up right.
Ears up! The handler sings tonight 🐰

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title is concise and accurately names the main change: implementing the StreamCreated handler.
Description check ✅ Passed The PR description covers summary, changes, testing, and verification, though some template sections are omitted.
Linked Issues check ✅ Passed The changes satisfy #34 by parsing StreamCreated, mapping to records, recording identity, adding idempotency, and testing the handler.
Out of Scope Changes check ✅ Passed The diff stays within indexer/streams handlers, exports, types, and tests, with no obvious unrelated additions.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 ESLint

If the error stems from missing dependencies, add them to the package.json file. For unrecoverable errors (e.g., due to private dependencies), disable the tool in the CodeRabbit configuration.

ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration.


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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@indexer/streams/src/handlers/streamCreated.ts`:
- Around line 22-31: The StreamCreated handler currently trusts a type cast
after JSON.parse, so invalid shapes can still produce a malformed StreamRecord.
Update the logic in streamCreated.ts, around the parsed payload handling in the
StreamCreatedPayload flow, to perform a real runtime validation of the parsed
object before building the return value. Use the existing streamCreated event
handler path to reject or guard against missing or wrong-typed streamId, sender,
recipient, amount, startTime, and endTime fields, and only return the record
once validation passes.
🪄 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

Run ID: cc30f585-3708-4e5f-b38f-f39951ab7f30

📥 Commits

Reviewing files that changed from the base of the PR and between bcfa08d and 6e5b3c8.

📒 Files selected for processing (4)
  • indexer/streams/src/handlers/streamCreated.test.ts
  • indexer/streams/src/handlers/streamCreated.ts
  • indexer/streams/src/handlers/types.ts
  • indexer/streams/src/index.ts

Comment thread indexer/streams/src/handlers/streamCreated.ts Outdated
Add runtime validation for all required fields (streamId, sender,
recipient, amount, startTime, endTime) per PR review feedback.
Previously relied solely on TypeScript type assertion which does not
enforce shape at runtime. Now validates field presence, type, and
non-empty constraint with clear error messages.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 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 `@indexer/streams/src/handlers/streamCreated.test.ts`:
- Around line 64-99: The negative coverage for parseStreamCreatedPayload is
missing a valid JSON payload with the wrong top-level shape, so add tests in
streamCreated.test for a case like null and ideally another non-object JSON
value. Harden parseStreamCreatedPayload in streamCreated to validate that
JSON.parse returns a non-null object before reading fields, and throw the same
intended validation error instead of letting a raw TypeError escape. Keep the
existing field validation path for streamId, amount, and recipient after the
shape check.
🪄 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

Run ID: 78a38b2b-57d1-4a94-b612-8ab650892627

📥 Commits

Reviewing files that changed from the base of the PR and between 6e5b3c8 and 23ce54e.

📒 Files selected for processing (2)
  • indexer/streams/src/handlers/streamCreated.test.ts
  • indexer/streams/src/handlers/streamCreated.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • indexer/streams/src/handlers/streamCreated.ts

Comment thread indexer/streams/src/handlers/streamCreated.test.ts
@pragmaticAweds

Copy link
Copy Markdown
Contributor

Hi Chief @d3vobed

Thank you for your awesome contribution, however after analyzing your implementation, there is a minor fixes and merge conflict to be fixed. Kindly fix them to merge your PR asap.

Also do not forget to use fundable.finance to offramp.

Resolved conflicts in:
- indexer/streams/src/index.ts
- indexer/streams/src/handlers/types.ts
- indexer/streams/src/handlers/index.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
indexer/streams/src/index.ts (1)

12-17: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove the duplicate StreamCreated re-export.
./handlers/index.js already exposes these symbols, so this barrel just repeats the same public API and adds another place for the export surface to drift.

🤖 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 `@indexer/streams/src/index.ts` around lines 12 - 17, The barrel export in
index.ts is duplicating the StreamCreated API already re-exported by
handlers/index.js. Remove the explicit re-export of handleStreamCreated,
parseStreamCreatedPayload, and STREAM_CREATED_TOPIC from streamCreated.js, and
keep the single source of truth through the handlers/index.js export surface so
the public API stays centralized.
🤖 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.

Nitpick comments:
In `@indexer/streams/src/index.ts`:
- Around line 12-17: The barrel export in index.ts is duplicating the
StreamCreated API already re-exported by handlers/index.js. Remove the explicit
re-export of handleStreamCreated, parseStreamCreatedPayload, and
STREAM_CREATED_TOPIC from streamCreated.js, and keep the single source of truth
through the handlers/index.js export surface so the public API stays
centralized.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2ea405df-3479-4150-9887-e2748815cc69

📥 Commits

Reviewing files that changed from the base of the PR and between 23ce54e and a7ac237.

📒 Files selected for processing (3)
  • indexer/streams/src/handlers/index.ts
  • indexer/streams/src/handlers/types.ts
  • indexer/streams/src/index.ts
🚧 Files skipped from review as they are similar to previous changes (1)
  • indexer/streams/src/handlers/types.ts

@d3vobed

d3vobed commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Hey @pragmaticAweds, Completed the fix and sure i will check the fundable app

@pragmaticAweds
pragmaticAweds merged commit 43f39f6 into Fundable-Protocol:dev Jun 29, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Implement StreamCreated handler

3 participants