feat(trade): warn of launch penalty on sell confirmation - #853
Open
Ajibose wants to merge 1 commit into
Open
Conversation
…org#825) Detects when a sell falls within a key's 7-day launch window using its createdAtLedger and launchPenaltyBps (from the key detail API) and shows a prominent warning plus an updated fee breakdown with the penalty deducted and net proceeds, so holders can acknowledge the cost before signing.
|
@Ajibose 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! 🚀 |
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 #825
Summary
Holders who sell within 7 days of a key's creation incur a launch penalty. The sell confirmation modal now detects this and shows a prominent warning with the penalty amount before the user signs the transaction.
createdAtLedgerNew files
src/utils/launchPenalty.utils.ts—isWithinLaunchWindow(ledger-delta check against a 7-day/120,960-ledger window) andcalculateLaunchPenalty(penalty + net proceeds from gross proceeds, ledgers, andlaunchPenaltyBps)src/components/common/LaunchPenaltyWarning.tsx— the yellow warning banner shown on the sell modalsrc/components/common/SellFeeBreakdown.tsx— sell-side fee breakdown (gross proceeds, launch penalty line, net proceeds), replacing the plain "Estimated proceeds" line that lived inline inTradeDialogModified files
src/components/common/TradeDialog.tsx— acceptscreatedAtLedger,currentLedger, andlaunchPenaltyBpsprops; computes the launch-penalty breakdown viauseMemofrom the estimated sell proceeds; rendersLaunchPenaltyWarningand swaps the old inline sell-proceeds block forSellFeeBreakdownsrc/services/course.service.ts— addscreatedAtLedgerandcurrentLedgerto theCoursetype (the key detail API model returned bygetCourse/GET /courses/:id), alongside the existinglaunchPenaltyBpssrc/pages/LandingPage.tsx— wires the newcreatedAtLedger/currentLedger/launchPenaltyBpsprops from the featured creator into the existingTradeDialogusageImplementation details
LAUNCH_WINDOW_LEDGERS = 120,960, derived from Stellar's ~5s ledger close time), matching the existingledgerToTimestampconvention instellarLedger.utils.ts, so the check is a plain ledger-delta comparison (currentLedger - createdAtLedger < LAUNCH_WINDOW_LEDGERS) with no extra RPC call needed.currentLedgeris sourced from the same key detail API response ascreatedAtLedger/launchPenaltyBps— this repo has no live Soroban/Horizon RPC integration yet, so the backend response is the natural place for a ledger reference point.calculateLaunchPenaltyis defensive: missing/invalid ledgers, a zero/undefinedlaunchPenaltyBps, or a non-positive gross amount all resolve toapplies: falsewithnetProceedsStroopsfalling back to the gross amount (or0if gross is unavailable), so malformed data never blocks a sell or fabricates a penalty.SellFeeBreakdownpreserves the exact "Estimated proceeds (approximate)" / "Estimated proceeds unavailable" copy and DOM shape used by the pre-existingTradeDialog.sellPayoutDisplay.test.tsxsuite, so that suite passes unmodified — the penalty and net-proceeds rows are purely additive, shown only whenlaunchPenalty.appliesis true.bpsToPercenthelper fromnumberFormat.utils.tsfor consistency with other fee displays.Tests added
src/utils/__tests__/launchPenalty.utils.test.ts— unit tests forisWithinLaunchWindow(at creation, mid-window, exactly at the 7-day boundary, well past, ledger clock-skew, missing/NaN inputs) andcalculateLaunchPenalty(applies within window, no-op past window, no-op with no penalty configured, no-op with missing ledger data, rounding, 0%/20% boundary penalties, gross-proceeds-unavailable fallback)src/components/common/__tests__/LaunchPenaltyWarning.test.tsx— renders nothing when not visible, renders the warning text and formatted percentage when visible, formats fractional percentages, hasrole="alert"src/components/common/__tests__/SellFeeBreakdown.test.tsx— gross-only rendering when no penalty applies, "unavailable" fallback, penalty + net proceeds rows when a penalty applies, correct formatting for a large (20%) penaltysrc/components/common/__tests__/TradeDialog.launchPenalty.test.tsx— integration coverage inside the sell modal: warning shown within the window, hidden past the window, hidden with no penalty configured, hidden with no ledger data, never shown on the buy side, correct penalty/net-proceeds amounts in the fee breakdown as the sell quantity changes, no penalty line item past the window, and confirming the sale still works after the warning is shownAll new/changed tests pass (61 tests across the four new files, plus the pre-existing
TradeDialog.sellPayoutDisplay.test.tsxandTradeDialog.a11y.test.tsxsuites verified unaffected). The two pre-existing failing test categories in the full suite (WagmiProviderNotFoundErrorinReferralLinkPanel.test.tsx,react-routercontext errors inCreatorCard.*.test.tsx, and clipboard-timeout tests inCreatorProfileHeader.copy.test.tsx) were confirmed present ondevbefore this change and are unrelated to this PR. Similarly, the pre-existingtsc -berrors inCreatorDetailPage.tsx(missing co-creator fields onCourse) were confirmed present ondevand are untouched by this change.How to test
pnpm install && pnpm test— run the full suite, or scope to the new files:pnpm dev, open the landing page, and click "Sell" on the featured creator card to open the sell confirmation modal.createdAtLedger/currentLedgeronDEMO_CREATORS[0]inLandingPage.tsxso the ledger delta is under 120,960 (e.g.createdAtLedger: 1000, currentLedger: 1100) and give it alaunchPenaltyBps(e.g.500for 5%) — the yellow warning banner and the "Launch penalty" / "Net proceeds" rows should appear in the fee breakdown as you change the sell amount.currentLedgerout pastcreatedAtLedger + 120,960(or remove the fields) to confirm the warning and penalty row disappear and the modal behaves exactly as before.