feat(contract): add preview_payout_deep for recursive leaf resolution - #318
Open
MarcusDavidG wants to merge 4 commits into
Open
feat(contract): add preview_payout_deep for recursive leaf resolution#318MarcusDavidG wants to merge 4 commits into
MarcusDavidG wants to merge 4 commits into
Conversation
Contributor
|
|
…utary-protocol#261) - Add checkTrustlines() in trustlines.ts: checks every leaf Account recipient (including those in nested Recipient::Split children) for a trustline to the selected token via Horizon account lookups. - XLM (native SAC) is always treated as receivable – no Horizon call. - Results are cached in-memory for 30 s; the check is debounced 400 ms in the UI so it does not fire an RPC call on every keystroke. - PaySplit shows a red blocking warning with the exact address(es) when a confirmed missing trustline is found, and disables the Pay button. - When a Horizon lookup errors the check degrades gracefully: an inconclusive notice is shown but the Pay button stays enabled. - Both warning and notice messages are fully translated in en/vi. - 15 unit tests cover: XLM skip, all-ok, missing trustline, Horizon error, network error, caching, recursive nested split resolution, deduplication, and circular-split guard.
…tributary-protocol#265) Adds preview_payout_deep(id, amount) -> Result<Vec<(Address, i128)>, Error> to the splitter contract. Contract changes (contracts/splitter/src/lib.rs): - New public method preview_payout_deep(env, id, amount) on Splitter. Returns (Address, i128) pairs for every leaf account the payment would ultimately reach, resolving Recipient::Split children recursively. - New private helper resolve_deep(env, id, amount, depth, out) does the recursive walk using the same amounts() helper as pay/distribute, so rounding (dust to last recipient) is bit-for-bit identical to an actual payment. - Duplicate leaf addresses from different branches are aggregated into a single entry. - New constant MAX_PREVIEW_DEPTH = 8. The guard fires when depth exceeds the cap and returns Error::BadChildSplit, matching the existing error used for invalid child split references. SDK changes (sdk/src/index.ts): - Added preview_payout_deep to the Client interface with return type Result<Array<readonly [string, i128]>>. - Added corresponding fromJSON entry. App changes (app/src/lib/tributary.ts): - Added previewPayoutDeep() helper that calls preview_payout_deep via the SDK and returns { address, amount }[] for use in Pay tab / tree views. Docs (README.md): - Added preview_payout_deep row to the Contract API table. Tests (contracts/splitter/src/test.rs) — 8 new tests, all pass: - deep_preview_flat_split_matches_shallow_preview - deep_preview_two_level_tree (preview matches actual pay+distribute) - deep_preview_three_level_tree (preview matches actual pay+distribute) - deep_preview_aggregates_shared_leaf_address - deep_preview_dust_rounding_matches_actual_pay - deep_preview_rejects_non_positive_amount - deep_preview_rejects_unknown_split - deep_preview_depth_cap_is_enforced (verifies both the cap and the boundary)
MarcusDavidG
force-pushed
the
feat/preview-payout-deep-265
branch
from
July 22, 2026 05:15
589f615 to
9816124
Compare
Spagero763
enabled auto-merge (squash)
July 27, 2026 05:41
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #265
What this does
Adds
preview_payout_deep(id, amount) -> Result<Vec<(Address, i128)>, Error>to the splitter contract. This is the deep variant ofpreview_payoutthat resolves everyRecipient::Splitchild recursively down to leafRecipient::Accountaddresses.Contract (
contracts/splitter/src/lib.rs)New public method:
preview_payout_deep(Address, i128)pairs — leaf address alongside its final amount. No more positional-zip againstget_split.Recipient::Splitchildren by loading each child split and applyingamounts()at each level.pay: uses the existingamounts()helper at every level, so dust-to-last-recipient behaviour is bit-for-bit identical to an actual payment.MAX_PREVIEW_DEPTH = 8. Calls that would exceed the cap returnError::BadChildSplit. At 32 recipients per split that covers trees with millions of theoretical leaf slots — far more than any real-world routing tree.New private helper:
resolve_deepRecursive implementation with an injected
depthcounter. Separated from the public entry point so the guard and accumulation logic stay readable.SDK (
sdk/src/index.ts)preview_payout_deepadded to theClientinterface with return typeResult<Array<readonly [string, i128]>>.fromJSONmap.App (
app/src/lib/tributary.ts)previewPayoutDeep(id, amount)helper wraps the SDK call and returns{ address: string; amount: bigint }[]for easy consumption by the Pay tab and the tree visualisation (Add a nested-split tree visualization #75).Docs (
README.md)Added
preview_payout_deeprow to the Contract API table.Tests (8 new, all pass — 49 total)
deep_preview_flat_split_matches_shallow_previewpreview_payout, paired with addressesdeep_preview_two_level_treepay+distributedeep_preview_three_level_treepay+distributechaindeep_preview_aggregates_shared_leaf_addressdeep_preview_dust_rounding_matches_actual_paydeep_preview_rejects_non_positive_amountInvalidAmountfor 0 and negative inputsdeep_preview_rejects_unknown_splitSplitNotFoundfor non-existent split iddeep_preview_depth_cap_is_enforcedBadChildSplit; 8-deep succeeds and sums to input amountAcceptance criteria
MAX_PREVIEW_DEPTH = 8in lib.rs doc-commentpreviewPayoutDeepapp helper ready to use