Skip to main content

🎯 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

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:

  1. API Key Setup - Complete
  2. Authentication - Complete
  3. Quickstart Tutorial - Complete
  4. React Integration - Complete

Explore Use Cases

Advanced Topics


Need Help?

If you encounter issues: