diff --git a/.a.swp b/.a.swp deleted file mode 100644 index 5e258018..00000000 Binary files a/.a.swp and /dev/null differ diff --git a/.capability.swp b/.capability.swp deleted file mode 100644 index 0286241f..00000000 Binary files a/.capability.swp and /dev/null differ diff --git a/.colored.swp b/.colored.swp deleted file mode 100644 index 1a2a4681..00000000 Binary files a/.colored.swp and /dev/null differ diff --git a/.for.swp b/.for.swp deleted file mode 100644 index 1187de8f..00000000 Binary files a/.for.swp and /dev/null differ diff --git a/.gitignore b/.gitignore index e57f4c17..6a0b2600 100644 --- a/.gitignore +++ b/.gitignore @@ -50,4 +50,6 @@ fix.md test-results/ # Generated OG images apps/docs/public/og/ -.nitro-static/og/ \ No newline at end of file +.nitro-static/og/ +# Editor swap files +*.swp diff --git a/.has.swp b/.has.swp deleted file mode 100644 index 608322b1..00000000 Binary files a/.has.swp and /dev/null differ diff --git a/.if.swp b/.if.swp deleted file mode 100644 index bbaac6f8..00000000 Binary files a/.if.swp and /dev/null differ diff --git a/.prompt,.swp b/.prompt,.swp deleted file mode 100644 index add1c79c..00000000 Binary files a/.prompt,.swp and /dev/null differ diff --git a/.terminal.swp b/.terminal.swp deleted file mode 100644 index ac0ef7b8..00000000 Binary files a/.terminal.swp and /dev/null differ diff --git a/.the.swp b/.the.swp deleted file mode 100644 index 8110e362..00000000 Binary files a/.the.swp and /dev/null differ diff --git a/.uncomment.swp b/.uncomment.swp deleted file mode 100644 index da4f6af3..00000000 Binary files a/.uncomment.swp and /dev/null differ diff --git a/apps/web/src/features/wallet/components/ConnectButton.tsx b/apps/web/src/features/wallet/components/ConnectButton.tsx index 9e69607e..7a5073b0 100644 --- a/apps/web/src/features/wallet/components/ConnectButton.tsx +++ b/apps/web/src/features/wallet/components/ConnectButton.tsx @@ -278,7 +278,7 @@ function WalletModal({ ) const sep7Uri = useMemo(() => { const origin = - typeof window === "undefined" ? "https://so4.markets" : window.location.origin + typeof window === "undefined" ? "https://so4.market" : window.location.origin const callbackUrl = new URL("/", origin).toString() if (pendingTransactionXdr) { diff --git a/apps/web/src/lib/amount.test.ts b/apps/web/src/lib/amount.test.ts index 38fede9f..bdb717ca 100644 --- a/apps/web/src/lib/amount.test.ts +++ b/apps/web/src/lib/amount.test.ts @@ -136,6 +136,13 @@ describe("parseAmount", () => { const result = parseAmount("1.1234567", { decimals: 6 }) expect(result.value).toBe(1.123456) }) + + it("does not lose a unit to floating-point truncation", () => { + // Math.floor(0.57 * 1e7) / 1e7 === 0.5699999 + expect(parseAmount("0.57").value).toBe(0.57) + expect(parseAmount("0.57", { decimals: 2 }).value).toBe(0.57) + expect(parseAmount("0.5799999999").value).toBe(0.5799999) + }) }) }) diff --git a/apps/web/src/lib/amount.ts b/apps/web/src/lib/amount.ts index 41ca0548..1d920958 100644 --- a/apps/web/src/lib/amount.ts +++ b/apps/web/src/lib/amount.ts @@ -99,17 +99,17 @@ export function parseAmount(raw: string, options: ParseAmountOptions = {}): Pars return { value: null, isPartial: false, wasClamped: false } } - const parsed = Number(normalized) + // Enforce decimal precision by truncating the string, not the float: + // Math.floor(0.57 * 1e7) / 1e7 yields 0.5699999 due to binary rounding. + const [intPart, fracPart = ""] = normalized.split(".") + const truncatedFrac = fracPart.slice(0, decimals) + const truncated = Number(truncatedFrac ? `${intPart}.${truncatedFrac}` : intPart) // Guard: NaN or Infinity shouldn't happen with the regex above, but be safe - if (!Number.isFinite(parsed)) { + if (!Number.isFinite(truncated)) { return { value: null, isPartial: false, wasClamped: false } } - // Enforce decimal precision — truncate excess digits - const factor = 10 ** decimals - const truncated = Math.floor(parsed * factor) / factor - // Clamp to maxAmount if provided let finalValue = truncated let wasClamped = false