@stridge/gateway-kit
v0.1.0-alpha.79
Published
React widgets and headless hooks for the Stridge Gateway — drop-in deposit and withdraw flows for crypto apps.
Readme
@stridge/gateway-kit
React widgets and headless hooks for the Stridge Gateway — drop-in deposit and withdraw flows for crypto apps.
Links · Website · Documentation · Live demo
Install
pnpm add @stridge/gateway-kitPeer dependencies: react, react-dom, viem and wagmi — all four are required installs. wagmi has to be installed, not mounted: the kit reads its context without throwing when no <WagmiProvider /> sits above it, so withdraw and deposit/transfer-crypto work on hosts that never mount one. Only the deposit/wallet method needs a live connection, because that is where the customer signs the source-chain transfer from their own wallet — and on Solana that signature comes from the source below instead.
Solana execution is bundled into Gateway Kit's private lazy runtime. An EVM-only or SSR import performs no initial Solana work and consumers install no separate Solana package.
Quick start
import { StridgeProvider } from "@stridge/gateway-kit";
import { DepositDialog } from "@stridge/gateway-kit/deposit/dialog";
import { WithdrawDialog } from "@stridge/gateway-kit/withdraw/dialog";
<StridgeProvider
gatewayKey={process.env.NEXT_PUBLIC_STRIDGE_GATEWAY_KEY!}
// `networkId` is the Stridge network id, listed at
// https://api.stridge.com/v1/uda/supported-assets — "9006" is BSC.
asset={{ networkId: "9006", symbol: "USDC" }}
flows={{
deposit: {
// Required — where bridged funds settle (your treasury, or the customer's wallet
// under a same-owner-only gateway-kit configuration).
destination: { address: customerAddress },
// Optional — `gateway/start.owner` for deposit UDAs. Falls back to the active
// source wallet's own address when omitted.
owner: { address: customerAddress },
},
withdraw: {
// Required — `gateway/start.owner` for withdraw UDAs. The kit scopes settlement
// polls against this address.
owner: { address: customerAddress },
},
}}
appearance={{ theme: "dark", accent: "oklch(78% 0.15 240)", radius: "rounded" }}
>
<YourApp />
<DepositDialog />
<WithdrawDialog balance={liveBalance} onSubmit={handleWithdrawSubmit} />
</StridgeProvider>;Open or close the dialogs with useDeposit().open() / useWithdraw().open(). Headless integrators render their own UI via useDeposit(), useDepositState(), useDepositSnapshot() and the withdraw mirrors — the root entry ships no UI, so the headless bundle stays clean. useOptionalDeposit() / useOptionalWithdraw() return null when called outside the provider, for hosts that mount <StridgeProvider /> conditionally (e.g. only after a wallet is connected).
Solana
One wallet family signs at a time, and the host states which.
Omit sourceWallet and nothing changes: the kit reads the connected wagmi account and nothing else, exactly as it always has. Pass it and the choice is explicit and exclusive — "evm" reads only wagmi, "svm" reads only what you hand over, and neither ever falls back to the other. It is one discriminated union, so the EVM arm is { family: "evm" } and nothing more: wagmi's context already holds the address, and reaching for one is a compile error rather than a runtime surprise. { family: "svm", account: null } is a disconnected Solana wallet, a state the kit renders rather than papers over by signing with an EVM account the user never picked.
sourceWallet and flows.deposit.owner are separate inputs. The owner is the gateway account a deposit settles into; the source is the wallet that signs. They meet in one place: with no owner pinned, the active source wallet supplies one, whichever family it belongs to — explicit flows.deposit.owner.address first, then that wallet's address, then dev.userAddressOverride. The fallback is family-aware, so a declared family with nothing connected resolves no owner rather than reaching for a lingering session of the other family, and disconnecting the active wallet clears the owner it supplied. Pin flows.deposit.owner to keep the owner independent of every wallet. flows.withdraw.owner stays required and has no fallback at all.
Omitting flows.deposit.destination.address settles to the owner, so the owner has to be an address the destination network can receive. A Solana wallet settling onto an EVM network — or the reverse — must name destination.address; the driver refuses the deposit and the dialog shows its bootstrap-error card, so a payout that could never land is never surfaced.
Keep the quick-start props unchanged and add the SVM account below. The account stays wallet-vendor-neutral:
Gateway Kit supplies serialized transaction bytes, and the host returns a base58 signature or its raw
bytes through (bytes) => Promise<string | Uint8Array>. A fresh callback reference does not change wallet
identity, and account: null needs no placeholder callback. Core supplies the active source account's
network-501 balances and USD prices. Gateway Kit owns the private Solana endpoint used for reserve checks,
transfer construction, lifetime validation, submission support, and confirmation.
<StridgeProvider
sourceWallet={{ family: "svm", account: solanaAccount }}
>
<YourApp />
<DepositDialog />
</StridgeProvider>;A nonzero Core balance without a valid positive USD price remains visible as "Price unavailable" and cannot be selected. A failed first Core read surfaces a retryable unavailable state; a failed refresh keeps the previous rows visible as stale while blocking new selections and quotes.
Documentation
Full setup, configuration, and integration patterns at docs.stridge.com. A working integration runs at demo.stridge.com.
License
MIT © Stridge Foundation.
