feat(contracts): add recurring stream auto-renew support - #912
feat(contracts): add recurring stream auto-renew support#912scarface-dev1 wants to merge 1 commit into
Conversation
Add enable_auto_renew and renew_stream methods to the StellarStreamContract that allow senders to configure automatic stream renewal with a max renewal count. When a stream completes or is fully claimed, the sender can trigger renewal which creates a fresh stream with the same parameters, deducts the escrow amount from the sender, and emits StreamRenewed and StreamCreated events. Closes ritik4ever#699 🤖 Generated with Codebuff Co-Authored-By: Codebuff <noreply@codebuff.com>
|
@scarface-dev1 is attempting to deploy a commit to the ritik4ever's projects Team on Vercel. A member of the Team first needs to authorize it. |
|
@scarface-dev1 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! 🚀 |
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 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 |
What it fixes
Adds contract-level support for recurring payment streams (auto-renew), as requested in #699.
Root cause
The Soroban smart contract (
StellarStreamContract) only supported one-shot stream lifecycles — once a stream completed or was fully claimed, it was done. There was no mechanism for a sender to configure automatic renewal, forcing manual recreation of identical streams for recurring payment use cases.The fix
Changes to
contracts/src/lib.rsExtended the
Streamstruct with three new fields:auto_renew: bool— whether the stream is configured for auto-renewalmax_renewals: u32— maximum number of times the stream may be renewedrenewals_completed: u32— how many renewals have occurred so farAdded
StreamRenewedevent struct following the existing event schema pattern (mandatorystream_id,actor,timestampfields + event-specific fieldsold_stream_id,new_stream_id,renewals_remaining).Added
enable_auto_renewmethod — sender-only, requires auth, setsauto_renew = trueandmax_renewalson the stream.Added
renew_streammethod — performs these steps:auto_renewis enabled andrenewals_completed < max_renewalsend_time) or fully claimed (claimed_amount >= total_amount)total_amountfrom sender into the contractrenewals_completedon the old streamStreamCreatedfor the new stream andStreamRenewedfor the renewal eventFixed duplicate imports — merged two overlapping
use soroban_sdk::{...}lines into one.Changes to
contracts/src/test.rsAdded 8 new tests covering:
test_enable_auto_renew— verifies auto-renew fields are set correctlytest_enable_auto_renew_wrong_sender— panics on unauthorized sendertest_renew_stream_after_completion— renew after time expiry, validates new stream paramstest_renew_stream_after_full_claim— renew after full claimtest_renew_stream_without_enable— panics when auto-renew not configuredtest_renew_stream_max_renewals_enforced— panics after exhausting renewalstest_renew_stream_before_completion— panics when stream is still activetest_renew_stream_insufficient_balance— panics when sender lacks fundsWhy this approach
Streamstruct rather than creating a separateRecurringConfigstorage key — keeps the data model flat and avoids extra storage lookups.StreamCreated/StreamTransferredconventions. Method signatures followpause_stream/resume_streampatterns (sender + auth).renew_streammethod requires the sender to call it (rather than auto-executing on claim) — this avoids unexpected token deductions and keeps the sender in control.claim()was rejected because it would couple renewal logic with claim logic and could cause confusing panics mid-claim.Trade-offs
bool+ 2xu32) and the methods reuse existing helper functions.Streamrecord now stores 9 extra bytes. For the MVP scale this is negligible.renew_stream()call. This is a deliberate trade-off for predictability — a future enhancement could add aclaim_and_renew()convenience method.How it was tested
contracts/src/test.rs(all follow existing test patterns usingEnv::default(),mock_all_auths(), andStellarStreamContractClient)cargo check --libverified the contract compilesFollow-up
claim_with_renew()convenience method that atomically claims and renews in one transactionenable_auto_renew/renew_streaminto the REST API and indexer event pipelineCloses #699
🤖 Generated with Codebuff
Co-Authored-By: Codebuff noreply@codebuff.com