@gizmolab/depositos
v1.10.2
Published
depositOS — embeddable, self-styled cross-chain crypto deposit widget for React. No Tailwind or CSS setup required.
Maintainers
Readme
depositOS Widget
Embeddable cross-chain deposit widget. Lets your users pay from any supported chain via connected wallet, or via a private deposit address, into a fixed destination chain and address that you set. The user cannot change the destination.
Features
- Zero styling setup — self-injects its own scoped stylesheet; no Tailwind, CSS import, or config needed, and it never touches your app's styles
- Clean, modern UX — funding-source tabs, themeable
- Wallet deposits — pay from any chain via connected wallet (cross-chain routing)
- Private deposits — enhanced privacy mode with a deposit address (no wallet needed)
- Cross-chain — 100+ tokens, all major EVM chains + Solana
- Gasless ready — works with permit-enabled tokens
- Customizable — theme, allowed chains/tokens, event tracking
Installation
npm install @gizmolab/depositosReact is the only peer dependency — wallet connectivity (EVM + Solana) is bundled, no extra vendor packages to install. The widget provides its own wallet context internally, so you don't wrap your app in DepositOSWalletProvider; you just call setDynamicEnvironmentId(...) once to enable the connect-wallet flow (see below).
No stylesheet to import. The widget ships fully self-styled: it injects a scoped stylesheet (.depositos-scope) into <head> the first time it opens, so it looks right in any app — with or without Tailwind — and its CSS can't leak into or restyle your page.
Embedding
Hook API (recommended)
Add the provider once, then call openDepositOS() from anywhere:
Step 1: Add the provider
The widget is self-contained — it already provides its own wallet context, so do not wrap it in DepositOSWalletProvider (nesting two Dynamic providers throws). Just set your Dynamic environment ID once, then add DepositOSDepositProvider:
// app/providers.tsx
"use client";
import {
setDynamicEnvironmentId,
DepositOSDepositProvider,
} from "@gizmolab/depositos";
// Enables the connect-wallet flow. Call once, before the widget opens.
setDynamicEnvironmentId(process.env.NEXT_PUBLIC_DYNAMIC_ENV_ID!);
export function Providers({ children }) {
return (
<DepositOSDepositProvider
config={{
destChain: 42161,
destToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
destAddress: "0x...",
apiKey: "dos_live_…", // from the depositOS portal
userId: "your-user-123", // same user → same deposit address, every visit
enablePrivateMode: true,
}}
onSuccess={(txHash) => console.log("Deposit complete!", txHash)}
>
{children}
</DepositOSDepositProvider>
);
}Step 2: Open from any component
import { useDepositOS } from "@gizmolab/depositos";
function DepositButton() {
const { openDepositOS } = useDepositOS();
return <button onClick={() => openDepositOS()}>Deposit</button>;
}Direct component (alternative)
For more control over modal state:
import { DepositOSWidget } from "@gizmolab/depositos";
<DepositOSWidget
config={config}
onClose={() => setOpen(false)}
onSuccess={(txHash) => console.log("Done!", txHash)}
/>Note: The widget provides its own wallet context — do not wrap it in
DepositOSWalletProvider. Just callsetDynamicEnvironmentId(...)once (as above) to enable the connect-wallet flow.
Config options
| Option | Required | Description |
|--------|----------|-------------|
| destChain | Yes | Destination chain ID (e.g. 42161 = Arbitrum). Locked — user cannot change. |
| destToken | Yes | Destination token address on destChain. Locked. |
| destAddress | Yes | Recipient address on destination chain. Locked. |
| apiKey | Yes | Your dos_live_… key from the depositOS portal (required by the hosted API). |
| userId | No | A stable id for your end user. The same userId always gets the same deposit address for a given route. Omit it and the address is tied to a per-browser id instead, which won't follow the user across devices. |
| refundAddresses | No | Per-VM refund defaults { evm, svm }. A refund must land on the source chain's own network. Falls back to destAddress when it lives on that VM, otherwise the user is asked. |
| gizmoFeeBps | No | Platform fee in basis points (default 30). Capped so total fee ≤ 100 bps. |
| integratorFeeBps | No | Your fee in basis points (default 0). |
| orderRef | No | Session/order reference for tracking. |
| theme | No | "light" or "dark". |
| allowedChains | No | Allowlist of source chain IDs. If omitted, all supported chains are allowed. |
| allowedTokens | No | Per-chain allowlist of token addresses. |
| brandingUrl | No | Where the footer branding links to (default: https://deposit-os.com). Pair with customLabels.footerBranding when rebranding. |
| enablePrivateMode | No | Enable private deposit mode toggle (default: false). |
| defaultMode | No | Default mode when widget opens. |
Private Mode
When enablePrivateMode: true, users can toggle between Wallet and Private tabs:
- Wallet: cross-chain swaps via the user's connected wallet.
- Private: a privacy-enhanced deposit-address flow. No wallet connection required — users select tokens, get a quote, then send funds to a deposit address.
Events
If you set apiKey, the widget POSTs a JSON body for each event (no PII) to the depositOS API. Event types: widget_loaded, quote_requested, quote_received, quote_failed, tx_initiated, tx_completed, tx_failed, plus private_* for private mode.
Fee model
- Total fee =
gizmoFeeBps + integratorFeeBps(capped at 100 bps). - Fee is applied by the routing engine and reflected in the quote (user sees "You receive" after fees).
Chain support
- All major EVM chains (Ethereum, Arbitrum, Optimism, Polygon, Base, BNB Chain, Avalanche, zkSync, Linea, Scroll, and more)
- Solana
Headless SDK
Prefer to build your own UI and flow? Import composable hooks + primitives from
@gizmolab/depositos/headless instead of dropping in <DepositOSWidget />.
import {
DepositOSWalletProvider,
EthereumWalletConnectors,
DepositOSProvider,
useWalletTokens, // tokens the connected wallet actually holds
useQuote,
useExecution,
useWalletSync,
useDepositOSState,
} from "@gizmolab/depositos";
function CustomFlow() {
useWalletSync();
useQuote();
const { runExecute } = useExecution();
const { state, dispatch } = useDepositOSState();
const { tokens } = useWalletTokens();
// …render your own UI; pick a token → dispatch SET_SOURCE_CHAIN/SET_SOURCE_TOKEN →
// set amount → runExecute()
}
// Wrap with <DepositOSWalletProvider> → <DepositOSProvider config={…}> → <CustomFlow />Unlike the drop-in widget (which self-provides its wallet context), the headless flow renders your own UI — so here you do wrap in
DepositOSWalletProviderto supply the wallet context yourself.
Exports (@gizmolab/depositos/headless):
- Wallet —
DepositOSWalletProvider,EthereumWalletConnectors,SolanaWalletConnectors - State/context —
DepositOSProvider,useDepositOSContext,useDepositOSState - Hooks —
useWalletTokens,useQuote,useExecution,useWalletSync,useDepositAnywhere,usePrivateSwap,useResolvedConfig,useApiKeyGate - Primitives —
fetchWalletTokens,fetchChains,fetchTokens,fetchQuote,quoteToRoute,executeRoute,setApiBaseUrl,setApiKey,sendEvent,setEventsApiKey,setWalletEnvironmentId, address helpers,SOLANA_CHAIN_ID - UI primitives —
WalletFlow,ChainTokenSelector,TokenSelector,AmountInput,WalletConnect
App API keys & analytics
Set config.apiKey (a dos_live_… key from the depositOS portal). The SDK sends it
as the x-api-key header on every analytics event, so the portal attributes volume
and transactions to your app.
See the full guide with a complete custom-flow example in the docs at /docs/headless-sdk.
Browser support
Modern browsers with ES modules and React 18+.
