Problem
preview_payout(id, amount) returns one amount per direct recipient:
pub fn preview_payout(env: Env, id: u64, amount: i128) -> Result<Vec<i128>, Error> {
...
Ok(amounts(&env, &split, amount))
}
For a split whose recipients include Recipient::Split(child), the returned vector shows the lump sum routed to the child, not where that money actually lands. It also returns a bare Vec<i128> with no recipient identifiers, so the caller has to zip it against get_split positionally and hope the ordering holds.
Why this matters
Composable routing trees are a headline feature ("a project split that feeds team splits"). But the one function whose entire purpose is "show me what will happen before I sign" stops at the first level. A payer looking at a two-level tree sees "8,000 goes to split #7" and cannot tell whether that means 8,000 to one person or 500 each to sixteen people.
That undermines:
Suggested fix
Add a deep variant, for example preview_payout_deep(id, amount) -> Vec<(Address, i128)>, that recurses through child splits and returns leaf accounts with final amounts. Returning the address alongside the amount also fixes the positional-zip fragility.
Requirements:
- Bound the recursion depth and document the cap (coordinate with the cycle-rejection work, which needs a depth bound anyway).
- Preserve the exact rounding behaviour of
amounts() at every level, including dust to the last recipient, so preview matches actual (extend the preview_matches_actual_payout test to nested cases).
- Aggregate correctly if the same address appears as a leaf under multiple branches.
Acceptance criteria
Problem
preview_payout(id, amount)returns one amount per direct recipient:For a split whose recipients include
Recipient::Split(child), the returned vector shows the lump sum routed to the child, not where that money actually lands. It also returns a bareVec<i128>with no recipient identifiers, so the caller has to zip it againstget_splitpositionally and hope the ordering holds.Why this matters
Composable routing trees are a headline feature ("a project split that feeds team splits"). But the one function whose entire purpose is "show me what will happen before I sign" stops at the first level. A payer looking at a two-level tree sees "8,000 goes to split #7" and cannot tell whether that means 8,000 to one person or 500 each to sixteen people.
That undermines:
Suggested fix
Add a deep variant, for example
preview_payout_deep(id, amount) -> Vec<(Address, i128)>, that recurses through child splits and returns leaf accounts with final amounts. Returning the address alongside the amount also fixes the positional-zip fragility.Requirements:
amounts()at every level, including dust to the last recipient, so preview matches actual (extend thepreview_matches_actual_payouttest to nested cases).Acceptance criteria