> ## Documentation Index
> Fetch the complete documentation index at: https://particlenetwork-fccf74d2-chore-updates-0.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Simple Deposit — Reference

> Type definitions, constants, chain utilities, and advanced configuration for the Simple Deposit.

## Types

### DestinationConfig

```typescript theme={null}
interface DestinationConfig {
  address?: string;     // Defaults to ownerAddress
  chainId: number;      // Required — use CHAIN constant
  token?: TokenType;    // Defaults to 'USDC' — see "Destination tokens"
}
```

#### Destination tokens

By default every deposit is delivered as **USDC** on the destination chain. Set
`destination.token` to deliver a different asset; the sweep converts each deposit
into that token and the fiat onramp buys it directly. The token must be
deliverable on the destination chain or the client throws a `ConfigurationError`.

```typescript theme={null}
// Deliver native ETH on Base instead of USDC
destination: { chainId: CHAIN.BASE, token: 'ETH' }
```

Deliverable token × chain matrix:

| Token |  Ethereum  |    Base    |  Arbitrum  |     BNB     |   Solana   |
| ----- | :--------: | :--------: | :--------: | :---------: | :--------: |
| USDC  |      ✓     |      ✓     |      ✓     |      ✓      |      ✓     |
| USDT  |      ✓     |      —     |      ✓     |      ✓      |      ✓     |
| ETH   | ✓ (native) | ✓ (native) | ✓ (native) | ✓ (bridged) |      —     |
| SOL   |      —     |      —     |      —     |      —      | ✓ (native) |

Deliverability mirrors the Universal Account's routable primary assets (Base has
no USDT route, for example). Use `isSupportedDestinationToken(token, chainId)` to
check a combo at runtime.

> **X Layer** is a deposit *source* only — the Universal Account has no X Layer
> primary tokens, so it cannot be used as a sweep destination.

> **Onramp note:** RampNow's fiat "Buy" supports a narrower set than the sweep —
> stablecoins on all chains, but `ETH` only on Ethereum/Base, `BNB` on BNB, and
> `SOL` on Solana. `isOnrampSupported()` / `isOnrampTokenSupported(token, chainId)`
> reflect this; gate "Buy" UI on them.

### DetectedDeposit

```typescript theme={null}
interface DetectedDeposit {
  id: string;
  token: TokenType;
  chainId: number;
  amount: string;
  amountUSD: number;
  rawAmount: bigint;
  detectedAt: number;
}
```

### SweepResult

```typescript theme={null}
interface SweepResult {
  depositId: string;
  transactionId: string;
  explorerUrl: string;
  status: 'success' | 'failed' | 'pending';
  error?: string;
}
```

### RecoveryResult

```typescript theme={null}
interface RecoveryResult {
  token: TokenType;
  chainId: number;
  amount: string;
  amountUSD: number;
  status: 'success' | 'failed' | 'skipped';
  error?: string;
  txHash?: string;
}
```

### RefundResult

```typescript theme={null}
interface RefundResult {
  depositId: string;
  token: TokenType;
  sourceChainId: number;
  amount: string;
  amountUSD: number;
  status: 'pending' | 'processing' | 'success' | 'failed' | 'skipped';
  reason: RefundReason;
  txHash?: string;
  error?: string;
  refundedTo?: string;
  refundedToSender?: boolean;
}
```

### DepositLifecycleEvent

Normalized, serializable view of a deposit at a single lifecycle phase — delivered by the `onDepositEvent` callback and the `deposit:lifecycle` event, and the basis for the notification UI. `id` is stable across phase transitions.

```typescript theme={null}
type DepositPhase = 'detected' | 'processing' | 'credited' | 'failed' | 'below_threshold';

interface DepositLifecycleEvent {
  id: string;
  phase: DepositPhase;
  token: TokenType;
  chainId: number;
  amount: string;
  amountUSD: number;
  destination?: { address: string; chainId: number };
  transactionId?: string; // present on 'credited'
  explorerUrl?: string;   // present on 'credited'
  error?: string;         // present on 'failed'
  timestamp: number;
}

// DepositNotification (from useDepositNotifications) adds `createdAt` / `updatedAt`.
```

### FundingConfig

```typescript theme={null}
interface FundingConfig {
  enabled: boolean;                       // Master switch (default: false)
  apiKey?: string;                        // Moralis key for DIRECT browser calls — dev/PoC only
  proxyUrl?: string;                      // Your own reverse proxy (injects the key server-side)
  balanceProvider?: BalanceProvider;      // Replace balance discovery entirely
  evmRpcUrls?: Record<number, string>;    // Per-chain EVM RPC overrides
  solanaRpcUrl?: string;                  // Solana RPC for building SPL/native transfers
  minValueUSD?: number;                   // Min USD value for a balance to be offered
}
```

### Funding Types

```typescript theme={null}
// A connected browser wallet used as a funding source.
interface FundingWallet {
  evm?: { provider: unknown; address: string };     // EIP-1193 provider + address
  solana?: { provider: unknown; address: string };  // Solana wallet provider + address
}

// Options when transferring a discovered balance.
interface FundOptions {
  rawAmount?: bigint;   // Omit for the gas-adjusted max
}

// Result of a fund-from-wallet transfer.
interface FundingTransferResult {
  txHash: string;
  // …plus chain/token/amount metadata for the submitted transfer
}

// FundingBalance is the descriptor returned by getWalletBalances() — pass one
// straight back into fundFromWallet(). Treat it as opaque; don't construct it by hand.
```

### OnrampConfig

```typescript theme={null}
interface OnrampConfig {
  enabled: boolean;                          // Master switch (default: false)
  apiKey?: string;                           // Your RampNow partner key (pk_live_…); omit to use the SDK default
  mode?: 'overlay' | 'redirect';             // 'overlay' = in-page iframe (emits order events); 'redirect' = new tab (no events). Default 'overlay'
  fiatCurrency?: string;                     // Fiat the user spends, e.g. 'EUR' (default 'USD')
  defaultFiatAmount?: number;                // Pre-fill the fiat amount
  paymentMode?: string;                      // 'card' | 'apple_pay' | 'google_pay' | 'sepa' | …
  widgetUrl?: string;                        // Override the RampNow widget base URL (e.g. a sandbox host)
}
```

| Property            | Type                      | Default                  | Description                                                                                                                                                             |
| ------------------- | ------------------------- | ------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `enabled`           | `boolean`                 | `false`                  | Master switch for the feature.                                                                                                                                          |
| `apiKey`            | `string`                  | *(SDK default)*          | **Optional.** Your RampNow partner key (`pk_live_…`). Omit to use the SDK's built-in key; set it to route through your own partner account (your fees / KYC / limits).  |
| `mode`              | `'overlay' \| 'redirect'` | `'overlay'`              | `'overlay'` = in-page iframe modal (emits order events → activity feed updates). `'redirect'` = open in a new tab (no close button to manage, but **no order events**). |
| `fiatCurrency`      | `string`                  | `'USD'`                  | Fiat currency the user spends (e.g. `'EUR'`).                                                                                                                           |
| `defaultFiatAmount` | `number`                  | —                        | Pre-fill the fiat amount.                                                                                                                                               |
| `paymentMode`       | `string`                  | —                        | Preferred method: `'card'`, `'apple_pay'`, `'google_pay'`, `'sepa'`, …                                                                                                  |
| `widgetUrl`         | `string`                  | `https://app.rampnow.io` | Override the RampNow widget base URL (e.g. a sandbox host). For testing you normally just use a sandbox `apiKey`.                                                       |

### OnrampOrder

The completed-order payload from RampNow, delivered by the `onramp:complete` event and exposed as `lastOrder` from `useOnramp`.

```typescript theme={null}
interface OnrampOrder {
  amount: string;     // Delivered amount
  token: TokenType;   // Delivered token (USDC today)
  // …plus RampNow order metadata (status, id, destination)
}
```

### UATransaction

```typescript theme={null}
interface UATransaction {
  transactionId: string;
  tag: string;
  createdAt: string;
  updatedAt: string;
  targetToken: {
    name: string;
    type: string;
    image: string;
    price: number;
    symbol: string;
    address: string;
    assetId: string;
    chainId: number;
    decimals: number;
    realDecimals: number;
    isPrimaryToken: boolean;
    isSmartRouterSupported: boolean;
  };
  change: {
    amount: string;
    amountInUSD: string;
    from: string;
    to: string;
  };
  detail: {
    redPacketCount: number;
  };
  status: number;
  fromChains: number[];
  toChains: number[];
}
```

### TransactionsResponse

```typescript theme={null}
interface TransactionsResponse {
  transactions: UATransaction[];
  page: number;
  pageSize: number;
}
```

### TokenTransactionFilter

```typescript theme={null}
interface TokenTransactionFilter {
  chainId: number;   // Chain ID to filter by
  address: string;   // Token contract address
}
```

### TokenTransactionsResponse

```typescript theme={null}
interface TokenTransactionsResponse {
  transactions: UATransaction[];
  nextPageToken?: string;  // Cursor for next page (undefined = no more pages)
}
```

### Other Types

```typescript theme={null}
type TokenType = 'ETH' | 'USDC' | 'USDT' | 'BTC' | 'SOL' | 'BNB';

type ClientStatus =
  | 'idle'
  | 'initializing'
  | 'ready'
  | 'watching'
  | 'sweeping'
  | 'error';

type RefundReason =
  | 'sweep_failed'
  | 'user_requested'
  | 'address_type_mismatch'
  | 'below_minimum';

interface DepositAddresses {
  evm: string;
  solana: string;
}
```

***

## Constants

### CHAIN

```typescript theme={null}
import { CHAIN } from '@particle-network/simple-deposit';

CHAIN.ETHEREUM    // 1
CHAIN.OPTIMISM    // 10
CHAIN.BNB         // 56
CHAIN.POLYGON     // 137
CHAIN.MONAD       // 143
CHAIN.SONIC       // 146
CHAIN.XLAYER      // 196
CHAIN.HYPERVM     // 999
CHAIN.MERLIN      // 4200
CHAIN.MANTLE      // 5000
CHAIN.BASE        // 8453
CHAIN.ARBITRUM    // 42161
CHAIN.AVALANCHE   // 43114
CHAIN.LINEA       // 59144
CHAIN.PLASMA      // 9745
CHAIN.BERACHAIN   // 80094
CHAIN.SOLANA      // 101
```

### Defaults

```typescript theme={null}
import {
  DEFAULT_SUPPORTED_TOKENS,      // ['ETH', 'USDC', 'USDT', 'BTC', 'SOL', 'BNB']
  DEFAULT_MIN_VALUE_USD,          // 0.50
  DEFAULT_POLLING_INTERVAL_MS,    // 3000
} from '@particle-network/simple-deposit';
```

### Chain Utilities

```typescript theme={null}
import {
  getChainName,                 // getChainName(42161) → "Arbitrum"
  isValidDestinationChain,      // isValidDestinationChain(42161) → true
  isSupportedDestinationToken,  // isSupportedDestinationToken('ETH', CHAIN.BASE) → true
  isOnrampTokenSupported,       // isOnrampTokenSupported('ETH', CHAIN.BASE) → true
  getAddressType,               // getAddressType(101) → 'solana'
  isValidEvmAddress,            // Validates 0x + 40 hex chars
  isValidSolanaAddress,         // Validates base58 format
  validateAddressForChain,      // Validates address format for chain type
} from '@particle-network/simple-deposit';
```

### Wallet Detection Utilities

Framework-agnostic helpers for the [Fund from Wallet](#fund-from-wallet) feature — discover and connect injected browser wallets without React.

```typescript theme={null}
import {
  detectInjectedEvmWallets,     // EIP-6963 + legacy window.ethereum fallback
  connectInjectedEvm,           // eth_requestAccounts → address
  getEvmAccounts,               // current eth_accounts
  promptEvmAccountSelection,    // wallet_requestPermissions → eth_accounts
  detectInjectedSolanaWallet,   // window.phantom?.solana / window.solana
  connectInjectedSolana,        // connect() → publicKey
  formatUnits, parseUnits,      // smallest-unit ↔ human-readable amount helpers
} from '@particle-network/simple-deposit';
```

***

## Advanced Topics

### Custom Particle Credentials

You can provide your own Particle project ID via the `uaProjectId` config option.

<Warning>
  `uaProjectId` only affects Universal Account operations (smart account initialization and asset queries). The intermediary wallet authentication (JWT + Auth Core session) always uses the SDK's built-in credentials — this is by design and cannot be overridden.
</Warning>

<Info>
  This is useful if you want to handle your own app fees. If you use your own project ID, deposits are subject to a 1% fee going to Particle. Reach out to configure a custom rate and establish a revenue sharing model.
</Info>

<Tip>
  Contact: [Particle Developer Support](https://t.me/particle_developer_bot)
</Tip>

<CodeGroup>
  ```tsx React theme={null}
  <DepositProvider config={{
    destination: { chainId: CHAIN.BASE },
    uaProjectId: 'your-project-id',
  }}>
    <App />
  </DepositProvider>
  ```

  ```typescript Headless theme={null}
  const client = new DepositClient({
    ownerAddress: '0x...',
    intermediaryAddress: '0x...',
    destination: { chainId: CHAIN.BASE },
    uaProjectId: 'your-project-id',
  });
  ```
</CodeGroup>

### Destination Configuration

Change the sweep destination at runtime.

<CodeGroup>
  ```tsx React theme={null}
  const { setDestination, currentDestination } = useDepositContext();

  setDestination({ chainId: CHAIN.ETHEREUM });
  ```

  ```typescript Headless theme={null}
  client.setDestination({ chainId: CHAIN.BASE, address: '0xTreasury...' });
  const dest = client.getDestination(); // { address, chainId }

  // Deliver a non-default token (see "Destination tokens")
  client.setDestination({ chainId: CHAIN.BASE, token: 'ETH' });
  ```
</CodeGroup>

<Note>
  Throws `ConfigurationError` if the chain ID, address, or token is invalid — see the
  [deliverable token × chain matrix](#destination-tokens).
</Note>

### Notifications

Surface deposit progress to your users. Set `notifications: true` on `DepositProvider` to auto-mount the toaster, build a custom UI with the `useDepositNotifications` hook, or go headless with the `onDepositEvent` callback / `deposit:lifecycle` event — all driven by the same `DepositLifecycleEvent`.

<CodeGroup>
  ```tsx React theme={null}
  <DepositProvider config={{
    destination: { chainId: CHAIN.BASE },
    notifications: { position: 'bottom-right', durationMs: 6000 },
  }}>
    <App />
  </DepositProvider>
  ```

  ```typescript Headless theme={null}
  const client = new DepositClient({
    ownerAddress: '0x...',
    intermediaryAddress: '0x...',
    destination: { chainId: CHAIN.BASE },
    onDepositEvent: (e) => console.log(e.phase, e.token, e.amountUSD),
  });
  ```
</CodeGroup>

#### DepositNotificationsProps

| Property     | Type                                                                                              | Default       | Description                                           |
| ------------ | ------------------------------------------------------------------------------------------------- | ------------- | ----------------------------------------------------- |
| `position`   | `'top-right' \| 'top-left' \| 'bottom-right' \| 'bottom-left' \| 'top-center' \| 'bottom-center'` | `'top-right'` | Anchor on screen.                                     |
| `theme`      | `'dark' \| 'light'`                                                                               | `'dark'`      | Color theme.                                          |
| `durationMs` | `number`                                                                                          | `6000`        | Auto-dismiss delay for terminal toasts. `0` disables. |
| `max`        | `number`                                                                                          | `5`           | Max simultaneous toasts.                              |
| `className`  | `string`                                                                                          | —             | Extra classes for the fixed container.                |
| `renderItem` | `(n, dismiss) => ReactNode`                                                                       | —             | Render-prop escape hatch (replaces default markup).   |

<Warning>
  Lifecycle events fire client-side and best-effort — they are **not** a reliable server webhook. Don't use them as the source of truth for crediting funds.
</Warning>

### Fund from Wallet

Let users top up their deposit address from a connected browser wallet (MetaMask / Rabby / Phantom / any injected EIP-1193 or Solana wallet). The SDK discovers cross-chain balances, builds a transfer to the deposit address, and the watcher sweeps it as usual. Balance discovery is **zero-config** (Particle's hosted service — no Moralis key, proxy, or backend). The browser wallet is a funding source only — it never becomes the Universal Account owner/signer.

```typescript theme={null}
const client = new DepositClient({
  ownerAddress: '0x...',
  intermediaryAddress: '0x...',
  authCoreProvider: provider,
  destination: { chainId: CHAIN.BASE },
  funding: { enabled: true },   // ← that's it
});
```

When `funding.enabled` is set, `DepositWidget` automatically shows a "Receive | Fund from wallet" toggle. For a standalone surface use the `FundFromWallet` component, or call `client.getWalletBalances()` / `client.fundFromWallet()` directly — see the [React SDK](/simple-deposit/react-sdk) and [Core SDK](/simple-deposit/core-sdk).

#### FundingConfig

| Property          | Type                     | Default              | Description                                                                                              |
| ----------------- | ------------------------ | -------------------- | -------------------------------------------------------------------------------------------------------- |
| `enabled`         | `boolean`                | `false`              | Master switch for the feature.                                                                           |
| `apiKey`          | `string`                 | —                    | Moralis API key for **direct** browser calls. Dev/PoC only — exposes the key. Prefer the hosted default. |
| `proxyUrl`        | `string`                 | Hosted service       | Base URL of your own reverse proxy. Omit to use Particle's hosted service.                               |
| `balanceProvider` | `BalanceProvider`        | —                    | Replace balance discovery entirely; `apiKey` / `proxyUrl` / hosted default are ignored.                  |
| `evmRpcUrls`      | `Record<number, string>` | Public RPCs          | Per-chain EVM RPC overrides (native gas checks / send fallback).                                         |
| `solanaRpcUrl`    | `string`                 | Public RPC           | Solana RPC used to build SPL/native transfers.                                                           |
| `minValueUSD`     | `number`                 | Client `minValueUSD` | Minimum USD value for a balance to be offered.                                                           |

<Note>
  Balance-source precedence: `balanceProvider` > `apiKey` (direct) > `proxyUrl` > hosted default. Balance discovery covers **Ethereum, BNB Chain, Base, Arbitrum, and Solana**; X Layer is not supported and is skipped during discovery.
</Note>

### Onramp

Let users buy crypto with fiat (card / Apple Pay / bank) via [RampNow](https://rampnow.io), delivered straight to the destination. Onramp bypasses the watcher/sweeper pipeline — RampNow's order events are the source of truth and are forwarded as `onramp:*` events. Zero-config: the SDK ships a default RampNow key, and `@rampnow/sdk` loads lazily only when the onramp opens.

```typescript theme={null}
const client = new DepositClient({
  ownerAddress: '0x...',
  intermediaryAddress: '0x...',
  authCoreProvider: provider,
  destination: { chainId: CHAIN.BASE },
  onramp: { enabled: true },   // ← that's it
});
```

When `onramp.enabled` is set, `DepositWidget` automatically adds a "Buy" tab. For custom placement use `OnrampButton`, the `useOnramp()` hook, or the `OnrampStatusToast` popup — see the [React SDK](/simple-deposit/react-sdk). Headless apps call `client.openOnramp({ amount })` directly — see the [Core SDK](/simple-deposit/core-sdk#onramp-buy-with-fiat-headless).

<Note>
  **Supported chains:** Ethereum, BNB Chain, Base, Arbitrum, and Solana. X Layer is **not** supported — `isOnrampSupported()` returns `false` and the "Buy" UI is disabled with an explanation.
</Note>

<Note>
  **Delivered token:** Onramp always buys **USDC**, matching the token the sweep delivers to the destination.
</Note>

<Warning>
  Order events only flow in `mode: 'overlay'`. A `redirect` tab has no postMessage channel back, so there's nothing to track (no activity-feed updates, no status toast).
</Warning>

### Recovery

Recover funds that are stuck in the intermediary wallet (e.g., due to failed sweeps).

```tsx theme={null}
const { stuckFunds, recoverFunds, isRecovering } = useDepositContext();
```

Or use the built-in UI:

```tsx theme={null}
<RecoveryModal isOpen={open} onClose={() => setOpen(false)} />
```

### Refund (Experimental)

<Warning>
  Refund is **experimental**. Auto-refund is disabled by default.
</Warning>

Enable auto-refund to automatically return funds to the source chain when sweeps fail:

```tsx theme={null}
<DepositProvider config={{
  destination: { chainId: CHAIN.BASE },
  refund: {
    enabled: true,
    delayMs: 5000,
    maxAttempts: 2,
    refundToSender: true,
  },
}}>
  <App />
</DepositProvider>
```

#### RefundConfig

| Property         | Type      | Default | Description                              |
| ---------------- | --------- | ------- | ---------------------------------------- |
| `enabled`        | `boolean` | `false` | Enable auto-refund.                      |
| `delayMs`        | `number`  | `5000`  | Delay before refund attempt.             |
| `maxAttempts`    | `number`  | `2`     | Max refund attempts.                     |
| `refundToSender` | `boolean` | `true`  | Refund to original sender if detectable. |

Manual refund is always available regardless of the auto-refund setting:

```typescript theme={null}
const result = await client.refund('deposit-id', 'user_requested');
const { eligible, reason } = await client.canRefund('deposit-id');
```

### Error Handling

All SDK errors extend `DepositSDKError`:

```typescript theme={null}
import {
  DepositSDKError,       // Base class
  ConfigurationError,    // Invalid config
  AuthenticationError,   // Auth failed
  JwtError,              // JWT service error
  UniversalAccountError, // UA operations failed
  SweepError,            // Sweep failed
  RefundError,           // Refund failed
  FundingError,          // Fund-from-wallet failed
  NetworkError,          // Network issues
} from '@particle-network/simple-deposit';
```

```typescript theme={null}
try {
  await client.initialize();
} catch (error) {
  if (error instanceof ConfigurationError) {
    // Invalid config — check destination chain ID and address
  }
  if (error instanceof JwtError) {
    // JWT service unreachable
  }
  if (error instanceof UniversalAccountError) {
    // UA initialization failed
  }
}
```

***

<CardGroup cols={1}>
  <Card title="Back to Quickstart" icon="arrow-left" href="/simple-deposit/quickstart">
    Installation, quickstart, and usage patterns.
  </Card>
</CardGroup>
