Skip to content

feat(stellar): add minimum-balance and reserve estimator - #1

Open
Ayomide-257 wants to merge 26 commits into
mainfrom
feat/134-minimum-balance-estimator
Open

feat(stellar): add minimum-balance and reserve estimator#1
Ayomide-257 wants to merge 26 commits into
mainfrom
feat/134-minimum-balance-estimator

Conversation

@Ayomide-257

Copy link
Copy Markdown
Owner

Summary

Adds a minimum-balance and reserve estimator to the Stellar Balance Viewer tool.

Closes #134

Changes

lib/stellar/horizon.ts

  • Added getBaseReserve() that fetches the network base reserve from the latest ledger, with a safe fallback to 0.5 XLM.

lib/stellar/account.ts

  • Added MinimumBalanceEstimate interface
  • Added getMinimumBalance() that calculates an account's Stellar minimum balance using the formula: (2 + subentry_count + num_sponsoring - num_sponsored) × base_reserve
  • Added toFixedDecimal() helper using stroop arithmetic to avoid JavaScript floating-point rounding issues
  • Safe fallbacks for missing sponsorship fields in older Horizon responses

app/tools/balance-viewer/page.tsx

  • Integrated the minimum balance estimator card into the Balance Viewer
  • Displays: formula breakdown, source ledger, estimated minimum balance, native XLM balance, and potentially spendable XLM
  • Potentially spendable XLM is explicitly labeled as an estimate (not transaction advice)
  • Ledger info hidden gracefully when unavailable

tests/stellar/minimumBalance.test.ts

  • 16 deterministic tests with mocked Horizon fixtures
  • Covers: basic accounts, trustline-heavy accounts, sponsored/sponsoring accounts, decimal precision, missing field fallbacks, network-aware base reserve

Quality Gates

  • npm run lint — clean
  • npm test — 28 tests pass (16 new + 12 existing)
  • npm run build — successful

Ayomide-257 and others added 26 commits July 28, 2026 11:47
Add getBaseReserve() and getMinimumBalance() with formula display, test fixtures for basic/trustline/sponsored accounts. Closes #134
…ING.md (RevenantLabs#205)

Co-authored-by: Dayz Tech Co <Dayztechnology@gmail.com>
Native XLM payments now omit asset_code/asset_issuer per spec, memo
requests include memo_type, and testnet requests include
network_passphrase. Documents the format in the README.
…ator (#8) (RevenantLabs#251)

- Add displayNetwork() helper to normalize Freighter raw values to Testnet/Mainnet
- Add Badge indicator (Match in green, Mismatch in warning orange) next to wallet network
- Add TODO(issue RevenantLabs/RevyHub#8) for future network change listener
- Improve network check messaging: only show when Freighter is available and has reported a network
- Add actionable mismatch guidance telling users which Freighter network to switch to
- Update docs/ISSUES.md maintainer status

Closes RevenantLabs/RevyHub#8
…evenantLabs#195)

* feat: add structured error codes and education to address validator

Enhance validatePublicKey with distinct validation codes (empty,
secret-key, muxed-account, invalid-prefix, invalid-characters,
invalid-length, invalid-checksum, valid) and specific, actionable
messages for each failure case instead of a single generic checksum
error. The address validator page now maps each code to a tailored
title/tone (success, warning for secret-key/muxed-account, error for
malformed addresses, info for empty input) and shows a persistent
"What is a Stellar public key?" panel explaining the format and the
difference from a secret key.

Updated existing tests to match the richer messages and added cases
covering muxed accounts, invalid characters, wrong length, and
malformed input to confirm validation never throws.

Closes RevenantLabs/RevyHub#2

* test: align address validation expectation

---------

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
* feat: add pull request template with summary, testing, screenshots, and checklist sections

- Enhance .github/PULL_REQUEST_TEMPLATE.md with YAML frontmatter, dedicated
  How to Test section, comprehensive checklist, and Related Issues block
- Update CONTRIBUTING.md to reference the PR template and remove stale TODO
  comments for issues #18 and #19

Closes #19

* fix: make pull request template GitHub-compatible

---------

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
* feat(qr): add real-time form validation with field-level errors (#11)

- Add validatePaymentForm() function returning structured field-level errors
- Validate destination, amount, asset code, asset issuer, and memo length
- Disable submit button when validation errors exist
- Show inline error messages below each field in warning tone
- Update createPaymentUri to delegate validation to the reusable function
- Remove TODO(issue #11) comment, update ISSUES.md and ARCHITECTURE.md

Closes RevenantLabs/RevyHub#11

* fix: enforce Stellar memo byte limit

---------

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
RevenantLabs#256)

* feat(horizon): wire AbortController for timeout and cancellation in tool pages

* feat(horizon): add timeout and cancellation support to Horizon requests

---------

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
…s#190)

* test: add comprehensive payment QR form validation tests

- Add invalid destination tests (empty, invalid format, checksum errors)
- Add invalid amount tests (zero, negative, non-numeric values)
- Add valid form tests (XLM, issued assets, minimal form)
- Add memo validation tests (length limits, special characters)
- Add issued asset validation tests (code length, issuer validation)

All tests pass locally with npm run test
Addresses acceptance criteria for issue #17

* test: cover payment form validation boundaries

---------

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
* feat: add local transaction XDR inspector

Decode transaction-envelope XDR entirely in the browser and show envelope
type, source account, sequence, fee, memo, preconditions, operation types,
and signature count for classic (v0/v1) and fee-bump envelopes.

- lib/stellar/xdrInspector.ts: bounded, local-only decoder with typed
  normalized results and clear error codes for empty, oversized,
  non-base64, malformed, and unsupported input
- app/tools/xdr-inspector: new tool page; pasted XDR stays in component
  state and is never logged, persisted, or placed in the URL
- components/stellar/EnvelopeDetails.tsx + components/ui/Textarea.tsx:
  display components following existing UI conventions
- tests/stellar/xdrInspector.test.ts: fixtures for classic v0/v1,
  fee-bump, unsigned, signed, malformed, truncated, and oversized
  envelopes, plus a guard that decoding never calls fetch

Closes #177

* fix: format XDR fees without precision loss

---------

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
Adds a Horizon fee_stats panel showing min/mode/percentile fees in
stroops and XLM, with plain-language definitions for last-ledger base
fee and ledger capacity usage. Loads on demand, guards against
concurrent refreshes, and shows a last-updated timestamp.

Closes #180

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
…#193)

Adds a complete federation-address lookup tool implementing SEP-0002
(stellar.toml discovery over HTTPS + GET-with-query federation server
call) and SEP-0001 (Federation Server discovery via
/.well-known/stellar.toml).

lib/stellar/federation.ts (new)
  - parseFederationAddress / validateFederationSyntax (pure)
  - resolveFederation: HTTPS GET stellar.toml, regex-extract
    FEDERATION_SERVER (quoted, unquoted, and inline-comment tolerant),
    GET ?q=<name*domain>&type=name the server, validate the JSON
    response, StrKey.isValidEd25519PublicKey the account_id, and
    enforce SEP-0002 memo type allowlist (text | id | hash | return)
    plus the 28-char text memo limit.
  - Discriminated FederationResult union with 14 typed error codes so
    the UI can map each to specific guidance.
  - Combined AbortSignal.timeout + caller-provided signal so either
    source ends the request cleanly. Fetch TypeErrors (CORS / DNS)
    surface as networkError, not 0-status.

app/tools/federation-resolver/page.tsx (new)
  - "Federation postmaster" character on a fresh /tools route,
    auto-registered in lib/constants.ts so Sidebar and ToolCard pick
    it up.
  - StatusMessage shown for every error code via the errorPresentation
    map. Memo disclosure with copyable text/return memos. Sources
    disclosure for stellar.toml + federation server URLs.
  - Persistent safety-reminder card so users know to verify account
    and memo before sending.

tests/stellar/federation.test.ts (new) - 26 unit tests
  - parseFederationAddress: happy paths, name regex, hostname regex,
    64-char limit, FIRST-asterisk split, empty/non-string guards.
  - validateFederationSyntax: empty / missing asterisk / empty halves.
  - resolveFederation: success (with / without memo), unquoted toml,
    inline-comment toml, all 3 alternate memo types.
  - Failure paths: empty, invalidSyntax, tomlNotFound 404,
    noFederationServer, httpsRequired, federationNotFound 404,
    federationMalformed (HTML body + missing account_id),
    invalidAccountId checksum fail, invalidMemo (unknown type +
    missing memo_type + 28-char overflow), federationServerError 5xx,
    timeout via pre-aborted AbortController, networkError via
    fetch TypeError.
  - Mocked fetch per test (no global mock leaks).

Resolves #182.

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
…ntLabs#260)

- lib/stellar/stellarToml.ts: normaliseDomain, parseStellarTomlCurrencies,
  fetchStellarToml with HTTPS-only enforcement, 100 KiB size guard,
  10-second timeout, CORS/network/redirect/404 distinct error messages
- app/tools/asset-metadata/page.tsx: new page using CharacterPanel,
  Card, Input, Button, StatusMessage, CopyableValue; shows fetch URL,
  timestamp, and per-currency fields (code, issuer, name, desc, image,
  home_domain); untrusted-content notice on all external values
- tests/stellar/stellarToml.test.ts: 24 unit tests covering domain
  normalisation, TOML parsing edge cases, and all fetch error paths
  via mocked fetch
- lib/constants.ts: register Asset Metadata Inspector tool entry

All quality gates pass: npm run lint, npm run test (36/36), npm run build

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
)

* test: cover CopyableValue clipboard success and failure

Add component tests for truncation, accessible full-value context,
feedback reset, clipboard rejection, and independent instance state.
Handle copy failures without unhandled rejections.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: address review for CopyableValue a11y and lockfile

Expose the full truncated value through sr-only + aria-describedby,
and pin optional @emnapi packages so npm ci stays reproducible.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: add PNG download for payment QR codes

Allow downloading the current QR data URL with a deterministic,
address-safe filename. Include coverage for filename generation and
download availability.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: snapshot QR download filename and sync lockfile

Keep the PNG filename tied to the generated QR rather than live form
fields, and pin optional @emnapi packages for reproducible npm ci.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
* feat: add Freighter local disconnect and clear action

Clear displayed public key and wallet network without claiming to
revoke Freighter extension permissions. Cover clear and reconnect
with component tests.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: sync package-lock for reproducible npm ci

Pin optional @emnapi packages required by the review and regenerate
the lockfile after rebasing onto latest main.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…bs#79)

* docs: add step-by-step guide for extending RevyHubX tools

Document where tool pages, shared components, Stellar utilities,
navigation metadata, error states, and quality gates belong, with
links from README, CONTRIBUTING, and ARCHITECTURE.

Co-authored-by: Cursor <cursoragent@cursor.com>

* fix: teach UTF-8 byte length for Stellar text memos

Update the extending guide example to validate memo size with
TextEncoder and add a multibyte emoji case contributors can copy.

Co-authored-by: Cursor <cursoragent@cursor.com>

---------

Co-authored-by: Cursor <cursoragent@cursor.com>
…enantLabs#200)

- Redesign hero section with animated entrance, gradient heading, and CTA buttons
- Group tools into validation, balances, and network categories
- Enhance ToolCard with category badges, hover/focus states
- Add fade-in-up animations and smooth scroll behavior
- Remove TODO(issue #1) markers
)

- Clearly label native XLM with a star icon and 'XLM — Native Asset'
- Show issued assets with asset code and truncated issuer via CopyableValue
- Handle liquidity pool shares with dedicated display
- Format balance amounts with max 7 decimal places, no trailing zeros
- Prevent layout breakage with truncate/min-w-0/shrink-0 on all text
- Add empty balances message when account has no balances
- Update BalanceList rendering to only show after successful search
- Remove TODO(issue #4) after completing all acceptance criteria
)

* feat(stellar): complete mainnet/testnet network switch

Closes the remaining gaps in the global network switch (issue #3).

Testnet-only tools now react to the switch. The Friendbot faucet
ignored the selected network entirely: it stayed enabled on mainnet
and would silently send a testnet request. It now renders a shared
TestnetOnlyNotice, disables its submit button off testnet, and offers
a one-click switch back.

The stored preference no longer risks a hydration mismatch. The
provider read localStorage inside a useState initializer, so a saved
"mainnet" choice made the server and client disagree on the header
select and badge. The selection is now read through
useSyncExternalStore, which also syncs the choice across tabs and
falls back to memory when localStorage is unavailable.

Network-dependent copy is no longer hardcoded to testnet, so the
active network reads correctly on both. The faucet call-to-action in
the balance viewer and trustline checker is gated on the selected
network instead of matching an error substring.

Network labels, tones, and input normalization move into
lib/stellar/horizon.ts so the header and tool pages share one source
of truth. Drops the unused horizonServer export, which eagerly built
a server pinned to a single network.

* fix: reconcile network switch with current tool metadata

---------

Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
)

- Add ARIA live-region semantics: role=status, aria-live (assertive for
  error/warning, polite for success/info), and aria-atomic=true so screen
  readers announce the full message as a unit.
- Export StatusMessageProps interface so downstream code and tests can
  import the type directly.
- Add JSDoc covering accessibility guarantees and colour-contrast note.
- Remove TODO(issue #6) marker (all acceptance criteria met).
- Add tests/ui/StatusMessage.test.ts with 14 vitest cases covering:
    - aria-live mapping logic for all four status types
    - StatusMessageProps interface (required fields, optional slots)
    - Full status-type matrix with politeness/interrupt assertions

All four status types (success, error, warning, info) are supported.
Component is already consumed in all seven tool pages:
address-validator, balance-viewer, freighter-connect, payment-qr,
testnet-faucet, transaction-lookup, trustline-checker.

npm run lint: passed (0 errors)
npm run build: passed (all 10 pages compiled + TypeScript checked)
vitest run: 26/26 tests pass

Closes #6
Co-authored-by: Ege Hidayet Koca <kocaege777@gmail.com>
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.