🎯 React Integration Guide
SDK Version
This guide is for BRDZ SDK v1.1.0+ which provides TypeScript declarations and direct method calls without custom hooks.
Prerequisites
- React 18+ (functional components with hooks)
- API Key configured
- Authentication understanding
- Basic TypeScript knowledge (optional)
Project Setup
Install Dependencies
# Create React app
npx create-react-app my-brdz-react-app --template typescript
cd my-brdz-react-app
# Install BRDZ SDK
npm install anantla_sdk
# Install additional dependencies
npm install @types/node dotenv
Environment Configuration
.env.local
# React Environment Variables
REACT_APP_BRDZ_API_BASE=https://api.brdz.link/api
REACT_APP_BRDZ_API_KEY=your_api_key_here
TypeScript Declarations
The SDK already includes TypeScript declarations. Verify they're working:
// src/types/sdk.d.ts (optional - for additional customization)
import type brdzSDK from 'anantla_sdk';
declare global {
interface Window {
brdzSDK: typeof brdzSDK;
}
}
export {};
Context API Setup
SDK Context Provider
src/contexts/SDKContext.tsx
import React, { createContext, useContext, useState, useEffect, ReactNode } from 'react';
import brdzSDK from 'anantla_sdk';
interface User {
id: number;
username: string;
email: string;
// Add other user properties
}
interface SDKContextType {
// SDK State
sdkReady: boolean;
sdkError: string | null;
// Authentication State
isAuthenticated: boolean;
currentUser: User | null;
// Authentication Methods
login: (email: string, password: string) => Promise<any>;
loginWith2FA: (userId: number, code: string) => Promise<any>;
register: (userData: any) => Promise<any>;
logout: () => void;
// Wallet Methods
createWallet: (name: string) => Promise<any>;
getUserWallets: () => Promise<any>;
// AI Methods
processAIRequest: (input: string) => Promise<any>;
// Utility Methods
refreshUserData: () => Promise<void>;
}
const SDKContext = createContext<SDKContextType | undefined>(undefined);
interface SDKProviderProps {
children: ReactNode;
}
export const SDKProvider: React.FC<SDKProviderProps> = ({ children }) => {
// SDK State
const [sdkReady, setSdkReady] = useState(false);
const [sdkError, setSdkError] = useState<string | null>(null);
// Auth State
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [currentUser, setCurrentUser] = useState<User | null>(null);
// Initialize SDK
useEffect(() => {
const initializeSDK = async () => {
try {
console.log('🔄 Initializing BRDZ SDK...');
// Configure SDK
const config = brdzSDK.config;
config.setBaseUrl(process.env.REACT_APP_BRDZ_API_BASE!);
config.setApiKey(process.env.REACT_APP_BRDZ_API_KEY!);
// Check for existing auth token
const savedToken = localStorage.getItem('brdz_auth_token');
const savedUserId = localStorage.getItem('brdz_user_id');
if (savedToken && savedUserId) {
config.setToken(savedToken);
try {
// Verify token is still valid
const auth = brdzSDK.auth;
const profile = await auth.getUserProfile(savedUserId);
setCurrentUser(profile);
setIsAuthenticated(true);
console.log('✅ User restored from saved session');
} catch (error) {
// Token expired, clear saved data
localStorage.removeItem('brdz_auth_token');
localStorage.removeItem('brdz_user_id');
console.log('⚠️ Saved session expired');
}
}
setSdkReady(true);
console.log('✅ BRDZ SDK ready');
} catch (error) {
console.error('❌ SDK initialization failed:', error);
setSdkError(error instanceof Error ? error.message : 'SDK initialization failed');
}
};
initializeSDK();
}, []);
// Authentication Methods
const login = async (email: string, password: string) => {
try {
const auth = brdzSDK.auth;
const result = await auth.loginUser(email, password);
if (result.requires_2fa) {
return {
success: false,
requires_2fa: true,
user_id: result.user_id
};
}
// Save auth data
localStorage.setItem('brdz_auth_token', result.token);
localStorage.setItem('brdz_user_id', result.user_id);
// Update SDK config
const config = brdzSDK.config;
config.setToken(result.token);
// Update state
setCurrentUser(result.user);
setIsAuthenticated(true);
return result;
} catch (error) {
throw error;
}
};
const loginWith2FA = async (userId: number, code: string) => {
try {
const auth = brdzSDK.auth;
const result = await auth.completeLoginWith2FA(userId, code);
// Save auth data
localStorage.setItem('brdz_auth_token', result.token);
localStorage.setItem('brdz_user_id', userId.toString());
// Update SDK config
const config = brdzSDK.config;
config.setToken(result.token);
// Update state
setCurrentUser(result.user);
setIsAuthenticated(true);
return result;
} catch (error) {
throw error;
}
};
const register = async (userData: any) => {
try {
const auth = brdzSDK.auth;
const result = await auth.registerUser(userData);
return result;
} catch (error) {
throw error;
}
};
const logout = () => {
// Clear storage
localStorage.removeItem('brdz_auth_token');
localStorage.removeItem('brdz_user_id');
// Clear SDK config
const config = brdzSDK.config;
config.setToken('');
// Update state
setCurrentUser(null);
setIsAuthenticated(false);
console.log('👋 User logged out');
};
// Wallet Methods
const createWallet = async (name: string) => {
if (!currentUser) throw new Error('User not authenticated');
try {
const cryptoWallet = brdzSDK.cryptoWallet;
const wallet = await cryptoWallet.createWallet({
wallet_name: name,
user_id: currentUser.id
});
return wallet;
} catch (error) {
throw error;
}
};
const getUserWallets = async () => {
if (!currentUser) throw new Error('User not authenticated');
try {
const cryptoWallet = brdzSDK.cryptoWallet;
const wallets = await cryptoWallet.getUserWallets(currentUser.id);
return wallets;
} catch (error) {
throw error;
}
};
// AI Methods
const processAIRequest = async (input: string) => {
if (!currentUser) throw new Error('User not authenticated');
try {
const cryptoWallet = brdzSDK.cryptoWallet;
const result = await cryptoWallet.processAIIntent({
user_input: input,
user_id: currentUser.id
});
return result;
} catch (error) {
throw error;
}
};
const refreshUserData = async () => {
if (!currentUser) return;
try {
const auth = brdzSDK.auth;
const profile = await auth.getUserProfile(currentUser.id.toString());
setCurrentUser(profile);
} catch (error) {
console.error('Failed to refresh user data:', error);
}
};
const contextValue: SDKContextType = {
sdkReady,
sdkError,
isAuthenticated,
currentUser,
login,
loginWith2FA,
register,
logout,
createWallet,
getUserWallets,
processAIRequest,
refreshUserData
};
return (
<SDKContext.Provider value={contextValue}>
{children}
</SDKContext.Provider>
);
};
// Custom hook to use SDK context
export const useSDK = (): SDKContextType => {
const context = useContext(SDKContext);
if (!context) {
throw new Error('useSDK must be used within SDKProvider');
}
return context;
};
JavaScript Version
src/contexts/SDKContext.js
import React, { createContext, useContext, useState, useEffect } from 'react';
import brdzSDK from 'anantla_sdk';
const SDKContext = createContext();
export const SDKProvider = ({ children }) => {
// SDK State
const [sdkReady, setSdkReady] = useState(false);
const [sdkError, setSdkError] = useState(null);
// Auth State
const [isAuthenticated, setIsAuthenticated] = useState(false);
const [currentUser, setCurrentUser] = useState(null);
// Initialize SDK
useEffect(() => {
const initializeSDK = async () => {
try {
console.log('🔄 Initializing BRDZ SDK...');
// Configure SDK
const config = brdzSDK.config;
config.setBaseUrl(process.env.REACT_APP_BRDZ_API_BASE);
config.setApiKey(process.env.REACT_APP_BRDZ_API_KEY);
// Check for existing auth token
const savedToken = localStorage.getItem('brdz_auth_token');
const savedUserId = localStorage.getItem('brdz_user_id');
if (savedToken && savedUserId) {
config.setToken(savedToken);
try {
// Verify token is still valid
const auth = brdzSDK.auth;
const profile = await auth.getUserProfile(savedUserId);
setCurrentUser(profile);
setIsAuthenticated(true);
console.log('✅ User restored from saved session');
} catch (error) {
// Token expired, clear saved data
localStorage.removeItem('brdz_auth_token');
localStorage.removeItem('brdz_user_id');
console.log('⚠️ Saved session expired');
}
}
setSdkReady(true);
console.log('✅ BRDZ SDK ready');
} catch (error) {
console.error('❌ SDK initialization failed:', error);
setSdkError(error.message || 'SDK initialization failed');
}
};
initializeSDK();
}, []);
// Authentication Methods
const login = async (email, password) => {
try {
const auth = brdzSDK.auth;
const result = await auth.loginUser(email, password);
if (result.requires_2fa) {
return {
success: false,
requires_2fa: true,
user_id: result.user_id
};
}
// Save auth data
localStorage.setItem('brdz_auth_token', result.token);
localStorage.setItem('brdz_user_id', result.user_id);
// Update SDK config
const config = brdzSDK.config;
config.setToken(result.token);
// Update state
setCurrentUser(result.user);
setIsAuthenticated(true);
return result;
} catch (error) {
throw error;
}
};
const logout = () => {
// Clear storage
localStorage.removeItem('brdz_auth_token');
localStorage.removeItem('brdz_user_id');
// Clear SDK config
const config = brdzSDK.config;
config.setToken('');
// Update state
setCurrentUser(null);
setIsAuthenticated(false);
console.log('👋 User logged out');
};
// ... other methods similar to TypeScript version
const contextValue = {
sdkReady,
sdkError,
isAuthenticated,
currentUser,
login,
logout,
// ... other methods
};
return (
<SDKContext.Provider value={contextValue}>
{children}
</SDKContext.Provider>
);
};
export const useSDK = () => {
const context = useContext(SDKContext);
if (!context) {
throw new Error('useSDK must be used within SDKProvider');
}
return context;
};
React Components
App Setup
src/App.tsx
import React from 'react';
import { SDKProvider } from './contexts/SDKContext';
import Dashboard from './components/Dashboard';
import LoadingScreen from './components/LoadingScreen';
import './App.css';
const App: React.FC = () => {
return (
<SDKProvider>
<div className="App">
<header className="App-header">
<h1>🚀 BRDZ React App</h1>
</header>
<main>
<Dashboard />
</main>
</div>
</SDKProvider>
);
};
export default App;
Dashboard Component
src/components/Dashboard.tsx
import React from 'react';
import { useSDK } from '../contexts/SDKContext';
import LoginForm from './LoginForm';
import WalletDashboard from './WalletDashboard';
import LoadingScreen from './LoadingScreen';
import ErrorMessage from './ErrorMessage';
const Dashboard: React.FC = () => {
const { sdkReady, sdkError, isAuthenticated } = useSDK();
if (!sdkReady) {
return <LoadingScreen message="Initializing BRDZ SDK..." />;
}
if (sdkError) {
return <ErrorMessage error={sdkError} />;
}
return (
<div className="dashboard">
{isAuthenticated ? (
<WalletDashboard />
) : (
<LoginForm />
)}
</div>
);
};
export default Dashboard;
Login Component
src/components/LoginForm.tsx
import React, { useState } from 'react';
import { useSDK } from '../contexts/SDKContext';
const LoginForm: React.FC = () => {
const { login, loginWith2FA, register } = useSDK();
const [mode, setMode] = useState<'login' | 'register' | '2fa'>('login');
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [pendingUserId, setPendingUserId] = useState<number | null>(null);
// Form states
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [username, setUsername] = useState('');
const [phone, setPhone] = useState('');
const [twoFactorCode, setTwoFactorCode] = useState('');
const handleLogin = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
const result = await login(email, password);
if (result.requires_2fa) {
setMode('2fa');
setPendingUserId(result.user_id);
setError('Please enter your 2FA code');
} else {
console.log('✅ Login successful');
}
} catch (err) {
setError(err instanceof Error ? err.message : 'Login failed');
} finally {
setLoading(false);
}
};
const handle2FALogin = async (e: React.FormEvent) => {
e.preventDefault();
if (!pendingUserId) return;
setLoading(true);
setError(null);
try {
await loginWith2FA(pendingUserId, twoFactorCode);
console.log('✅ 2FA login successful');
} catch (err) {
setError(err instanceof Error ? err.message : '2FA verification failed');
} finally {
setLoading(false);
}
};
const handleRegister = async (e: React.FormEvent) => {
e.preventDefault();
setLoading(true);
setError(null);
try {
await register({
email,
username,
phone,
client_alias: 'React App',
client_type: 'individual',
country_code: 'ID'
});
setMode('login');
setError('Registration successful! Please login.');
} catch (err) {
setError(err instanceof Error ? err.message : 'Registration failed');
} finally {
setLoading(false);
}
};
if (mode === '2fa') {
return (
<div className="auth-container">
<h2>🔒 Two-Factor Authentication</h2>
<p>Enter the 6-digit code from your authenticator app</p>
<form onSubmit={handle2FALogin}>
<input
type="text"
placeholder="123456"
value={twoFactorCode}
onChange={(e) => setTwoFactorCode(e.target.value)}
maxLength={6}
required
/>
<button type="submit" disabled={loading}>
{loading ? '⏳ Verifying...' : '✅ Verify'}
</button>
<button
type="button"
onClick={() => setMode('login')}
className="secondary"
>
← Back to Login
</button>
</form>
{error && <div className="error">{error}</div>}
</div>
);
}
return (
<div className="auth-container">
<div className="auth-tabs">
<button
className={mode === 'login' ? 'active' : ''}
onClick={() => setMode('login')}
>
Login
</button>
<button
className={mode === 'register' ? 'active' : ''}
onClick={() => setMode('register')}
>
Register
</button>
</div>
{mode === 'login' ? (
<form onSubmit={handleLogin}>
<h2>🔐 Login</h2>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<input
type="password"
placeholder="Password"
value={password}
onChange={(e) => setPassword(e.target.value)}
required
/>
<button type="submit" disabled={loading}>
{loading ? '⏳ Logging in...' : '🔐 Login'}
</button>
</form>
) : (
<form onSubmit={handleRegister}>
<h2>📝 Register</h2>
<input
type="text"
placeholder="Username"
value={username}
onChange={(e) => setUsername(e.target.value)}
required
/>
<input
type="email"
placeholder="Email"
value={email}
onChange={(e) => setEmail(e.target.value)}
required
/>
<input
type="tel"
placeholder="Phone (+628123456789)"
value={phone}
onChange={(e) => setPhone(e.target.value)}
required
/>
<button type="submit" disabled={loading}>
{loading ? '⏳ Registering...' : '📝 Register'}
</button>
</form>
)}
{error && <div className="error">{error}</div>}
</div>
);
};
export default LoginForm;
Wallet Dashboard Component
src/components/WalletDashboard.tsx
import React, { useState, useEffect } from 'react';
import { useSDK } from '../contexts/SDKContext';
interface Wallet {
bw_id: number;
wallet_name: string;
created_at: string;
}
const WalletDashboard: React.FC = () => {
const { currentUser, logout, createWallet, getUserWallets, processAIRequest } = useSDK();
const [wallets, setWallets] = useState<Wallet[]>([]);
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const [aiInput, setAiInput] = useState('');
const [aiResponse, setAiResponse] = useState<string>('');
useEffect(() => {
loadWallets();
}, []);
const loadWallets = async () => {
setLoading(true);
try {
const userWallets = await getUserWallets();
setWallets(userWallets);
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to load wallets');
} finally {
setLoading(false);
}
};
const handleCreateWallet = async () => {
const walletName = prompt('Enter wallet name:');
if (!walletName) return;
try {
await createWallet(walletName);
await loadWallets(); // Refresh list
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to create wallet');
}
};
const handleAIRequest = async (e: React.FormEvent) => {
e.preventDefault();
if (!aiInput.trim()) return;
setLoading(true);
try {
const result = await processAIRequest(aiInput);
setAiResponse(result.agent_response?.message || 'No response from AI');
setAiInput('');
} catch (err) {
setError(err instanceof Error ? err.message : 'AI request failed');
} finally {
setLoading(false);
}
};
return (
<div className="wallet-dashboard">
<header className="dashboard-header">
<div className="user-info">
<h2>👋 Welcome, {currentUser?.username}!</h2>
<p>Email: {currentUser?.email}</p>
</div>
<button onClick={logout} className="logout-btn">
🚪 Logout
</button>
</header>
<div className="dashboard-content">
{/* Wallets Section */}
<section className="wallets-section">
<div className="section-header">
<h3>💼 My Wallets ({wallets.length})</h3>
<button onClick={handleCreateWallet}>
➕ Create Wallet
</button>
</div>
{loading && <p>⏳ Loading wallets...</p>}
<div className="wallets-grid">
{wallets.map((wallet) => (
<div key={wallet.bw_id} className="wallet-card">
<h4>{wallet.wallet_name}</h4>
<p>ID: {wallet.bw_id}</p>
<small>Created: {new Date(wallet.created_at).toLocaleDateString()}</small>
</div>
))}
</div>
{wallets.length === 0 && !loading && (
<div className="empty-state">
<p>No wallets found</p>
<button onClick={handleCreateWallet}>
Create your first wallet
</button>
</div>
)}
</section>
{/* AI Assistant Section */}
<section className="ai-section">
<h3>🤖 AI Wallet Assistant</h3>
<form onSubmit={handleAIRequest} className="ai-form">
<input
type="text"
placeholder="Ask AI about your wallets... (e.g., 'show my balances')"
value={aiInput}
onChange={(e) => setAiInput(e.target.value)}
disabled={loading}
/>
<button type="submit" disabled={loading || !aiInput.trim()}>
{loading ? '🤔 Thinking...' : '🚀 Ask AI'}
</button>
</form>
{aiResponse && (
<div className="ai-response">
<h4>💬 AI Response:</h4>
<p>{aiResponse}</p>
</div>
)}
</section>
</div>
{error && (
<div className="error-banner">
<span>❌ {error}</span>
<button onClick={() => setError(null)}>✖</button>
</div>
)}
</div>
);
};
export default WalletDashboard;
Utility Components
src/components/LoadingScreen.tsx
import React from 'react';
interface LoadingScreenProps {
message?: string;
}
const LoadingScreen: React.FC<LoadingScreenProps> = ({
message = "Loading..."
}) => {
return (
<div className="loading-screen">
<div className="loading-spinner">⏳</div>
<p>{message}</p>
</div>
);
};
export default LoadingScreen;
src/components/ErrorMessage.tsx
import React from 'react';
interface ErrorMessageProps {
error: string;
onRetry?: () => void;
}
const ErrorMessage: React.FC<ErrorMessageProps> = ({ error, onRetry }) => {
return (
<div className="error-message">
<h3>❌ Error</h3>
<p>{error}</p>
{onRetry && (
<button onClick={onRetry}>
🔄 Retry
</button>
)}
</div>
);
};
export default ErrorMessage;
Styling
src/App.css
.App {
text-align: center;
}
.App-header {
background-color: #282c34;
padding: 20px;
color: white;
}
.dashboard {
padding: 20px;
max-width: 1200px;
margin: 0 auto;
}
/* Authentication Styles */
.auth-container {
max-width: 400px;
margin: 0 auto;
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.auth-tabs {
display: flex;
margin-bottom: 20px;
}
.auth-tabs button {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
background: #f5f5f5;
cursor: pointer;
}
.auth-tabs button.active {
background: #007bff;
color: white;
}
.auth-container form {
display: flex;
flex-direction: column;
gap: 15px;
}
.auth-container input {
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
font-size: 16px;
}
.auth-container button {
padding: 12px;
background: #007bff;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 16px;
}
.auth-container button:disabled {
background: #ccc;
cursor: not-allowed;
}
.auth-container button.secondary {
background: #6c757d;
}
/* Dashboard Styles */
.wallet-dashboard {
text-align: left;
}
.dashboard-header {
display: flex;
justify-content: space-between;
align-items: center;
padding: 20px;
border-bottom: 1px solid #eee;
}
.logout-btn {
padding: 8px 16px;
background: #dc3545;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.dashboard-content {
display: grid;
gap: 30px;
padding: 20px;
}
.section-header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 20px;
}
.section-header button {
padding: 8px 16px;
background: #28a745;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
/* Wallets Grid */
.wallets-grid {
display: grid;
grid-template-columns: repeat(auto-fill, minmax(250px, 1fr));
gap: 15px;
}
.wallet-card {
padding: 20px;
border: 1px solid #ddd;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.empty-state {
text-align: center;
padding: 40px;
color: #666;
}
/* AI Section */
.ai-form {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
.ai-form input {
flex: 1;
padding: 12px;
border: 1px solid #ddd;
border-radius: 4px;
}
.ai-form button {
padding: 12px 20px;
background: #17a2b8;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.ai-response {
padding: 15px;
background: #f8f9fa;
border-left: 4px solid #17a2b8;
border-radius: 4px;
}
/* Utility Styles */
.loading-screen {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
min-height: 200px;
}
.loading-spinner {
font-size: 48px;
animation: spin 2s linear infinite;
}
@keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
.error {
color: #dc3545;
background: #f8d7da;
padding: 10px;
border-radius: 4px;
margin-top: 15px;
}
.error-banner {
position: fixed;
top: 20px;
right: 20px;
background: #dc3545;
color: white;
padding: 15px;
border-radius: 4px;
display: flex;
align-items: center;
gap: 10px;
z-index: 1000;
}
.error-banner button {
background: none;
border: none;
color: white;
cursor: pointer;
font-size: 18px;
}
Advanced Examples
Custom Hook for 2FA
src/hooks/use2FA.ts
import { useState } from 'react';
import brdzSDK from 'anantla_sdk';
export const use2FA = () => {
const [loading, setLoading] = useState(false);
const [error, setError] = useState<string | null>(null);
const setup2FA = async () => {
setLoading(true);
setError(null);
try {
const twofa = brdzSDK.twofa;
const result = await twofa.setup();
return result;
} catch (err) {
setError(err instanceof Error ? err.message : '2FA setup failed');
throw err;
} finally {
setLoading(false);
}
};
const enable2FA = async (code: string) => {
setLoading(true);
setError(null);
try {
const twofa = brdzSDK.twofa;
const result = await twofa.enable(code);
return result;
} catch (err) {
setError(err instanceof Error ? err.message : '2FA enable failed');
throw err;
} finally {
setLoading(false);
}
};
const check2FAStatus = async () => {
try {
const twofa = brdzSDK.twofa;
const status = await twofa.getStatus();
return status.is_enabled;
} catch (err) {
setError(err instanceof Error ? err.message : 'Failed to check 2FA status');
return false;
}
};
return {
setup2FA,
enable2FA,
check2FAStatus,
loading,
error
};
};
MCP Commerce Component
src/components/MCPCommerce.tsx
import React, { useState } from 'react';
import brdzSDK from 'anantla_sdk';
const MCPCommerce: React.FC = () => {
const [prompt, setPrompt] = useState('');
const [loading, setLoading] = useState(false);
const [step, setStep] = useState(1);
const [orderData, setOrderData] = useState<any>(null);
const handleStep1 = async () => {
setLoading(true);
try {
const mcp = brdzSDK.mcp;
const result = await mcp.step1_detectIntent({ prompt });
console.log('Intent detected:', result);
setStep(2);
} catch (error) {
console.error('Step 1 failed:', error);
} finally {
setLoading(false);
}
};
return (
<div className="mcp-commerce">
<h3>🛒 AI Commerce (MCP)</h3>
<div className="commerce-form">
<textarea
value={prompt}
onChange={(e) => setPrompt(e.target.value)}
placeholder="Tell AI what you want to buy... (e.g., 'I want to buy headphones from tokopedia')"
rows={3}
/>
<button onClick={handleStep1} disabled={loading || !prompt.trim()}>
{loading ? '🔄 Processing...' : '🛍️ Start Shopping'}
</button>
</div>
{step > 1 && (
<div className="commerce-steps">
<p>Step {step}: Product detection completed</p>
{/* Add more steps here */}
</div>
)}
</div>
);
};
export default MCPCommerce;
Testing
Unit Tests Example
src/__tests__/SDKContext.test.tsx
import { render, screen, waitFor } from '@testing-library/react';
import { SDKProvider, useSDK } from '../contexts/SDKContext';
// Mock BRDZ SDK
jest.mock('anantla_sdk', () => ({
config: {
setBaseUrl: jest.fn(),
setApiKey: jest.fn(),
setToken: jest.fn()
},
auth: {
loginUser: jest.fn(),
getUserProfile: jest.fn()
}
}));
const TestComponent = () => {
const { sdkReady, isAuthenticated } = useSDK();
return (
<div>
<div data-testid="sdk-ready">{sdkReady ? 'Ready' : 'Loading'}</div>
<div data-testid="auth-status">{isAuthenticated ? 'Authenticated' : 'Not Authenticated'}</div>
</div>
);
};
describe('SDKContext', () => {
it('initializes SDK properly', async () => {
render(
<SDKProvider>
<TestComponent />
</SDKProvider>
);
await waitFor(() => {
expect(screen.getByTestId('sdk-ready')).toHaveTextContent('Ready');
});
});
});
Best Practices
Error Boundaries
src/components/ErrorBoundary.tsx
import React, { Component, ErrorInfo, ReactNode } from 'react';
interface Props {
children: ReactNode;
}
interface State {
hasError: boolean;
error?: Error;
}
class ErrorBoundary extends Component<Props, State> {
public state: State = {
hasError: false
};
public static getDerivedStateFromError(error: Error): State {
return { hasError: true, error };
}
public componentDidCatch(error: Error, errorInfo: ErrorInfo) {
console.error('Error caught by boundary:', error, errorInfo);
}
public render() {
if (this.state.hasError) {
return (
<div className="error-boundary">
<h2>🚨 Something went wrong</h2>
<p>{this.state.error?.message}</p>
<button onClick={() => window.location.reload()}>
🔄 Reload Page
</button>
</div>
);
}
return this.props.children;
}
}
export default ErrorBoundary;
Performance Optimization
// Use React.memo for expensive components
const WalletCard = React.memo<{ wallet: Wallet }>(({ wallet }) => {
return (
<div className="wallet-card">
<h4>{wallet.wallet_name}</h4>
<p>ID: {wallet.bw_id}</p>
</div>
);
});
// Use useCallback for event handlers
const handleCreateWallet = useCallback(async (name: string) => {
try {
await createWallet(name);
await loadWallets();
} catch (error) {
setError(error.message);
}
}, [createWallet, loadWallets]);
// Use useMemo for expensive calculations
const walletStats = useMemo(() => {
return {
total: wallets.length,
active: wallets.filter(w => w.status === 'active').length,
totalValue: wallets.reduce((sum, w) => sum + (w.balance || 0), 0)
};
}, [wallets]);
Next Steps
You now have a complete React integration with BRDZ SDK:
- ✅ API Key Setup - Complete
- ✅ Authentication - Complete
- ✅ Quickstart Tutorial - Complete
- ✅ React Integration - Complete
Explore Use Cases
- AI Wallet Management - ABSK examples
- Payment Processing - Commerce flows
- Cross-Chain Operations - Multi-blockchain
Advanced Topics
- SDK Reference - Complete API documentation
- Two-Factor Auth - Enhanced security
- Crypto Wallet - Advanced wallet features
Need Help?
If you encounter issues:
- Email: contact@anantla.com
- Contact: BRDZ Contact Form