Headless Mode
Build custom UI with core SDK exports, React hooks, and direct API access
Headless Mode
The Nero MPC SDK provides a headless integration path for developers who want to build a completely custom user interface while leveraging the SDK's core MPC, authentication, and session management capabilities. This approach bypasses pre-built UI components by using core SDK exports and React hooks directly.
Core Integration Entities
| Entity | Role | Source |
|---|---|---|
NeroMpcSDK | Primary entry point for managing auth, sessions, and wallets | src/nero-sdk.ts |
NeroProvider | EIP-1193 compatible provider for transaction signing | src/core/provider.ts |
AuthAPI | Handles OAuth flows, email/phone login, and JWT verification | src/transport/api/auth-api.ts |
WalletAPI | Manages wallet metadata and public key retrieval | src/transport/api/wallet-api.ts |
ClientKeyManager | Manages local device keys and secure storage | src/core/client-key-manager.ts |
SDK Initialization
import { NeroMpcSDK } from "@nerochain/mpc-sdk";
const sdk = new NeroMpcSDK({
backendUrl: "https://your-api.example.com",
apiKey: "your-project-api-key",
chainId: 689,
});
await sdk.initialize();Custom Authentication Flow
OAuth
const { url } = await sdk.getOAuthUrl("google", window.location.href);
window.location.href = url;
// After redirect back:
const { user, requiresDKG } = await sdk.handleOAuthCallback(
"google",
code,
state
);Email OTP
await sdk.loginWithEmail("user@example.com");
const result = await sdk.verifyEmailLogin("user@example.com", "123456");Wallet Operations
if (requiresDKG) {
const walletInfo = await sdk.generateWallet();
console.log(walletInfo.eoaAddress);
}
const wallets = await sdk.getWallets();Transaction Signing
const signature = await sdk.signMessage("Hello NERO");
const txSig = await sdk.signTransaction(txParams);
const typedSig = await sdk.signTypedData(domain, types, value);
// Or via EIP-1193 provider
const provider = await sdk.connect();
const accounts = await provider.request({ method: "eth_accounts" });Event Subscription
sdk.on("login", ({ user }) => {
console.log(`User logged in: ${user.id}`);
});
sdk.on("connected", ({ chainId }) => {
console.log(`Connected to chain ${chainId}`);
});
sdk.once("initialized", () => {
console.log("SDK ready");
});Protocol-Specific Considerations
DKLS Protocol (Default): Operates over HTTP with direct signing. Suitable for standard EOA wallets.
Pedersen DKG Protocol: Requires WebSocket (wsUrl) for real-time coordination. Produces ERC-4337 smart contract wallets.
const sdk = new NeroMpcSDK({
backendUrl: "https://your-api.example.com",
wsUrl: "wss://your-ws.example.com",
protocol: "pedersen",
});Security Considerations
Sensitive Data Handling: Recovery seeds or device keys managed by ClientKeyManager must never be exposed in the UI layer or logged to external services.
Secure Storage: The SDK defaults to IndexedDBStorage. Ensure your environment supports this or provide a custom SecureKeyStorage implementation.
Transaction Verification: Since pre-built confirmation modals are bypassed, your custom UI must clearly display transaction details (to, value, data) to the user before calling signing methods.
const displayTx = {
to: txParams.to,
value: ethers.formatEther(txParams.value),
data: txParams.data,
gas: txParams.gas?.toString(),
};
// User reviews displayTx in custom UI...
const signature = await sdk.signTransaction(txParams);Pre-built Components (Modal Path)
If you prefer ready-made UI, the @nerochain/mpc-sdk/modal module provides LoginModal and LoginButton components with built-in OAuth flows and wallet discovery. The LoginModal supports:
| Prop | Type | Default | Description |
|---|---|---|---|
isOpen | boolean | required | Controls modal visibility |
onClose | () => void | required | Called when modal is dismissed |
onLogin | (provider: OAuthProvider) => Promise<void> | required | Triggered when social provider button clicked |
providers | OAuthProvider[] | ["google", "github", "apple"] | OAuth providers to render |
title | string | "Sign in" | Heading text |
logo | string | undefined | Custom logo URL |
showWallets | boolean | true | Whether to show wallet section |
onWalletConnect | (wallet: DetectedWallet) => void | undefined | Called when user selects detected browser wallet |
Supported OAuth Providers
| Provider | Display Name | Icon Color |
|---|---|---|
"google" | #4285F4 | |
"github" | GitHub | #24292e |
"apple" | Apple | #000000 |
"discord" | Discord | #5865F2 |
"line" | LINE | #00B900 |
"linkedin" | #0A66C2 | |
"twitter" | #1DA1F2 | |
"wechat" | #07C160 | |
"facebook" | #1877F2 |
Theme System
The SDK includes a React-based theme system for customizing pre-built components.
UIConfig
| Property | Type | Description |
|---|---|---|
appName | string | Name displayed in headers and titles (default: "NERO MPC Wallet") |
logoLight | string | URL or base64 for logo in light mode |
logoDark | string | URL or base64 for logo in dark mode |
mode | ThemeMode | light, dark, or auto |
theme | Partial<Theme> | Custom overrides for colors, spacing, and typography |
Theme Mode Resolution
| UIConfig.mode | System Preference | resolvedMode |
|---|---|---|
'auto' | dark | 'dark' |
'auto' | light | 'light' |
'light' | (ignored) | 'light' |
'dark' | (ignored) | 'dark' |
Theme Hooks
useTheme()-- Returns fullThemeContextValueincluding theme object and modeuseThemeColors()-- Returns only thetheme.colorsobjectuseResolvedMode()-- Returns currently active mode (lightordark), resolvingautoto system preference
ThemeContextValue
| Field | Type | Description |
|---|---|---|
theme | Theme | Complete theme object with colors and spacing |
mode | ThemeMode | Raw mode setting |
resolvedMode | 'light' | 'dark' | Computed effective mode |
setMode | (mode: ThemeMode) => void | Updates mode and persists to localStorage |
Theme preferences are saved to localStorage under the key nero-theme-mode.
Wallet Services Plugin
For wallet dashboard features (funding, receiving, balances, history), use the Wallet Services Plugin:
import { createWalletServicesPlugin } from "@nerochain/mpc-sdk/wallet-services";
const walletPlugin = createWalletServicesPlugin({
backendUrl: "https://api.example.com",
chainId: 689,
});
sdk.registerPlugin(walletPlugin);WalletServicesPlugin Interface
| Method | Description |
|---|---|
openFunding(config?: FundingConfig) | Triggers the funding modal for users to add assets |
openReceive(config?: ReceiveConfig) | Displays the receive modal showing address and QR code |
getBalances(address: string) | Retrieves token balances for a wallet address |
getTransactionHistory(address: string) | Fetches historical transactions for the address |
Data Models
interface TokenBalance {
symbol: string;
balance: string;
usdValue?: string;
}
interface TransactionHistoryItem {
id: string;
type: "send" | "receive";
amount: string;
timestamp: number;
status: "pending" | "completed" | "failed";
}External Wallet Adapters
The SDK supports third-party wallets alongside the native MPC wallet through a standardized adapter interface.
Available Adapters
| Feature | MetaMaskAdapter | CoinbaseAdapter | WalletConnectAdapter |
|---|---|---|---|
| SDK Dependency | @metamask/sdk | @coinbase/wallet-sdk | @walletconnect/ethereum-provider |
| Primary Method | window.ethereum | makeWeb3Provider() | EthereumProvider.init() |
| Injected Support | Yes | Yes (via SDK) | No (Remote only) |
| Chain Switching | wallet_switchEthereumChain | wallet_switchEthereumChain | wallet_switchEthereumChain |
| Factory Function | createMetaMaskAdapter() | createCoinbaseAdapter() | createWalletConnectAdapter() |
Adapter Status
| Status | Description |
|---|---|
disconnected | Default state; no active connection |
connecting | Connection attempt is in progress |
connected | Wallet successfully authorized |
errored | Unhandled error occurred |
Adapter Events
| Event | Trigger | Payload |
|---|---|---|
connect | Successful connection | { chainId: number; accounts: string[] } |
disconnect | Wallet disconnected | error?: Error |
accountsChanged | User switched accounts | accounts: string[] |
chainChanged | User switched networks | chainId: number |
error | Adapter-level error | error: Error |
API Reference Summary
| Method | Description |
|---|---|
initialize() | Loads device key, restores session, initializes wallet |
getOAuthUrl(provider, redirectUri) | Returns OAuth URL and state |
handleOAuthCallback(provider, code, state) | Processes OAuth response |
loginWithEmail(email) | Sends OTP/magic link |
verifyEmailLogin(email, code) | Verifies email OTP |
generateWallet() | Triggers DKG/DKLS keygen |
signMessage(message) | Signs raw message (EIP-191) |
signTransaction(txParams) | Signs transaction |
signTypedData(domain, types, value) | Signs EIP-712 data |
connect() | Returns EIP-1193 provider |
disconnect() | Disconnects provider and logs out |