Skip to content

fix: stroop precision, friendbot mainnet guard, server-only env guard… - #749

Merged
Jambox11 merged 1 commit into
mux-labs:stagingfrom
cyberpunk30:feature/696-695-694-693-task-fixes
Aug 31, 2026
Merged

fix: stroop precision, friendbot mainnet guard, server-only env guard…#749
Jambox11 merged 1 commit into
mux-labs:stagingfrom
cyberpunk30:feature/696-695-694-693-task-fixes

Conversation

@cyberpunk30

Copy link
Copy Markdown

Title:

fix: stroop precision, friendbot mainnet guard, server-only env guard, API URL alias chain

Description:

Closes #696
Closes #695
Closes #694
Closes #693

Summary

Four related hardening fixes across validation, security, and configuration.


#696 — Validate send amounts with stroop precision

Stellar amounts have at most 7 decimal places (1 stroop = 0.0000001 XLM).
Sending 1.00000001 XLM would previously pass validation and be silently
truncated by the network.

  • validateSendAmount() now rejects any amount with more than 7 decimal places
  • Added isStroopPrecise() helper and STROOP_DECIMALS = 7 constant
  • xlmFormat.ts gains toStroopPrecision(), isExactStroopAmount(),
    XLM_MAX_DECIMALS, and MIN_XLM_AMOUNT
  • Tests cover boundary cases: 0.0000001 ✅, 0.00000001

#695 — Friendbot helper must refuse mainnet

Calling the Friendbot faucet against mainnet was a silent no-op at best and
exposes addresses to a public API at worst.

  • getFriendbotUrl() now throws MainnetFriendbotError immediately when
    network === "mainnet"
  • New assertTestnetOnly() helper for explicit guards at call-sites
  • MainnetFriendbotError is a named class so callers can catch it specifically
  • Backward-compatible: network param is optional

#694 — Do not bundle MUX_API_SECRET into client JS

Next.js strips non-NEXT_PUBLIC_* vars at build time, but a future refactor
could accidentally import a server-only helper into a client component and get
a silent undefined rather than a visible error.

  • Added assertServerSide(varName) to env.ts — throws when window is defined
  • Added getServerOnlyEnv(name) as the safe way to read server-only vars
  • Tests simulate a browser context (globalThis.window = {}) to verify the guard

#693 — Resolve NEXT_PUBLIC_API_URL vs NEXT_PUBLIC_MUX_API_URL vs NEXT_PUBLIC_API_BASE

Three aliases for the same concept with no documented priority and no protection
against blank-string mis-configuration.

  • Exported API_URL_CANDIDATES constant — single source of truth for the chain
  • getApiBaseUrl() now skips empty-string aliases (not just undefined), so
    NEXT_PUBLIC_API_URL= correctly falls through to the legacy alias
  • Added getActiveApiUrlVar() for startup diagnostics/logging
  • getServerApiKey() deprecated in favour of getApiKey()
  • Docs and README updated

Testing

All changes are covered by Vitest unit tests runnable via pnpm test.
No new dependencies. No production behavior changes — all guards are additive.

…, API URL alias chain

mux-labs#696 - validateSendAmount now rejects amounts with >7 decimal places (stroop
precision). Added isStroopPrecise() + STROOP_DECIMALS to validateSendAmount.ts.
xlmFormat.ts gains toStroopPrecision(), isExactStroopAmount(), XLM_MAX_DECIMALS,
and MIN_XLM_AMOUNT. Tests updated with stroop edge cases.

mux-labs#695 - friendbot.ts throws MainnetFriendbotError immediately when network is
'mainnet'. Added assertTestnetOnly() helper and MainnetFriendbotError class so
callers can catch the specific error type. getFriendbotUrl() accepts an optional
network param for backward compat. Tests updated.

mux-labs#694 - env.ts gains assertServerSide() and getServerOnlyEnv(). Both throw at
runtime when called from a browser context (window defined), surfacing any
accidental client-side import of server-only vars (MUX_API_SECRET, MUX_API_KEY,
etc.) visibly in development. Tests simulate a browser environment to verify.

mux-labs#693 - config.ts: exported API_URL_CANDIDATES constant documents the exact
three-alias priority order. getApiBaseUrl() now skips empty-string aliases so a
mis-set deploy that blanks NEXT_PUBLIC_API_URL still picks up the legacy alias.
Added getActiveApiUrlVar() for startup diagnostics. Deprecated getServerApiKey()
as an alias of getApiKey(). Tests and docs updated.
@drips-wave

drips-wave Bot commented Aug 31, 2026

Copy link
Copy Markdown

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

@Jambox11
Jambox11 merged commit a9feedf into mux-labs:staging Aug 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants