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;
}
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/universal-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/universal-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/universal-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.
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
| 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:
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
NetworkError, // Network issues
} from '@particle-network/universal-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
}
}