Skip to content

fix(vesting): surface all schedules per recipient in UI (#303) - Vest…#317

Merged
zachyo merged 1 commit into
soropad:masterfrom
blockchainrafik:fix/303-vesting-multi-schedule
Jun 30, 2026
Merged

fix(vesting): surface all schedules per recipient in UI (#303) - Vest…#317
zachyo merged 1 commit into
soropad:masterfrom
blockchainrafik:fix/303-vesting-multi-schedule

Conversation

@blockchainrafik

Copy link
Copy Markdown

Closes #303

Summary

This PR updates the vesting UI to fully support multiple vesting schedules per recipient.

Although the vesting contract has supported indexed schedules since Wave 5 (#40), the frontend always assumed a single schedule (index = 0). As a result, recipients with multiple grants (for example, follow-on allocations after a completed vesting period) could only view and claim their first schedule.

The UI now discovers every schedule for a recipient using get_schedule_count() and renders each schedule independently, ensuring all vesting grants are visible and claimable.


Problem

The vesting contract stores schedules using (Address, index) and exposes:

  • get_schedule_count(recipient)
  • get_schedule(recipient, index)
  • release(recipient, index)
  • revoke(recipient, index)

The frontend ignored these indexed APIs and always operated on the default schedule (index = 0).

This caused several issues:

  • Only the first vesting schedule was displayed.
  • Additional schedules were invisible in the dashboard.
  • Users could not claim tokens from later schedules.
  • Admin release/revoke flows could only target the first schedule.

Changes

ClaimVesting.tsx

  • Calls fetchScheduleCount() when looking up a recipient.
  • Fetches all schedules (0..count-1) in parallel.
  • Renders one vesting card per schedule.
  • Displays an independent progress bar and claimable amount for each schedule.
  • Each Release button passes the correct scheduleIndex to buildReleaseTx().

PersonalDashboard.tsx

  • Replaces:
vestingSchedule: VestingScheduleInfo | null

with:

vestingSchedules: VestingScheduleInfo[]
  • Updates the vesting lookup flow to:
    • Fetch the schedule count.
    • Fetch every indexed schedule in parallel.
    • Store all schedules for rendering.

VestingSection.tsx

  • Maps over vestingSchedules.
  • Renders one VestingCard per schedule instead of assuming a single schedule.

VestingCard.tsx

  • Adds a schedule badge when multiple schedules exist.
  • Displays labels such as:
Schedule 2 of 4

to distinguish multiple vesting grants.

VestingForm.tsx

Adds an optional Schedule Index field to both:

  • Release form
  • Revoke form

This allows administrators to target a specific schedule for a recipient.

useSoroban.ts

  • Exposes fetchVestingScheduleCount().
  • Threads scheduleIndex?: number through fetchVestingSchedule().

useTransactionSimulator.ts

  • Threads scheduleIndex?: number through:
    • checkVestingRelease()
    • checkVestingRevoke()

The underlying simulator already supported indexed schedules; this change exposes that functionality through the hook.


Result

After these changes:

  • ✅ All vesting schedules are discovered automatically.
  • ✅ Every schedule is displayed independently.
  • ✅ Users can claim tokens from any schedule.
  • ✅ Dashboard and lookup views support multiple grants.
  • ✅ Admin release and revoke actions can target any indexed schedule.
  • ✅ The frontend no longer assumes schedule 0.

The UI is now fully aligned with the indexed vesting functionality already supported by the smart contract.

… - VestingSection/PersonalDashboard: fetch schedule count then load all schedules in parallel; store as VestingScheduleInfo[] instead of a single nullable value - VestingCard: show 'Schedule N of M' badge when scheduleCount > 1 - ClaimVesting: iterate 0..count, render one ScheduleCard per schedule, each with its own progress bar and Claim button passing the correct index to release() - VestingForm (release + revoke): add optional Schedule Index field so admins can target any schedule per recipient - useSoroban: expose fetchVestingScheduleCount and thread scheduleIndex through fetchVestingSchedule - useTransactionSimulator: thread scheduleIndex through checkVestingRelease and checkVestingRevoke Closes soropad#303
@drips-wave

drips-wave Bot commented Jun 30, 2026

Copy link
Copy Markdown

@blockchainrafik 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

@zachyo zachyo merged commit ebeaadb into soropad:master Jun 30, 2026
1 of 2 checks 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.

Vesting UI: surface multiple schedules per recipient (contract already supports it)

3 participants