Funding Sources
depositOS supports three funding methods: Wallet, Deposit from Anywhere, and Private Deposit.
Wallet
The wallet funding method lets users connect their existing crypto wallet and pay with any token on any supported chain. The widget automatically discovers the optimal route and executes the cross-chain swap to deliver your chosen token at your destination address.
- Supports 20+ EVM chains including Ethereum, Arbitrum, Optimism, Polygon, Base, and more
- Real-time quotes with gas estimates and expected output
- Automatic token approvals, swaps, and bridging
- Live execution progress tracking
User flow: Connect Wallet → Select Source Chain & Token → Get Quote → Approve Token → Execute Swap → Bridge (if cross-chain) → Complete
const config: DepositOSConfig = {
destChain: 42161,
destToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
destAddress: "0xYourAddress",
apiKey: "dos_live_…",
enableWallet: true, // default — can be omitted
};
Wallet mode is enabled by default. Set enableWallet: false to disable it.
Private Deposit
Private deposit mode provides enhanced privacy for users who want to fund your application without creating an on-chain link between their source wallet and the deposit. No wallet connection is required.
- Enhanced privacy — no on-chain link between sender and recipient
- No wallet connection required
- User selects a token, receives deposit details, and sends funds
User flow: Select Token → Get Quote → Receive Deposit Details → Send Funds → Await Confirmation → Complete
const config: DepositOSConfig = {
destChain: 42161,
destToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
destAddress: "0xYourAddress",
apiKey: "dos_live_…",
enablePrivateMode: true,
};
Private deposits are served by the depositOS API — nothing extra to configure on your side.
Deposit from Anywhere
"Deposit from anywhere" lets a user fund your app by sending a token to a deposit address — from any wallet, exchange withdrawal, or custody system. No wallet connection, no signatures, no approvals. depositOS watches the address and routes the funds to your destination.
- No wallet connection required — works from exchange withdrawals and hardware wallets
- Send any amount; the address is not tied to one figure. Deposits too small to cover fees are refunded.
- Same-chain swaps and cross-chain bridging through one flow
- ~64 source chains, including Solana, each with its own depositable tokens
- The user's address is persistent — see below
User flow: Select source chain & token → Get deposit address → Send funds → Track to completion (or automatic refund)
const config: DepositOSConfig = {
destChain: 42161,
destToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
destAddress: "0xYourAddress",
apiKey: "dos_live_…",
userId: "your-user-123", // same user → same deposit address, every visit
enableDepositAnywhere: true,
};
Persistent addresses
Each user gets one deposit address per route — a route being the source chain, source token, destination chain, destination token and recipient. Come back tomorrow, on another device, and the same address is shown.
The address is keyed on config.userId, so pass your own user id. Omit it and the SDK
falls back to an id kept in the browser's localStorage, which won't follow the user to
another device and is shared by everyone using that browser profile.
depositOS stores the address and re-verifies it before handing it back, minting a new one only if the old one stops being valid. Addresses accept repeat deposits: each one is detected and routed independently.
Refund addresses across chains
A failed or refunded deposit must go back to an address on the source chain's own network — a Solana deposit cannot refund to an EVM address, and vice versa.
The widget resolves the refund target in this order:
config.refundAddressesfor the source chain's VM — set this if your app has embedded wallets, and the user is never asked.- Your
destAddress, when it happens to live on that VM. - Otherwise the widget asks the user for their address on that chain.
const config: DepositOSConfig = {
destChain: 42161,
destToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
destAddress: "0xYourTreasury",
apiKey: "dos_live_…",
userId: "your-user-123",
refundAddresses: {
evm: "0xUsersEvmWallet",
svm: "9WzDXwBbmkg8ZTbNMqUxvQRAyrZzDsGYdLVL9zYtAWWM",
},
enableDepositAnywhere: true,
};
So with an EVM destAddress and no refundAddresses, an EVM source refunds silently to
your destination, while a Solana source prompts the user. Supply refundAddresses.svm and
that prompt disappears.
Solana also works as a destination — set destChain to Solana's chain id and
destAddress to a base58 address, and recipients are validated as base58 rather than EVM.
Direction: deposit, transfer, withdraw
config.mode controls where the funds land.
| Mode | Recipient | Who sends |
|---|---|---|
| "deposit" (default) | Locked to your destAddress | The user |
| "transfer" | Entered by the user | The user |
| "withdraw" | Entered by the user | Your app |
In "withdraw" mode the widget mints the address and hands it to you via onWithdrawReady,
then your app sends the funds:
<DepositOSWidget
config={{ ...config, mode: "withdraw" }}
onWithdrawReady={({ depositAddress, amount, fromChainId, fromTokenAddress, recipient }) => {
// your app sends `amount` of `fromTokenAddress` on `fromChainId` to `depositAddress`;
// it arrives at `recipient` on your destination chain.
}}
/>
Provider keys live on the depositOS API and are never exposed to the browser — all traffic is proxied.
Enabling Multiple Methods
You can enable any combination. When multiple methods are enabled, the widget presents a selection screen where the user picks their preferred funding method.
Wallet + private enabled
const config: DepositOSConfig = {
destChain: 42161,
destToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
destAddress: "0xYourAddress",
apiKey: "dos_live_…",
enableWallet: true,
enablePrivateMode: true,
};
Only non-wallet methods
const config: DepositOSConfig = {
destChain: 42161,
destToken: "0xaf88d065e77c8cC2239327C5EDb3A432268e5831",
destAddress: "0xYourAddress",
apiKey: "dos_live_…",
enableWallet: false,
enablePrivateMode: true,
};
Setting a default mode
Use defaultMode to control which method is pre-selected when the widget opens:
const config: DepositOSConfig = {
// ...
enableWallet: true,
enablePrivateMode: true,
defaultMode: "private", // Opens to private deposit by default
};
Valid values are "standard" (default) and "private".