Skip to content

Fix: 2 issues (#881, #883) - #949

Open
Novastrum1 wants to merge 1 commit into
Stellar-split:mainfrom
Novastrum1:simple/881-883
Open

Novastrum1 wants to merge 1 commit into
Stellar-split:mainfrom
Novastrum1:simple/881-883

Conversation

@Novastrum1

Copy link
Copy Markdown

Closes #881
Closes #883

Issues

#881 Add subscription and recurring payment management

Overview

Enable creators to manage subscriptions with pause, resume, and cancellation options.

Requirements

  • Design subscription lifecycle states
  • Implement pause/resume functionality
  • Add cancellation with reason tracking
  • Create subscription modification UI
  • Implement billing notifications
  • Add subscription analytics dashboard

Acceptance Criteria

[ ] Subscriptions can be created and managed
[ ] Pause/resume works correctly
[ ] Cancellations tracked with reasons
[ ] Modifications reflected immediately
[ ] Analytics dashboard functional

Definition of Done

All CI checks must pass before the PR is reviewed.

#883 Add Ledger hardware wallet support with transaction verification

Overview

Enable users to sign transactions using Ledger devices with clear transaction verification.

Requirements

  • Integrate Ledger Stellar app
  • Implement derivation path selection
  • Add transaction display on Ledger
  • Implement confirmation flow
  • Handle Ledger connection errors
  • Add Ledger status monitoring

Acceptance Criteria

[ ] Ledger devices can be connected
[ ] Transactions display on device
[ ] Signing confirmation works
[ ] Connection issues handled gracefully
[ ] Status monitoring accurate

Definition of Done

All CI checks must pass before the PR is reviewed.

Summary

Subscription changes are mostly additive: keep existing callers of pauseSubscription/resumeSubscription/cancelSubscription working by making new parameters optional (reason/note). CancelModal is shared with invoice cancellation, so the reason step must be opt-in via requireReason to avoid breaking existing flows. Ledger support requires new dependencies (@ledgerhq/hw-transport-webhid, @ledgerhq/hw-app-str) — add them to package.json and ensure CI installs them; all Ledger code must be dynamically imported and guarded with typeof window to keep SSR/build green. Route all signing through the shared signTransaction adapter in freighter.ts so both features compose cleanly. Run the full test suite and lint before opening the PR.

Changes

  • Extend the subscription domain types: add lifecycle states (active, paused, cancelled, past_due, expired) to SubscriptionStatus, add a CancellationReason type (e.g. 'too_expensive' | 'not_using' | 'switched_service' | 'other') plus optional cancellationReason/cancelledAt fields on Subscription, add pausedAt/resumedAt timestamps, and add a SubscriptionModification type for tracking edits. Also add a SubscriptionAnalytics type used by the analytics dashboard. (src/types/subscription.ts)
  • Implement subscription lifecycle logic: state-transition helpers (canPause/canResume/canCancel), pauseSubscription/resumeSubscription that record timestamps and recompute nextRunDate, cancelSubscription(sub, reason, note?) that records cancellation reason and timestamp, modifySubscription(sub, changes) that applies modifications immediately and recomputes nextRunDate, plus an aggregateSubscriptionAnalytics(subs) function returning counts by status, MRR, churn rate, and cancellation-reason breakdown for the analytics dashboard. Also emit billing notifications (via notifications/pushNotifications) when invoices are generated or a subscription is paused/cancelled. (src/lib/subscriptions.ts)
  • Add subscription billing notification helpers: extend NotificationPreferences with subscriptionBilling, subscriptionPaused, subscriptionCancelled flags and add notifySubscriptionBilling(subId, amountLabel), notifySubscriptionPaused(subId), notifySubscriptionCancelled(subId, reason) functions that respect prefs and call sendBrowserNotification. (src/lib/notifications.ts)
  • Add a subscription billing push helper: export showSubscriptionNotification(subscriptionId, title, message) mirroring showInvoiceNotification but routing data.url to /subscriptions/, so billing events can be delivered via the service worker. (src/lib/pushNotifications.ts)
  • Add a server-side sendSubscriptionBillingNotification(subscription, payload) helper in webPush.ts that mirrors sendFundingMilestoneNotification (VAPID guard, 404/410 cleanup) and delivers subscription billing/reminder pushes. (src/lib/webPush.ts)
  • Update SubscriptionsClient: replace the window.confirm cancellation with a CancelModal-based flow that captures a cancellation reason (and optional note) and passes it to cancelSubscription; add a 'Modify' action that opens a new SubscriptionModifyModal to edit frequency/interval/recipients and applies changes immediately via modifySubscription; extend the status filter to include past_due and expired; surface billing notifications through the notification helpers. (src/components/SubscriptionsClient.tsx)
  • Create SubscriptionModifyModal component: a FocusTrap-wrapped dialog with fields for frequency (weekly/biweekly/monthly), interval days, and recipient amounts, validation, and an onConfirm(changes) callback that the parent uses to call modifySubscription. Include loading/error states. (src/components/SubscriptionModifyModal.tsx)
  • Update SubscriptionCard: add STATUS_STYLES entries for past_due and expired, render cancellation reason (if present) on cancelled cards, and show a paused-since timestamp for paused subscriptions. (src/components/SubscriptionCard.tsx)
  • Update SubscriptionDetailClient: wire the pause/resume/cancel actions to the new lifecycle helpers, open CancelModal to capture a cancellation reason and pass it to cancelSubscription, add a 'Modify subscription' button that opens SubscriptionModifyModal and applies changes immediately, and display cancellation reason/timestamp and paused-since info in the detail view. (src/components/SubscriptionDetailClient.tsx)
  • Extend CancelModal to support an optional reason-capture step: add optional props requireReason, reasons (list of {value,label}), and change onConfirm signature to onConfirm(reason?: string, note?: string). Render a reason select plus optional free-text note before the destructive-action gate when requireReason is true, keeping existing invoice-cancellation callers working unchanged. (src/components/CancelModal.tsx)
  • Add subscription invoice rows to SubscriptionHistoryTable: show a 'Cancelled' badge and cancellation reason column when the parent passes cancellation metadata, and include the reason in the CSV export. (src/components/SubscriptionHistoryTable.tsx)
  • Update SubscriptionCalendarPreview to accept a status prop and render paused/cancelled states distinctly (e.g. muted dates and a status banner) so upcoming dates reflect the subscription lifecycle. (src/components/SubscriptionCalendarPreview.tsx)
  • Extend RecurringWizard to support the new lifecycle: allow selecting pause-after-creation and expose the chosen interval/frequency in the confirmed config so SubscriptionsClient can persist it consistently with the new Subscription type. (src/components/RecurringWizard.tsx)
  • Add subscription notification types: extend NotificationType with 'subscription_billing' | 'subscription_paused' | 'subscription_cancelled', and render subscription notifications with links to /subscriptions/ in the dropdown. (src/components/NotificationCenter.tsx)
  • Add a subscription analytics section to AnalyticsPanel: accept an optional subscriptions prop, compute aggregateSubscriptionAnalytics (active/paused/cancelled counts, MRR, churn, cancellation-reason breakdown) and render summary cards plus a small bar chart alongside the existing invoice analytics. (src/components/AnalyticsPanel.tsx)
  • Wire subscription analytics into the analytics page: load subscriptions via loadSubscriptions, pass them to AnalyticsPanel, and add a 'Subscriptions' tab/section showing the subscription analytics dashboard. (src/app/analytics/page.tsx)
  • Create a Ledger integration module: implement connectLedger(), disconnectLedger(), getLedgerStatus(), listDerivationPaths()/selectDerivationPath(), signWithLedger(xdr, path) using the Stellar app transport (dynamic import of @ledgerhq/hw-transport-webhid and @ledgerhq/hw-app-str), display the transaction on-device before signing, and return the signed XDR. Guard all calls with typeof window checks and throw typed errors for not_connected/locked/app_not_open/denied. (src/lib/ledger.ts)
  • Extend the wallet adapter layer: add 'ledger' to WalletType, add connectLedger/getLedgerPublicKey/disconnectLedger wrappers, and update signTransaction(xdr) to route to signWithLedger when a Ledger device is the active wallet (falling back to WalletConnect/Freighter otherwise). (src/lib/freighter.ts)
  • Update useWallet to support connecting a Ledger wallet: add 'ledger' handling in connect(), persist walletType 'ledger' in the session cache, expose ledgerStatus/derivationPath and setDerivationPath, and surface Ledger connection errors through the existing error state. (src/hooks/useWallet.ts)
  • Expose Ledger state through WalletContext: extend WalletContextValue with ledgerStatus, derivationPath, setDerivationPath, and connectLedger so components can read Ledger connection status and trigger connection from the shared context. (src/contexts/WalletContext.tsx)
  • Route transaction signing through Ledger: in useStellarTransaction, when the active wallet is Ledger, call signWithLedger (which triggers on-device display and confirmation) instead of signTransaction, and map Ledger rejection/connection errors to the existing toast/error paths. (src/hooks/useStellarTransaction.ts)
  • Update useTransactionWithRetry to treat Ledger connection errors (device disconnected, app not open) as non-retryable and surface a clear toast, while still retrying rate-limit errors. (src/hooks/useTransactionWithRetry.ts)
  • Add Ledger error classification: extend ErrorKind with 'ledger_not_connected' | 'ledger_locked' | 'ledger_app_not_open' | 'ledger_denied' and add matching patterns/messages in classifyError so Ledger failures are surfaced consistently. (src/lib/errors.ts)
  • Add Ledger error mappings to stellarErrorParser: add entries for ledger_not_connected, ledger_locked, ledger_app_not_open, and ledger_denied with titles/explanations/suggested actions (actionType 'manual') so the UI can render actionable guidance. (src/lib/stellarErrorParser.ts)
  • Extend walletMonitor to also poll Ledger status: add startLedgerPolling/stopLedgerPolling and include ledger connection state in WalletState notifications so subscribers learn when a Ledger device connects/disconnects. (src/lib/walletMonitor.ts)
  • Update WalletConnect UI: add a 'Connect Ledger' button that calls connectLedger from context, show a Ledger status indicator (connected/locked/app not open) with derivation path selector, and route Ledger errors to WalletErrorModal. (src/components/WalletConnect.tsx)
  • Extend WalletErrorModal with Ledger error types: add 'ledger_not_connected' | 'ledger_locked' | 'ledger_app_not_open' | 'ledger_denied' to WalletErrorType and render appropriate guidance (open Stellar app, unlock device, reconnect USB) with retry action. (src/components/WalletErrorModal.tsx)
  • Update TxConfirmModal to support a pre-signing Ledger confirmation state: add optional props for 'awaiting_device' status showing 'Confirm on your Ledger device' with the transaction summary, and render the success state once the signed transaction is submitted. (src/components/TxConfirmModal.tsx)
  • Add Ledger as a payment method in PaymentMethodSelector: extend PaymentMethod to include 'ledger', load/save the preference, and show the option only when a Ledger device is detected (via getLedgerStatus). (src/components/PaymentMethodSelector.tsx)
  • Update stellar.ts signing helpers (e.g. convertXlmToUsdc and other build/sign flows) to use the shared signTransaction adapter so Ledger-signed transactions are supported wherever Freighter was previously hard-coded. (src/lib/stellar.ts)

Co-authored-by: Simple Agent <agent@simple.dev>
@vercel

vercel Bot commented Oct 17, 2026

Copy link
Copy Markdown

@Novastrum1 is attempting to deploy a commit to the kingsman-99's projects Team on Vercel.

A member of the Team first needs to authorize it.

@drips-wave

drips-wave Bot commented Oct 17, 2026

Copy link
Copy Markdown

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

This branch has not been deployed

No deployments
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.

Add Ledger hardware wallet support with transaction verification Add subscription and recurring payment management

1 participant