Skip to main content

Types

DestinationConfig

interface DestinationConfig {
  address?: string;   // Defaults to ownerAddress
  chainId: number;    // Required — use CHAIN constant
}

DetectedDeposit

interface DetectedDeposit {
  id: string;
  token: TokenType;
  chainId: number;
  amount: string;
  amountUSD: number;
  rawAmount: bigint;
  detectedAt: number;
}

SweepResult

interface SweepResult {
  depositId: string;
  transactionId: string;
  explorerUrl: string;
  status: 'success' | 'failed' | 'pending';
  error?: string;
}

RecoveryResult

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

RefundResult

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.
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

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

// 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.

UATransaction

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

interface TransactionsResponse {
  transactions: UATransaction[];
  page: number;
  pageSize: number;
}

TokenTransactionFilter

interface TokenTransactionFilter {
  chainId: number;   // Chain ID to filter by
  address: string;   // Token contract address
}

TokenTransactionsResponse

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

Other Types

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

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

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

import {
  getChainName,              // getChainName(42161) → "Arbitrum"
  isValidDestinationChain,   // isValidDestinationChain(42161) → 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 feature — discover and connect injected browser wallets without React.
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.
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.
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.
<DepositProvider config={{
  destination: { chainId: CHAIN.BASE },
  uaProjectId: 'your-project-id',
}}>
  <App />
</DepositProvider>

Destination Configuration

Change the sweep destination at runtime.
const { setDestination, currentDestination } = useDepositContext();

setDestination({ chainId: CHAIN.ETHEREUM });
Throws ConfigurationError if the chain ID or address is invalid.

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.
<DepositProvider config={{
  destination: { chainId: CHAIN.BASE },
  notifications: { position: 'bottom-right', durationMs: 6000 },
}}>
  <App />
</DepositProvider>

DepositNotificationsProps

PropertyTypeDefaultDescription
position'top-right' | 'top-left' | 'bottom-right' | 'bottom-left' | 'top-center' | 'bottom-center''top-right'Anchor on screen.
theme'dark' | 'light''dark'Color theme.
durationMsnumber6000Auto-dismiss delay for terminal toasts. 0 disables.
maxnumber5Max simultaneous toasts.
classNamestringExtra classes for the fixed container.
renderItem(n, dismiss) => ReactNodeRender-prop escape hatch (replaces default markup).
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.

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.
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 and Core SDK.

FundingConfig

PropertyTypeDefaultDescription
enabledbooleanfalseMaster switch for the feature.
apiKeystringMoralis API key for direct browser calls. Dev/PoC only — exposes the key. Prefer the hosted default.
proxyUrlstringHosted serviceBase URL of your own reverse proxy. Omit to use Particle’s hosted service.
balanceProviderBalanceProviderReplace balance discovery entirely; apiKey / proxyUrl / hosted default are ignored.
evmRpcUrlsRecord<number, string>Public RPCsPer-chain EVM RPC overrides (native gas checks / send fallback).
solanaRpcUrlstringPublic RPCSolana RPC used to build SPL/native transfers.
minValueUSDnumberClient minValueUSDMinimum USD value for a balance to be offered.
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.

Recovery

Recover funds that are stuck in the intermediary wallet (e.g., due to failed sweeps).
const { stuckFunds, recoverFunds, isRecovering } = useDepositContext();
Or use the built-in UI:
<RecoveryModal isOpen={open} onClose={() => setOpen(false)} />

Refund (Experimental)

Refund is experimental. Auto-refund is disabled by default.
Enable auto-refund to automatically return funds to the source chain when sweeps fail:
<DepositProvider config={{
  destination: { chainId: CHAIN.BASE },
  refund: {
    enabled: true,
    delayMs: 5000,
    maxAttempts: 2,
    refundToSender: true,
  },
}}>
  <App />
</DepositProvider>

RefundConfig

PropertyTypeDefaultDescription
enabledbooleanfalseEnable auto-refund.
delayMsnumber5000Delay before refund attempt.
maxAttemptsnumber2Max refund attempts.
refundToSenderbooleantrueRefund to original sender if detectable.
Manual refund is always available regardless of the auto-refund setting:
const result = await client.refund('deposit-id', 'user_requested');
const { eligible, reason } = await client.canRefund('deposit-id');

Error Handling

All SDK errors extend DepositSDKError:
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';
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
  }
}

Back to Quickstart

Installation, quickstart, and usage patterns.