API Reference
The complete export surface, the headless engine, and what the widget deliberately does not do.
Package @glacislabs/stablegenie-zerodelta. MIT, zero runtime dependencies. The current version and the full changelog are on npm.
Exports
@glacislabs/stablegenie-zerodelta
Components
StableGeniePay · StableGenieSwap · StableGenieExchange · StableGenieRwaExchange · PaymentIsland · StableGenieProvider
Mounting
mount
Theme
lightTheme · darkTheme · resolveTheme
Compliance
CompliancePanel · complianceChecks · complianceView · complianceControlsLine · formatJurisdiction · humanizeComplianceReason
Engine
createEngine · symbolKey
Catalogue
assetClassOf · brokenLaneReason · counterpartTokens · destinationAvailability
Constants
EXECUTABLE_STABLE_ASSETS · STABLE_ASSETS · TRADEABLE_RWA_ASSETS · SUPPORTED_ASSETS · SUPPORTED_CHAIN_IDS
…/core
The framework-agnostic engine — no React, no DOM. Everything above except the components, plus the primitives (address, units, ABI encoding, escrow, route solving, order normalisation, transaction validation, compliance derivation, the API client and the verifier).
…/mount
mount(el, config) for non-React hosts. Returns an unmount function.
…/standalone
The IIFE build. Sets window.StableGenieWidget with mountPay, mountSwap, mountExchange, mountRwaExchange and mountExpress.
Types
StableGenieConfig
The shared config — see Configure
StableGeniePayProps · StableGenieSwapProps · StableGenieExchangeProps · PaymentIslandProps
Per-component props
SupportedAsset
Union of 26 symbols (below)
ExchangeMode
"exchange" | "onramp" | "offramp"
ExchangeProduct
"stable" | "rwa"
ExchangeInput
{ fromChainId: number | null; fromAsset: string | null; toChainId: number | null; toAsset: string | null; amount: string } — what the exchange card holds, as onInputChange reports it; see Configure → Events
PillOpenAs
"modal" | "drawer" — how a variant="pill" card opens; see Configure → The pill
PaymentIslandKind
"pay" | "swap" | "exchange"
SettlementMethod
"stablecoin" | "bank"
MountConfig
Discriminated union on variant: "pay" | "swap" | "exchange" | "rwa"
StableGenieTheme
23 theme tokens — see Theming
SuccessInfo
{ hash: string; verdict: VerifyResult; route: RouteResult }
VerifyResult
{ status: "confirmed" | "mismatch" | "reverted" | "unconfirmed"; reason?: string }
Compliance
The gateway's decision for a quote's wallet pair — status, decision, screened wallets, jurisdiction, applied policies and legislation, risk / flagged / blocking categories, reasons, checkId, expiresAt — plus sourceCountry when your proxy adds it (see The Keyless Proxy)
ComplianceCheck
One control: id (location | screening | risk | asset | limits), label, ok, reasons, evidence
ComplianceView
The derived display state: tone, label, headline, blocked, needsAction, screened
ComplianceTone
"ok" | "warn" | "blocked" | "neutral"
WalletScreen
A standalone /screen/wallet verdict — the direct-settlement gate
SanitizedTxEntry
The display-safe record passed to onTransaction
QuoteBlock
{ blocked: true; category: string; reason: string; message: string }
Catalogue · Availability · BrokenLane
The derived selectable set and why a lane is unavailable
Chain · Token · Route
Registry shapes
Plan · RouteResult · SwapInput
Engine planning shapes. Quote and RouteResult carry compliance?
LinkIdentity · BankPayoutAccount
ZeroDelta Link shapes
Eip1193Provider
The provider interface accepted by config.provider
SupportedAsset
The union bounds what can be named. What is selectable is derived per load — see Configure → Coverage.
The headless engine
createEngine() gives you the routing, encoding and verification layer without any UI. Use it to build your own picker or checkout on top of the same guarantees the widget enforces.
EngineConfig
apiBase
string
/api/widget/v1
apiKey
string
—
getApiKey
() => string | Promise<string>
—
trustedApiOrigin
string
—
fetchImpl
typeof fetch
global fetch
rpcOverrides
Record<number, string>
—
onTransaction
(entry: SanitizedTxEntry) => void
—
Engine
fetchChains()
the enabled chain registry
fetchTokens()
per-chain token addresses and decimals
fetchRoutes()
the published route matrix
fetchRouteHealth()
measured lane health, or null — never rejects
fetchPrices(symbols)
USD prices by upper-cased symbol, for display only — never rejects; an unpriced symbol is absent
fetchQuote(body)
a priced quote, carrying the compliance decision
fetchCatalogue(allowedAssets?, product?)
the selectable Catalogue
fetchPaymentPlan(request, payer, wallet?)
an exact-receive Plan
quoteSwapPreview(swap, owner?)
an exact-in preview
buildSwapPlan(swap, payer, wallet?)
an exact-in Plan
payerNonceBaseline(...)
the pre-broadcast nonce baseline
verifySubmittedTx(...)
a VerifyResult
readBalances(...) · readNativeBalance(...)
wallet balances
recordTransaction(entry)
the sanitized history entry
api · verifier · apiBase
the underlying client, verifier and resolved base
Resource reads are cached for 60 seconds per engine; a wallet screening verdict is held for 5 minutes, because it is a property of the address rather than of the market. fetchCatalogue never rejects: a failed read yields ready: false, which means "not known yet", not "nothing is supported". fetchPrices never rejects either, and a stale snapshot counts as no price — treat its numbers as decoration, never as an input to an amount.
Rendering the compliance decision yourself
If you build your own checkout on …/core, use the same derivation the widget uses rather than reimplementing it — complianceChecks(), complianceView() and CompliancePanel are exported for exactly that. formatJurisdiction(jurisdiction, country) prints the jurisdiction the way the widget and the ZeroDelta app do: the policy region, with the visitor's country beside it when the decision carries sourceCountry (EU · Spain (ES)), and the region alone when it does not. See Configure → Compliance for the rule that governs all of them.
Fees and attribution
The widget takes no fee. There is no fee hook, no integrator string and no revenue-share configuration — what the quote prices is what the payer pays.
From v4.7.0 the widget submits the quote's own partnerId. A quote priced on an API key with special rates carries a partnerId marker that binds that price to the order (wallets, tokens, chains and amounts); the widget passes it verbatim to submitOrder, and the pre-sign validator binds the encoded word to it. A quote without a marker — an ordinary key, or one priced before both wallets were known — is submitted with bytes32(0), exactly as before. The marker is not an integrator setting: you cannot supply or override it. Versions before 4.7.0 always submit bytes32(0), so do not use a key with special rates on them: the order would ask for the special rate with nothing behind it and may remain unfilled.
Known limits
No localisation
Every string is English. There is no locale seam or message catalogue.
No fee or attribution hook
See above.
mount() cannot set a layout
Its variant selects the component; use JSX or the script-tag helpers for pill / wide.
On- and off-ramp are not shipped
mode: "onramp" / "offramp" render a coming-soon panel.
Bank settlement is not shipped
settlement: "bank" parks the same way.
Plume network switching
No wallet_addEthereumChain metadata is bundled for Plume (98866); users add it manually.
Reference proxy rate limiter
In-memory per warm instance — best-effort, not a hard ceiling.
Versioning
Releases are semantic and automated from main. Pin an exact version in production — this component sits in a payment path.
Four majors have carried breaking changes:
4.0.0
Direct settlements are screened, and the compliance decision is disclosed in the UI. Deployments must add screen/wallet to the proxy allow-list or direct settlement fails closed — see The Keyless Proxy.
3.0.0
The exported PayMethod union drops "recommended" and "anyasset"; the default method is "stablecoin". The any-asset funding rail is no longer reachable from the UI.
2.0.0
Closed an API-key leak and readied the package for public npm.
1.0.0
DEFAULT_API_BASE is no longer exported. Hosts passing an absolute apiBase together with an apiKey must now also set trustedApiOrigin, or the key is withheld. Consumers on the default same-origin proxy are unaffected.
Minor and patch releases are listed in the changelog that ships with the package on npm.

