Releases: sumfxn/usdh-kit
@usdh-kit/widget@0.1.1
@usdh-kit/sdk@0.3.0
Minor Changes
- a9eb9ab: Add USDH spot market discovery. The kit now exposes
listPairs(),getPair(),
getBook(), andgetMids()for every spot pair where USDH is base or quote,
along with theUsdhPairtype and the underlyinglistUsdhSpotPairs/
findUsdhSpotPairhelpers.InfoClientgains anallMids()method to back
mid-price reads. - ebb0029: Add experimental read-only outcome market reads. The SDK now exposes outcome
metadata, encoded side books, and outcome mids throughcreateUsdhKit, with
runtimeoutcomeMetavalidation and safe outcome id encoding.
Patch Changes
- c2eadbb: Add release safety guardrails, package licenses, and widget dependency metadata.
@usdh-kit/widget@0.1.0
Minor Changes
-
0bd4c4b: fix(sdk): retire SlippageExceededError, memoize useUsdhKit, drop dead code
Three pre-1.0 fixes surfaced by an internal audit:
-
SlippageExceededErrorretired. The post-fill slippage check was
removed in PR #10 when the matcher started enforcing the limit price
pre-fill, but the error class and its READMEs example stuck around.
The export now corresponds to a code path that cannot run, which is
worse than no export. Removed fromerrors.tsandindex.ts. Both
READMEs now demonstrateresult.slippageBps(realised slippage)
instead of catching an error that never throws. Breaking for
anyone importingSlippageExceededError; replace with reading
result.slippageBpsand tighteningslippageBpsif it's higher
than expected. -
useUsdhKitis now memoized. The hook previously re-ran
createUsdhKit(...)on every render, throwing away the kit's
monotonic-nonce closure (lastNonce), the pair-resolver cache, and
any in-flightspotMetarequests. Wrapped inuseMemokeyed on
[network, address, walletClient, signTypedDataAsync, signMessageAsync]
so consumers get a stable kit identity across renders. Adds a
renderHooktest that asserts kit identity is preserved across
rerenders and rebuilt whennetworkchanges. -
Dead code removed.
assertBookHasSidesinkit.tswas
unreachable:midPrice18(book)runs first on the samebook
reference and already throwsNetworkErrorwhen a side is missing.
Removed the helper, its single call site, and the now-unusedL2Book
import. Added a defensive non-zero-pair-index test to
pair-resolver.test.tsto lock the contract thatpair.indexis
the canonical universe index from spotMeta (mainnet has USDH/USDC at
index 230, not array position 0).
-
-
8180915: feat(widget): require network prop, ship CSS bundle and tailwind content paths, add smoke tests
Three changes that should land before the first public npm tag:
-
networkis now required on<USDHSwap />anduseUsdhKit. The
previous default of'mainnet'silently routed swaps to production
if the integrator forgot to pass the prop. Required props move that
decision into the type system. Breaking for anyone relying on
the implicit default. -
The widget renders Tailwind utility classes inline. Without action,
host apps end up with broken styling: any class unique to the widget
(the white "Bridge and swap" button, the red error card, the green
success card, the spinner) is missing from the host's compiled CSS
because Tailwind only scans the host's own source files. Two new
entry points fix this:@usdh-kit/widget/tailwind-content— array of content globs for
Tailwind v3 hosts. Spread into yourtailwind.configso the
widget's classes are emitted alongside yours. (Tailwind v3 does
not deep-merge presetcontentarrays, so a preset wouldn't work
here.)@usdh-kit/widget/styles.css— pre-compiled, minified utility
stylesheet (about 3 KB) for non-Tailwind hosts. Import once at
your app entry.
apps/democonsumestailwind-contentfor dogfood. Build pipeline
adds abuild:cssstep using the Tailwind CLI; preflight is
disabled so the bundle never resets host styles. -
Smoke tests for
<USDHSwap />covering the disconnected, idle,
quote-success, quote-error, and bridge+swap-success paths. wagmi
and the SDK are mocked at the module level so tests are fast and
deterministic. Closes a gap between the heavily-tested SDK and the
previously-untested UI surface.
-
-
9de157c: feat(widget): port USDHSwap from apps/demo
Replaces the placeholder with the working
USDHSwapcomponent that
quotes, bridges, and swaps USDC into USDH end-to-end. Also exports the
useUsdhKithook for custom UI compositions and theHyperNetwork
type. Tailwind classes are inline; a standalone CSS bundle lands in a
follow-up.apps/demonow consumes@usdh-kit/widgetinstead of duplicating the
component locally. -
2eab63f: feat(widget): scaffold package with placeholder component
New
@usdh-kit/widgetpackage. Ships anUSDHSwapplaceholder plus the
build pipeline (tsup ESM+CJS, dts) and peer deps on React 18+, wagmi v2,
viem v2,@tanstack/react-queryv5, and@usdh-kit/sdk. The component
renders a placeholder; the real swap UI is extracted fromapps/demoin
a follow-up. -
5c695c8: feat(widget): light, dark and auto theming with WCAG-AA defaults
The widget palette is now driven by CSS variables defined in the shipped
stylesheet.USDHSwapaccepts a new optionalthemeprop:'auto'(default) — follow the user's system preference via
prefers-color-scheme. The widget re-renders when the OS theme
changes.'dark'— force the dark palette.'light'— force the light palette.
Defaults are tuned for WCAG AA contrast on every body text against the
surface it sits on, in both modes. Integrators can override any token
in their own stylesheet (loaded after the widget's stylesheet) to
customise the palette without forking the widget, e.g..usdh-widget.dark { --usdh-bg: 8 4 16; }
Tokens follow the
rgb(<r> <g> <b>)triple format so Tailwind's
<alpha-value>substitution works as expected with classes such as
bg-usdh-surface/40.The
useEffectiveTheme(theme)hook is also exported for consumers
building their own UI on top of the SDK who want the same
auto-detection behaviour. -
c614acf: feat(widget): UX overhaul and friendly error mapping
Replaces the placeholder swap form with a connected-state UX that integrators can ship without a custom UI layer. Bundles the friendly-error helper.
Widget UX
- Stacked you-pay / you-receive cards with per-side balance display: HyperEVM USDC (the bridge source) and HyperCore USDC (where the swap fills) are both shown and refresh on a 12s cadence.
- Inline slippage chips (0.10 / 0.30 / 0.50 / 1.00 %) plus a custom % input. The chosen value is passed to
kit.swap({ slippageBps })per call. - Auto-quote on amount change (debounced) with the rounded receive estimate displayed without bps drift noise. Stale quotes are cleared once their
validUntilwindow elapses so consumers cannot fill against an outdated mid. - HC-only swap detection: if the user's HyperCore USDC balance already covers the trade plus a slippage + fee buffer, the bridge step is skipped and the button reads "Swap" instead of "Bridge and swap".
- Pre-flight insufficient-balance check disables the swap button and switches its label to "Insufficient balance" before the user signs anything.
- Inline system-address note (
0x2000…0000is Hyperliquid's USDC system address, not phishing) renders alongside the action button when a bridge is required, so the wallet prompt is never the user's first hint about where funds are going. No intermediate confirm step — click "Bridge and swap" goes straight to the wallet. - Wrong-network banner with a
useSwitchChainbutton. Inputs and slippage chips are disabled while the wallet is on the wrong chain so accidental clicks cannot reach the SDK. The network toggle is locked once a swap is in flight. - MAX button on the pay side that snaps to the user's HyperEVM USDC balance.
- Optional Sentral + LiquidTerminal watermark, opt-out via
hideAttribution.
Friendly errors
- New
friendlyError(err: unknown): stringhelper maps common failure modes to short, human-readable strings: viem'sUserRejectedRequestError(and EIP-1193 code 4001 walked up the cause chain),MissingEvmWalletError,BridgeTimeoutError(with explicit "funds are safe" guidance),InsufficientBalanceError(asset-specific),InvalidInputError,SigningError,NotImplementedError, andNetworkError(passes through Hyperliquid protocol-level rejections like "Order would immediately match …" so the user sees the actionable reason, redacts raw RPC payloads otherwise). Used internally for all error display in the widget; also exported for SDK consumers building their own UI.
SDK
- New public exports:
createInfoClient,InfoClient,InfoClientConfig,NSigFigs,L2Book,L2Level,SpotMeta,SpotPair,SpotToken,SpotBalance,SpotClearinghouseState. The widget needs read-only access to spotMeta and the user's HyperCore balance to render the source/destination balance lines; surfacing the existingInfoClientis the smallest change that unblocks any consumer building similar read-only UIs without re-implementing transport.
Tests added for the friendly-error mappings and connected-state UI (chain mismatch banner, slippage chip toggling, insufficient-balance state, HC-only swap path, debounce cancellation, expiry-driven quote clear).
Patch Changes
- 84504fc: Restore the Sentral and LiquidTerminal partner marks in the widget watermark with X links, theme-safe colouring, and a dedicated HyperEVM/HyperCore balance row.
- ead6d35: Add
isBridgeAndSwapError()to narrowBridgeAndSwapErrorinstances and structural copies safely. The widget now uses the guard before unwrapping lifecycle causes, and the docs cover bridge timeout recovery throughBridgeAndSwapError.cause. - 7d1fc55: Add
BridgeAndSwapErrorfor high-level swap orchestration failures. The error preserves the failingphase, underlyingcause, route context, and optional bridge result so apps can render recovery UI without parsing message strings. The widget ...
@usdh-kit/sdk@0.2.0
Minor Changes
-
35ee28e: feat(sdk): bridgeToCore for HyperEVM stables to HyperCore
Adds
kit.bridgeToCore({ asset, amount })that sends an ERC20 transfer of the
asset on HyperEVM to its HyperCore system address (0x20…<tokenIndex BE>),
then pollsspotClearinghouseStateuntil the deposit is reflected. Default
credit timeout is 30s, overridable viawaitForCreditTimeoutMs.New
KitConfig.evmWallet(EvmWalletinterface, minimalsendTransaction)
is required for this method only —swapandgetQuoteare unaffected.Errors:
MissingEvmWalletError,BridgeTimeoutError. -
ead6d35: Add
isBridgeAndSwapError()to narrowBridgeAndSwapErrorinstances and structural copies safely. The widget now uses the guard before unwrapping lifecycle causes, and the docs cover bridge timeout recovery throughBridgeAndSwapError.cause. -
7d1fc55: Add
BridgeAndSwapErrorfor high-level swap orchestration failures. The error preserves the failingphase, underlyingcause, route context, and optional bridge result so apps can render recovery UI without parsing message strings. The widget now unwraps this error for friendly copy, and the docs clarifypreflightSwap,bridgeAndSwap, progress events, and lifecycle error handling. -
0bd4c4b: fix(sdk): retire SlippageExceededError, memoize useUsdhKit, drop dead code
Three pre-1.0 fixes surfaced by an internal audit:
-
SlippageExceededErrorretired. The post-fill slippage check was
removed in PR #10 when the matcher started enforcing the limit price
pre-fill, but the error class and its READMEs example stuck around.
The export now corresponds to a code path that cannot run, which is
worse than no export. Removed fromerrors.tsandindex.ts. Both
READMEs now demonstrateresult.slippageBps(realised slippage)
instead of catching an error that never throws. Breaking for
anyone importingSlippageExceededError; replace with reading
result.slippageBpsand tighteningslippageBpsif it's higher
than expected. -
useUsdhKitis now memoized. The hook previously re-ran
createUsdhKit(...)on every render, throwing away the kit's
monotonic-nonce closure (lastNonce), the pair-resolver cache, and
any in-flightspotMetarequests. Wrapped inuseMemokeyed on
[network, address, walletClient, signTypedDataAsync, signMessageAsync]
so consumers get a stable kit identity across renders. Adds a
renderHooktest that asserts kit identity is preserved across
rerenders and rebuilt whennetworkchanges. -
Dead code removed.
assertBookHasSidesinkit.tswas
unreachable:midPrice18(book)runs first on the samebook
reference and already throwsNetworkErrorwhen a side is missing.
Removed the helper, its single call site, and the now-unusedL2Book
import. Added a defensive non-zero-pair-index test to
pair-resolver.test.tsto lock the contract thatpair.indexis
the canonical universe index from spotMeta (mainnet has USDH/USDC at
index 230, not array position 0).
-
-
c614acf: feat(widget): UX overhaul and friendly error mapping
Replaces the placeholder swap form with a connected-state UX that integrators can ship without a custom UI layer. Bundles the friendly-error helper.
Widget UX
- Stacked you-pay / you-receive cards with per-side balance display: HyperEVM USDC (the bridge source) and HyperCore USDC (where the swap fills) are both shown and refresh on a 12s cadence.
- Inline slippage chips (0.10 / 0.30 / 0.50 / 1.00 %) plus a custom % input. The chosen value is passed to
kit.swap({ slippageBps })per call. - Auto-quote on amount change (debounced) with the rounded receive estimate displayed without bps drift noise. Stale quotes are cleared once their
validUntilwindow elapses so consumers cannot fill against an outdated mid. - HC-only swap detection: if the user's HyperCore USDC balance already covers the trade plus a slippage + fee buffer, the bridge step is skipped and the button reads "Swap" instead of "Bridge and swap".
- Pre-flight insufficient-balance check disables the swap button and switches its label to "Insufficient balance" before the user signs anything.
- Inline system-address note (
0x2000…0000is Hyperliquid's USDC system address, not phishing) renders alongside the action button when a bridge is required, so the wallet prompt is never the user's first hint about where funds are going. No intermediate confirm step — click "Bridge and swap" goes straight to the wallet. - Wrong-network banner with a
useSwitchChainbutton. Inputs and slippage chips are disabled while the wallet is on the wrong chain so accidental clicks cannot reach the SDK. The network toggle is locked once a swap is in flight. - MAX button on the pay side that snaps to the user's HyperEVM USDC balance.
- Optional Sentral + LiquidTerminal watermark, opt-out via
hideAttribution.
Friendly errors
- New
friendlyError(err: unknown): stringhelper maps common failure modes to short, human-readable strings: viem'sUserRejectedRequestError(and EIP-1193 code 4001 walked up the cause chain),MissingEvmWalletError,BridgeTimeoutError(with explicit "funds are safe" guidance),InsufficientBalanceError(asset-specific),InvalidInputError,SigningError,NotImplementedError, andNetworkError(passes through Hyperliquid protocol-level rejections like "Order would immediately match …" so the user sees the actionable reason, redacts raw RPC payloads otherwise). Used internally for all error display in the widget; also exported for SDK consumers building their own UI.
SDK
- New public exports:
createInfoClient,InfoClient,InfoClientConfig,NSigFigs,L2Book,L2Level,SpotMeta,SpotPair,SpotToken,SpotBalance,SpotClearinghouseState. The widget needs read-only access to spotMeta and the user's HyperCore balance to render the source/destination balance lines; surfacing the existingInfoClientis the smallest change that unblocks any consumer building similar read-only UIs without re-implementing transport.
Tests added for the friendly-error mappings and connected-state UI (chain mismatch banner, slippage chip toggling, insufficient-balance state, HC-only swap path, debounce cancellation, expiry-driven quote clear).