Skip to content

[Spike Priority][Enhancement] Batch Stream Creation in Factory #48

Description

@Jaydbrown

Context & Problem
When a sender needs to distribute funds to multiple recipients—such as running payroll for a team, paying out grants, or airdropping vested tokens—they are currently forced to call create_stream individually for each recipient.
This results in multiple network transactions, meaning higher total gas fees, slow execution, and severe UX friction (requiring the user to sign a separate wallet approval for every single stream).

Proposed Solution
Introduce a create_batch_streams function in DripFactory. This will accept an array/vector of stream configurations and execute them in a single transaction. We can reuse the existing core logic of create_stream to ensure consistency in validation and state management.

Edge Cases & Considerations

  • Gas Limits: Soroban has instruction and gas limits. We need to document or enforce a maximum batch size (e.g., 50-100 streams) so the transaction doesn't hit limits and fail mid-execution.
  • Partial Failures: If one stream configuration in the batch is invalid, the entire transaction should revert. We shouldn't leave the contract in a partially executed state.
  • Event Emitting: Ensure that events are still emitted correctly for each individual stream created so the indexer doesn't break.

Suggested Implementation

#[contractimpl]
impl DripFactory {
    pub fn create_batch_streams(
        env: Env,
        requests: Vec<BatchStreamRequest>,
        clawback: bool,
    ) -> Result<Vec<u64>, Error> {
        let mut stream_ids = Vec::new(&env);
        
        for request in requests.iter() {
            // Re-use existing create_stream validation and logic
            let request = request.unwrap();
            let stream_id = Self::create_stream(
                env.clone(),
                request.recipient,
                request.token,
                request.deposit,
                request.rate_per_sec,
                request.start_time,
                request.end_time,
                clawback
            )?;
            
            stream_ids.push_back(stream_id);
        }
        
        Ok(stream_ids)
    }
}

#[contracttype]
pub struct BatchStreamRequest {
    pub recipient: Address,
    pub token: Address,
    pub deposit: i128,
    pub rate_per_sec: i128,
    pub start_time: u64,
    pub end_time: u64,
}

Acceptance Criteria

  • Accepts a Vec<BatchStreamRequest> and loops through them to create streams.
  • Uses the same validation constraints as individual stream creation.
  • Returns a list of generated stream IDs.
  • A test script verifying gas usage for batches of 10, 50, and 100 streams to identify upper bounds.

Metadata

Metadata

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions