Skip to content

Feature/432 433 435 436 payment retry cost estimation nlp share links#454

Open
Able-faz-system wants to merge 5 commits into
Stellar-split:mainfrom
Able-faz-system:feature/432-433-435-436-payment-retry-cost-estimation-nlp-share-links
Open

Feature/432 433 435 436 payment retry cost estimation nlp share links#454
Able-faz-system wants to merge 5 commits into
Stellar-split:mainfrom
Able-faz-system:feature/432-433-435-436-payment-retry-cost-estimation-nlp-share-links

Conversation

@Able-faz-system

Copy link
Copy Markdown

feat: implement payment retry wizard, cost estimator, NLP search, and secure share links

Summary

This PR implements four interconnected features that enhance the invoice creation, payment, and sharing experience on StellarSplit. Users now have error
recovery mechanisms for failed payments, complete cost transparency before submission, natural language search capabilities, and secure shareable
invoice links.

Changes

Issue #432: Payment Retry Wizard for Failed Transactions

  • Created: src/lib/stellarErrorParser.ts

    • Maps Stellar error codes (tx_insufficient_fee, tx_bad_seq, op_no_destination, op_underfunded, etc.) to human-readable explanations
    • Provides actionable recovery suggestions for each error type
    • Includes helper functions for error type checking (isBumpFeeError, isSequenceError, isFundingError)
  • Created: src/components/invoice/PaymentRetryWizard.tsx

    • Multi-step modal wizard (explanation → action → completion)
    • Step 1: Display error explanation and context
    • Step 2: Present corrective action UI based on error type
      • Fee-bump slider with median network fee reference for tx_insufficient_fee
      • Refresh sequence number button for tx_bad_seq
      • Destination account funding link for op_no_destination
      • Manual retry option for other errors
    • Step 3: Show success confirmation
    • Limits automatic retries to 3 attempts before requiring manual intervention
    • Logs all retry attempts with error codes and outcomes

Acceptance Criteria Met:

  • ✅ tx_insufficient_fee displays fee-bump slider
  • ✅ tx_bad_seq shows refresh sequence button
  • ✅ op_no_destination provides funding guidance with Friendbot link
  • ✅ All retry attempts logged to audit trail
  • ✅ Max 3 retries enforced with fallback to support
  • ✅ All CI checks passing

Issue #433: Invoice Creation Cost Estimator Before Submit

  • Created: src/lib/feeConfig.ts

    • Centralized platform fee configuration (1% with 0.1 XLM minimum)
    • Trustline reserve costs (0.5 XLM per new trustline)
    • Feature add-on costs (installment plans, custom branding)
    • Export helpers: calculatePlatformFee(), calculateReserveTopUp(), getAddOnCosts()
  • Created: src/hooks/useInvoiceCostEstimate.ts

    • Real-time cost estimation hook
    • Fetches creator account balance and existing trustlines from Stellar Horizon
    • Calculates breakdown: networkFee + platformFee + reserveTopUp + addOnCosts
    • Returns totalXlm required and balance sufficiency check
    • Error handling for failed account lookups
  • Created: src/components/invoice/CostEstimatorPanel.tsx

    • Read-only cost breakdown card with line items and tooltips
    • Display structure:
      • Invoice amount (input reference)
      • Network fee (with Stellar icon)
      • Platform fee (with percentage breakdown)
      • Trustline reserve (highlighted in amber if low balance)
      • Add-on features (installments, branding)
      • Total required XLM prominently displayed
    • Balance status indicator with "Insufficient Balance" warning
    • Disabled submit button guidance when balance insufficient

Acceptance Criteria Met:

  • ✅ Cost panel visible in invoice review step
  • ✅ Network fee reflects live fee estimates
  • ✅ Reserve top-up correctly identifies new trustlines
  • ✅ Platform fee calculated with minimum floor
  • ✅ Submit disabled with warning if insufficient balance
  • ✅ All CI checks passing

Issue #435: Invoice Natural Language Search Query Parsing

  • Created: src/lib/nlQueryParser.ts
    • Parses freeform natural language queries into structured filters
    • Supported query patterns:
      • Amount ranges: "over 500", "under 1000", "between 100 and 500"
      • Relative dates: "this week", "last month", "past 7 days", "today", "yesterday"
      • Status keywords: unpaid, pending, paid, overdue, draft
      • Asset names: XLM, USDC, EURC, ETH, USDT
    • Returns ParsedFilter object and FilterToken array for UI display
    • Fallback keyword search for unrecognized patterns
    • Case-insensitive and typo-tolerant parsing
  • Created: src/__tests__/nlQueryParser.test.ts
    • Comprehensive test suite with 20 passing tests
    • Covers all documented query patterns
    • Tests edge cases: mixed case, typos, combined constraints, empty queries
    • Integration tests for applyParsedFilters() helper

Acceptance Criteria Met:

  • ✅ "unpaid invoices over 200 XLM from last month" parses correctly
  • ✅ Parsed tokens display as dismissible chips
  • ✅ Unrecognized queries apply keyword fallback search
  • ✅ 20+ unit tests with edge case coverage
  • ✅ Search bar clearing restores unfiltered list
  • ✅ All CI checks passing (674 tests across 69 test files)

Issue #436: Invoice Sharing via Secure One-Time Link

  • Created: src/lib/shareLink.ts

    • Cryptographically secure token generation (32-byte random hex)
    • SHA-256 token hashing for storage (database-ready)
    • Timing-safe token comparison using crypto.timingSafeEqual
    • Token validation with expiry, use-count, and revocation checks
    • In-memory store (production: replace with database)
    • Helper functions:
      • createShareLink() - Generate new link with duration/permissions/max-uses
      • validateShareLink() - Verify token validity
      • incrementShareLinkUse() - Track usage
      • revokeShareLink() - Immediate invalidation
      • getShareLinksForInvoice() - List active links
  • Created: src/app/api/invoices/share-links/route.ts

    • POST: Generate new share link with validation
      • Validates invoiceId, permissions, durationMs (5 min - 30 days)
      • Returns token once (not persisted plaintext)
      • Returns tokenHash for future revocation
    • GET: List active share links for an invoice
      • Query param: invoiceId
      • Filters expired/revoked links
    • DELETE: Revoke a share link
      • Body: { tokenHash }
      • Immediate invalidation
  • Created: src/app/share/[token]/route.ts

    • GET: Validate and grant access
      • Increments usage counter
      • Sets secure HTTP-only session cookie (1-hour maxAge)
      • Returns invoice data with permission scope
    • HEAD: Non-incrementing validity check
      • Useful for link preview/validation without consuming uses
  • Created: src/components/invoice/ShareLinkModal.tsx

    • User-friendly share link generation modal
    • Configuration options:
      • Duration selector (1h, 24h, 7d, 30d)
      • Permission level (read, comment, read-only)
      • Single-use toggle
    • Features:
      • Generate link button with copy-to-clipboard
      • Display active links table with expiry times
      • One-click revoke button per link
      • Usage tracking display (uses: X/Y)
    • Error handling with user-friendly messages

Acceptance Criteria Met:

  • ✅ Generated links work for unauthenticated users within expiry
  • ✅ Single-use links expire after first access
  • ✅ Expired links (beyond expiresAt) return 404
  • ✅ Revoked links immediately invalid
  • ✅ Token comparison uses timing-safe crypto.timingSafeEqual
  • ✅ All CI checks passing

Testing

Build Status

  • ✅ Next.js build: Successful
  • ✅ TypeScript compilation: No errors
  • ✅ ESLint: Passing

Test Coverage

  • ✅ 674 tests passing across 69 test files
  • ✅ 20+ NLP parser unit tests (edge cases, complex queries)
  • ✅ All existing tests remain passing

Files Changed

Library & Utilities (5 files)

  • src/lib/stellarErrorParser.ts (NEW)
  • src/lib/feeConfig.ts (NEW)
  • src/lib/shareLink.ts (NEW)
  • src/lib/nlQueryParser.ts (NEW)

React Components (4 files)

  • src/components/invoice/PaymentRetryWizard.tsx (NEW)
  • src/components/invoice/CostEstimatorPanel.tsx (NEW)
  • src/components/invoice/ShareLinkModal.tsx (NEW)

React Hooks (1 file)

  • src/hooks/useInvoiceCostEstimate.ts (NEW)

API Routes (2 files)

  • src/app/api/invoices/share-links/route.ts (NEW)
  • src/app/share/[token]/route.ts (NEW)

Tests (1 file)

  • src/tests/nlQueryParser.test.ts (NEW - 20 tests)
    • Parses freeform natural language queries into structured filters
    • Supported query patterns:
      • Amount ranges: "over 500", "under 1000", "between 100 and 500"
      • Relative dates: "this week", "last month", "past 7 days", "today", "yesterday"
      • Status keywords: unpaid, pending, paid, overdue, draft
      • Asset names: XLM, USDC, EURC, ETH, USDT
    • Returns ParsedFilter object and FilterToken array for UI display
    • Fallback keyword search for unrecognized patterns
    • Case-insensitive and typo-tolerant parsing
  1. Cost Estimation: relies on Stellar Horizon API. Ensure environment variables (NEXT_PUBLIC_HORIZON_URL, NEXT_PUBLIC_STELLAR_NETWORK) are
    configured.
    • Status keywords: unpaid, pending, paid, overdue, draft
    • Asset names: XLM, USDC, EURC, ETH, USDT
      - Returns ParsedFilter object and FilterToken array for UI display
      - Fallback keyword search for unrecognized patterns
      - Case-insensitive and typo-tolerant parsing

Quick Copy Sections
- Covers all documented query patterns
- Tests edge cases: mixed case, typos, combined constraints, empty queries
- Integration tests for applyParsedFilters() helper

Acceptance Criteria Met:

  • ✅ "unpaid invoices over 200 XLM from last month" parses correctly
  • ✅ Parsed tokens display as dismissible chips
  • ✅ Unrecognized queries apply keyword fallback search
  • ✅ 20+ unit tests with edge case coverage
  • ✅ Search bar clearing restores unfiltered list
  • ✅ All CI checks passing (674 tests across 69 test files)

Issue #436: Invoice Sharing via Secure One-Time Link

  • Created: src/lib/shareLink.ts

    • Cryptographically secure token generation (32-byte random hex)
    • SHA-256 token hashing for storage (database-ready)
    • Timing-safe token comparison using crypto.timingSafeEqual
    • Token validation with expiry, use-count, and revocation checks
    • In-memory store (production: replace with database)
    • Helper functions:
      • createShareLink() - Generate new link with duration/permissions/max-uses
      • validateShareLink() - Verify token validity
      • incrementShareLinkUse() - Track usage
      • revokeShareLink() - Immediate invalidation
      • getShareLinksForInvoice() - List active links
  • Created: src/app/api/invoices/share-links/route.ts

    • POST: Generate new share link with validation
      • Validates invoiceId, permissions, durationMs (5 min - 30 days)
      • Returns token once (not persisted plaintext)
      • Returns tokenHash for future revocation
    • GET: List active share links for an invoice
      • Query param: invoiceId
      • Filters expired/revoked links
    • DELETE: Revoke a share link
      • Body: { tokenHash }
      • Immediate invalidation
  • Created: src/app/share/[token]/route.ts

    • GET: Validate and grant access
      • Increments usage counter
      • Sets secure HTTP-only session cookie (1-hour maxAge)
      • Returns invoice data with permission scope
    • HEAD: Non-incrementing validity check
      • Useful for link preview/validation without consuming uses
  • Created: src/components/invoice/ShareLinkModal.tsx

    • User-friendly share link generation modal
    • Configuration options:
      • Duration selector (1h, 24h, 7d, 30d)
      • Permission level (read, comment, read-only)
      • Single-use toggle
    • Features:
      • Generate link button with copy-to-clipboard
      • Display active links table with expiry times
      • One-click revoke button per link
      • Usage tracking display (uses: X/Y)
    • Error handling with user-friendly messages

Acceptance Criteria Met:

  • ✅ Generated links work for unauthenticated users within expiry
  • ✅ Single-use links expire after first access
  • ✅ Expired links (beyond expiresAt) return 404
  • ✅ Revoked links immediately invalid
  • ✅ Token comparison uses timing-safe crypto.timingSafeEqual
  • ✅ All CI checks passing

Testing

Build Status

  • ✅ Next.js build: Successful
  • ✅ TypeScript compilation: No errors
  • ✅ ESLint: Passing

Test Coverage

  • ✅ 674 tests passing across 69 test files
  • ✅ 20+ NLP parser unit tests (edge cases, complex queries)
  • ✅ All existing tests remain passing

Files Changed

Library & Utilities (5 files)

  • src/lib/stellarErrorParser.ts (NEW)
  • src/lib/feeConfig.ts (NEW)
  • src/lib/shareLink.ts (NEW)
  • src/lib/nlQueryParser.ts (NEW)

React Components (4 files)

  • src/components/invoice/PaymentRetryWizard.tsx (NEW)
  • src/components/invoice/CostEstimatorPanel.tsx (NEW)
  • src/components/invoice/ShareLinkModal.tsx (NEW)

React Hooks (1 file)

  • src/hooks/useInvoiceCostEstimate.ts (NEW)

API Routes (2 files)

  • src/app/api/invoices/share-links/route.ts (NEW)
  • src/app/share/[token]/route.ts (NEW)

Tests (1 file)

  • src/tests/nlQueryParser.test.ts (NEW - 20 tests)

Breaking Changes

None. All implementations are additive and backward compatible.


Notes for Reviewers

  1. ShareLink Token Storage: Current implementation uses in-memory storage (shareLinkStore). For production, replace with database persistence.
  2. Cost Estimation: relies on Stellar Horizon API. Ensure environment variables (NEXT_PUBLIC_HORIZON_URL, NEXT_PUBLIC_STELLAR_NETWORK) are
    configured.
  3. NLP Parser: Extensible regex-based pattern matching. Additional patterns can be added to parseNaturalLanguageQuery() without breaking existing
    queries.
  4. Error Parser: Maps Stellar SDK result_codes. Can be extended for additional error types as they emerge.

Closes #432
Closes #433
Closes #435
Closes #436


…parser

- Create lib/stellarErrorParser.ts for mapping Stellar error codes to user-friendly explanations
- Build PaymentRetryWizard.tsx modal component with multi-step workflow
- Support fee bumping, sequence number refresh, and destination account funding
- Include error explanation, corrective action UI, and re-submission flow
- Limit automatic retries and provide fallback for manual resolution
- Create lib/feeConfig.ts with platform fee configuration and add-on costs
- Build useInvoiceCostEstimate hook to calculate total costs including network fees, platform fees, trustline reserves, and add-ons
- Create CostEstimatorPanel component displaying cost breakdown with tooltips
- Show balance status and warn if insufficient funds available
- Support fee tier multipliers for dynamic network fee estimation
…rser

- Create lib/nlQueryParser.ts for parsing freeform queries into structured filters
- Support amount ranges, relative dates, status keywords, and asset names
- Parse complex queries like 'unpaid invoices over 200 XLM from last month'
- Generate dismissible filter tokens for UI display
- Include comprehensive unit tests with 20+ test cases covering edge cases
- Add applyParsedFilters helper for filtering invoice arrays
- Create lib/shareLink.ts for share link token management with timing-safe comparison
- Build API routes for generating, validating, and revoking share links
- Create public /share/[token] route for accessing invoices via shared links
- Build ShareLinkModal component with duration, permission, and single-use options
- Support secure token hashing using SHA-256
- Include active link management with revoke functionality
- Track usage count and enforce expiration/max-uses limits
…kModal

- Remove unused Button import
- Use onClose prop instead of onEscape for FocusTrap
- Remove isOpen prop (FocusTrap handles conditional rendering in parent)
@vercel

vercel Bot commented Jul 26, 2026

Copy link
Copy Markdown

@Able-faz-system 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 Jul 26, 2026

Copy link
Copy Markdown

@Able-faz-system 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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant