Replace truthiness guard with Number.isFinite() so NaN and Infinity are
explicitly rejected rather than silently masked. Zero is now handled by
toLocaleString, which returns '0' correctly. Add test cases for NaN and
Infinity.
The direct cast of Error to Record<string, unknown> is rejected by
TypeScript because the types don't sufficiently overlap. Cast via
unknown first to satisfy the compiler.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
viem's BaseError extends Error, so the instanceof Error branch was
firing and returning error.message before the isRecord branch could
check shortMessage. Check shortMessage first inside instanceof Error
so terse viem messages are shown to users instead of verbose full ones.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace console.warn with a thrown Error when wethReceived <= 0n so any
caller without a return-value check is protected, not just always-leave.spec.ts.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix max-button race: wait for input to be non-empty after clicking Max
(setMax is async, composable calls loadKrkBalance() before setting value)
- Add on-chain confirmation via WETH Transfer event polling (mirrors buyKrk)
so balance query happens after the swap is mined, not just UI-idle
- Use Pick<SellConfig, 'rpcUrl' | 'accountAddress'> since krkAddress is unused
- Add page heading assertion after navigate (consistent with buyKrk)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- recenter.ts: parse isUp from Recentered event logs instead of a
follow-up eth_call that would decode wrong post-recenter state
- recenter.ts: remove hardcoded private key from comment; add blocks>0
guard in mineBlocks; call provider.destroy() to prevent leaked intervals
- market.ts: snapshot KRK balance before buy to compute krkBought as
delta instead of cumulative total; call provider.destroy() on exit;
remove unused withdraw entry from WETH_ABI
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Add Fee Destination section to PRODUCT-TRUTH.md
- Explicitly ban 'fees grow your KRK value' and 'auto-compounding' claims
- Clarify holder value comes from asymmetric slippage, not fee reinvestment
- Fix misleading 'floor always goes up if fee income exceeds sell pressure'
- Update ARCHITECTURE.md feeDestination annotation
- Export waitForReceipt from swap.ts so market.ts and recenter.ts can reuse it
- Add market.ts with roundTripSwap: direct-RPC buy+sell round-trip using ethers Wallet
- Add recenter.ts with triggerRecenter (calls LiquidityManager.recenter()) and mineBlocks (anvil_mine)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Verifies that passive holders are not diluted when new buyers enter.
- Two wallets (Anvil accounts 4 & 5) buy KRK sequentially
- First buyer's balance must remain unchanged after second buy
- Second buyer receives fewer tokens per ETH due to AMM price impact
- Tests core protocol invariant: holding KRK does not dilute position