Skip to main content

Basic Authentication Example

A simple authentication flow with error handling and loading states.
import { 
  B3Provider, 
  SignInWithB3, 
  useB3 
} from "@b3dotfun/sdk/global-account/react";

function AuthExample() {
  return (
    <B3Provider environment="production" partnerId="your-awesome-partner-id">
      <AuthComponent />
    </B3Provider>
  );
}

function AuthComponent() {
  const { account, isAuthenticated, isLoading, signOut } = useB3();
  const [authError, setAuthError] = useState<string | null>(null);

  if (isLoading) {
    return (
      <div className="loading-container">
        <div className="spinner" />
        <p>Loading your account...</p>
      </div>
    );
  }

  return (
    <div className="auth-container">
      {isAuthenticated ? (
        <div className="user-profile">
          <img 
            src={account?.avatarUrl} 
            alt="Profile" 
            className="avatar"
          />
          <h2>Welcome, {account?.displayName}!</h2>
          <p>Email: {account?.email}</p>
          <button onClick={signOut} className="sign-out-btn">
            Sign Out
          </button>
        </div>
      ) : (
        <div className="sign-in-container">
          <h2>Sign in to B3</h2>
          
          <SignInWithB3
            provider={{ strategy: "google" }}
            partnerId="your-partner-id"
            onLoginSuccess={(globalAccount) => {
              setAuthError(null);
              console.log("Authentication successful:", globalAccount);
            }}
            onLoginError={(error) => {
              setAuthError(error.message);
              console.error("Authentication failed:", error);
            }}
          />

          <SignInWithB3
            provider={{ strategy: "discord" }}
            partnerId="your-partner-id"
            onLoginSuccess={(globalAccount) => {
              setAuthError(null);
              console.log("Discord auth successful:", globalAccount);
            }}
            onLoginError={(error) => {
              setAuthError(error.message);
            }}
          />

          {authError && (
            <div className="error-message">
              <p>Authentication failed: {authError}</p>
            </div>
          )}
        </div>
      )}
    </div>
  );
}

export default AuthExample;

Gaming Application Example

Complete example for a gaming application with session keys and permissions.
import {
  B3Provider,
  SignInWithB3,
  RequestPermissionsButton,
  useB3,
  usePermissions,
  useAccountWallet
} from "@b3dotfun/sdk/global-account/react";

const b3Chain = {
  id: 8333,
  name: "B3",
  nativeCurrency: { name: "Ether", symbol: "ETH", decimals: 18 },
  rpc: "https://mainnet-rpc.b3.fun",
};

const gameContracts = [
  "0x9c275ff1634519E9B5449ec79cd939B5F900564d", // Game contract
  "0x...", // NFT marketplace
  "0x...", // Token contract
];

function GameApp() {
  return (
    <B3Provider environment="production" partnerId="your-awesome-partner-id">
      <GameContainer />
    </B3Provider>
  );
}

function GameContainer() {
  const { account, isAuthenticated } = useB3();
  const { hasPermissions, isExpired } = usePermissions();
  const { wallet, isConnected } = useAccountWallet();

  const isGameReady = isAuthenticated && hasPermissions && !isExpired && isConnected;

  return (
    <div className="game-container">
      <header className="game-header">
        <h1>🎮 Epic B3 Game</h1>
        {isAuthenticated && (
          <div className="user-info">
            <img src={account?.avatarUrl} alt="Avatar" className="small-avatar" />
            <span>{account?.displayName}</span>
          </div>
        )}
      </header>

      <main className="game-content">
        {!isAuthenticated ? (
          <AuthenticationStep />
        ) : !isConnected ? (
          <WalletConnectionStep />
        ) : !hasPermissions || isExpired ? (
          <PermissionStep />
        ) : (
          <GameReadyState />
        )}
      </main>
    </div>
  );
}

function AuthenticationStep() {
  return (
    <div className="setup-step">
      <h2>🔐 Sign In</h2>
      <p>Connect your B3 Global Account to start playing</p>
      
      <div className="auth-options">
        <SignInWithB3
          provider={{ strategy: "google" }}
          partnerId="epic-game-studio"
          onLoginSuccess={(account) => {
            console.log("Welcome to the game:", account.displayName);
          }}
        />
        
        <SignInWithB3
          provider={{ strategy: "discord" }}
          partnerId="epic-game-studio"
          onLoginSuccess={(account) => {
            console.log("Discord player joined:", account.displayName);
          }}
        />
      </div>
    </div>
  );
}

function WalletConnectionStep() {
  const { connect } = useAccountWallet();

  return (
    <div className="setup-step">
      <h2>👛 Connect Wallet</h2>
      <p>Connect your wallet to interact with the game</p>
      <button onClick={connect} className="connect-wallet-btn">
        Connect Wallet
      </button>
    </div>
  );
}

function PermissionStep() {
  const gamePermissions = {
    approvedTargets: gameContracts,
    startDate: new Date(),
    endDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 days
    nativeTokenLimitPerTransaction: 0.001, // Small ETH limit for gas
  };

  return (
    <div className="setup-step">
      <h2>🛡️ Grant Game Permissions</h2>
      <p>Allow the game to perform actions on your behalf</p>
      
      <div className="permission-details">
        <h3>This will allow the game to:</h3>
        <ul>
          <li>✅ Interact with game contracts</li>
          <li>✅ Trade NFTs on your behalf</li>
          <li>✅ Spend up to 0.001 ETH per transaction</li>
          <li>✅ Valid for 7 days</li>
        </ul>
      </div>

      <RequestPermissionsButton
        chain={b3Chain}
        sessionKeyAddress="0x..." // Your session key address
        permissions={gamePermissions}
        onSuccess={() => {
          console.log("Game permissions granted! Starting game...");
        }}
        onError={(error) => {
          console.error("Permission grant failed:", error);
        }}
      />
    </div>
  );
}

function GameReadyState() {
  const { account } = useB3();
  const { wallet } = useAccountWallet();
  
  return (
    <div className="game-ready">
      <h2>🎯 Game Ready!</h2>
      <div className="player-stats">
        <div className="stat">
          <label>Player:</label>
          <span>{account?.displayName}</span>
        </div>
        <div className="stat">
          <label>Wallet:</label>
          <span>{wallet?.address?.substring(0, 6)}...{wallet?.address?.substring(-4)}</span>
        </div>
        <div className="stat">
          <label>Balance:</label>
          <span>{wallet?.balance} ETH</span>
        </div>
      </div>
      
      <div className="game-actions">
        <button className="play-btn">Start Playing</button>
        <button className="inventory-btn">View Inventory</button>
        <button className="marketplace-btn">Marketplace</button>
      </div>
    </div>
  );
}

export default GameApp;

E-commerce Application Example

Example showing B3 Global Accounts integration in an e-commerce context.
import {
  B3Provider,
  SignInWithB3,
  useB3,
  useAccountAssets
} from "@b3dotfun/sdk/global-account/react";

function EcommerceApp() {
  return (
    <B3Provider environment="production" partnerId="your-awesome-partner-id">
      <ShopContainer />
    </B3Provider>
  );
}

function ShopContainer() {
  const { isAuthenticated } = useB3();

  return (
    <div className="shop-container">
      <header className="shop-header">
        <h1>🛍️ B3 NFT Marketplace</h1>
        <UserSection />
      </header>

      <main>
        {isAuthenticated ? (
          <AuthenticatedShop />
        ) : (
          <GuestShop />
        )}
      </main>
    </div>
  );
}

function UserSection() {
  const { account, isAuthenticated, signOut } = useB3();

  return (
    <div className="user-section">
      {isAuthenticated ? (
        <div className="user-menu">
          <img src={account?.avatarUrl} alt="Profile" className="avatar" />
          <div className="dropdown">
            <span>{account?.displayName}</span>
            <div className="dropdown-content">
              <button>My Collection</button>
              <button>Purchase History</button>
              <button onClick={signOut}>Sign Out</button>
            </div>
          </div>
        </div>
      ) : (
        <div className="auth-buttons">
          <SignInWithB3
            provider={{ strategy: "google" }}
            partnerId="nft-marketplace"
            onLoginSuccess={(account) => {
              console.log("Welcome to the marketplace:", account.displayName);
            }}
          />
        </div>
      )}
    </div>
  );
}

function AuthenticatedShop() {
  const { assets } = useAccountAssets();

  return (
    <div className="authenticated-shop">
      <section className="user-collection">
        <h2>Your Collection</h2>
        <div className="asset-grid">
          {assets?.map((asset) => (
            <div key={asset.id} className="asset-card">
              <img src={asset.imageUrl} alt={asset.name} />
              <h3>{asset.name}</h3>
              <p className="price">{asset.value} {asset.currency}</p>
            </div>
          ))}
        </div>
      </section>

      <section className="marketplace">
        <h2>Marketplace</h2>
        <MarketplaceGrid />
      </section>
    </div>
  );
}

function GuestShop() {
  return (
    <div className="guest-shop">
      <section className="hero">
        <h2>Discover Amazing NFTs</h2>
        <p>Sign in to start collecting and trading</p>
        
        <SignInWithB3
          provider={{ strategy: "google" }}
          partnerId="nft-marketplace"
          onLoginSuccess={() => {
            console.log("User joined the marketplace!");
          }}
        />
      </section>

      <section className="featured">
        <h2>Featured Collections</h2>
        <MarketplaceGrid />
      </section>
    </div>
  );
}

function MarketplaceGrid() {
  // Mock marketplace items
  const items = [
    { id: 1, name: "Cool NFT #1", price: "0.1 ETH", image: "/nft1.jpg" },
    { id: 2, name: "Rare Item #42", price: "0.5 ETH", image: "/nft2.jpg" },
    // ... more items
  ];

  return (
    <div className="marketplace-grid">
      {items.map((item) => (
        <div key={item.id} className="marketplace-item">
          <img src={item.image} alt={item.name} />
          <h3>{item.name}</h3>
          <p className="price">{item.price}</p>
          <button className="buy-btn">Buy Now</button>
        </div>
      ))}
    </div>
  );
}

export default EcommerceApp;

React Native Example

Example for React Native applications.
// App.tsx (React Native)
import React from 'react';
import { View, Text, TouchableOpacity, StyleSheet } from 'react-native';
import { B3Provider, useB3 } from '@b3dotfun/sdk/global-account/react';

function App() {
  return (
    <B3Provider environment="production" partnerId="your-awesome-partner-id">
      <MainScreen />
    </B3Provider>
  );
}

function MainScreen() {
  const { account, isAuthenticated, isLoading } = useB3();

  if (isLoading) {
    return (
      <View style={styles.container}>
        <Text>Loading...</Text>
      </View>
    );
  }

  return (
    <View style={styles.container}>
      {isAuthenticated ? (
        <AuthenticatedView account={account} />
      ) : (
        <SignInView />
      )}
    </View>
  );
}

function SignInView() {
  return (
    <View style={styles.signInContainer}>
      <Text style={styles.title}>Welcome to B3 Mobile</Text>
      
      {/* React Native implementation would use native auth flows */}
      <TouchableOpacity style={styles.signInButton}>
        <Text style={styles.buttonText}>Sign In with Google</Text>
      </TouchableOpacity>
      
      <TouchableOpacity style={styles.signInButton}>
        <Text style={styles.buttonText}>Sign In with Discord</Text>
      </TouchableOpacity>
    </View>
  );
}

function AuthenticatedView({ account }) {
  const { signOut } = useB3();

  return (
    <View style={styles.authenticatedContainer}>
      <Text style={styles.welcomeText}>
        Welcome, {account?.displayName}!
      </Text>
      
      <TouchableOpacity 
        style={styles.signOutButton}
        onPress={signOut}
      >
        <Text style={styles.buttonText}>Sign Out</Text>
      </TouchableOpacity>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
    backgroundColor: '#f5f5f5',
  },
  signInContainer: {
    padding: 20,
    alignItems: 'center',
  },
  title: {
    fontSize: 24,
    fontWeight: 'bold',
    marginBottom: 30,
  },
  signInButton: {
    backgroundColor: '#007AFF',
    padding: 15,
    borderRadius: 10,
    marginVertical: 10,
    minWidth: 200,
  },
  signOutButton: {
    backgroundColor: '#FF3B30',
    padding: 15,
    borderRadius: 10,
    marginTop: 20,
  },
  buttonText: {
    color: 'white',
    textAlign: 'center',
    fontSize: 16,
    fontWeight: '600',
  },
  authenticatedContainer: {
    alignItems: 'center',
  },
  welcomeText: {
    fontSize: 20,
    marginBottom: 20,
  },
});

export default App;

Next.js App Router Example

Example for Next.js 13+ App Router.
// app/layout.tsx
import { B3Provider } from '@b3dotfun/sdk/global-account/react';
import '@b3dotfun/sdk/index.css';

export default function RootLayout({
  children,
}: {
  children: React.ReactNode;
}) {
  return (
    <html lang="en">
      <body>
        <B3Provider environment="production" partnerId="your-awesome-partner-id">
          {children}
        </B3Provider>
      </body>
    </html>
  );
}

// app/page.tsx
'use client';

import { useB3 } from '@b3dotfun/sdk/global-account/react';
import AuthComponent from './components/AuthComponent';
import Dashboard from './components/Dashboard';

export default function HomePage() {
  const { isAuthenticated, isLoading } = useB3();

  if (isLoading) {
    return <div>Loading...</div>;
  }

  return (
    <main>
      {isAuthenticated ? <Dashboard /> : <AuthComponent />}
    </main>
  );
}

// app/components/AuthComponent.tsx
'use client';

import { SignInWithB3 } from '@b3dotfun/sdk/global-account/react';

export default function AuthComponent() {
  return (
    <div className="auth-container">
      <h1>Welcome to B3 App</h1>
      
      <SignInWithB3
        provider={{ strategy: "google" }}
        partnerId="nextjs-app"
        onLoginSuccess={(account) => {
          console.log("Next.js auth success:", account);
        }}
      />
    </div>
  );
}

Advanced Custom Hook Example

Custom hook that combines multiple B3 features:
import { 
  useB3, 
  usePermissions, 
  useAccountWallet,
  useAccountAssets 
} from "@b3dotfun/sdk/global-account/react";

function useB3GameState() {
  const { account, isAuthenticated } = useB3();
  const { hasPermissions, isExpired, permissions } = usePermissions();
  const { wallet, isConnected } = useAccountWallet();
  const { assets } = useAccountAssets();

  // Calculate game readiness
  const isGameReady = isAuthenticated && hasPermissions && !isExpired && isConnected;
  
  // Get game-specific assets (NFTs, tokens)
  const gameAssets = assets?.filter(asset => 
    asset.contractAddress && 
    permissions?.approvedTargets.includes(asset.contractAddress)
  ) || [];

  // Calculate total game value
  const totalGameValue = gameAssets.reduce((sum, asset) => sum + asset.value, 0);

  // Game state object
  const gameState = {
    player: {
      id: account?.id,
      name: account?.displayName,
      avatar: account?.avatarUrl,
      email: account?.email,
    },
    wallet: {
      address: wallet?.address,
      balance: wallet?.balance,
      chainId: wallet?.chainId,
    },
    permissions: {
      active: hasPermissions && !isExpired,
      expires: permissions?.endDate,
      contracts: permissions?.approvedTargets || [],
    },
    assets: {
      items: gameAssets,
      count: gameAssets.length,
      totalValue: totalGameValue,
    },
    status: {
      authenticated: isAuthenticated,
      connected: isConnected,
      authorized: hasPermissions && !isExpired,
      ready: isGameReady,
    }
  };

  return {
    gameState,
    isGameReady,
    gameAssets,
    totalGameValue,
  };
}

// Usage in a game component
function GameDashboard() {
  const { gameState, isGameReady } = useB3GameState();

  if (!isGameReady) {
    return <GameSetup gameState={gameState} />;
  }

  return (
    <div className="game-dashboard">
      <PlayerInfo player={gameState.player} />
      <WalletInfo wallet={gameState.wallet} />
      <AssetInventory assets={gameState.assets} />
      <GameActions />
    </div>
  );
}

CSS Styling Examples

Example CSS for styling B3 components:
/* Custom B3 component styles */
.b3-auth-container {
  max-width: 400px;
  margin: 0 auto;
  padding: 2rem;
  border-radius: 12px;
  background: linear-gradient(135deg, #007AFF 0%, #4DA6FF 100%);
  color: white;
}

.b3-sign-in-button {
  width: 100%;
  padding: 12px 24px;
  border: none;
  border-radius: 8px;
  background: rgba(255, 255, 255, 0.2);
  color: white;
  font-size: 16px;
  font-weight: 600;
  cursor: pointer;
  transition: all 0.3s ease;
}

.b3-sign-in-button:hover {
  background: rgba(255, 255, 255, 0.3);
  transform: translateY(-2px);
}

.b3-user-profile {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 1rem;
  background: #f8f9fa;
  border-radius: 8px;
  border: 1px solid #e9ecef;
}

.b3-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  object-fit: cover;
}

.b3-permission-card {
  padding: 1.5rem;
  border: 2px solid #007AFF;
  border-radius: 12px;
  background: #f8f9ff;
}

.b3-game-ready {
  text-align: center;
  padding: 2rem;
  background: linear-gradient(135deg, #28a745 0%, #20c997 100%);
  color: white;
  border-radius: 12px;
}
These examples provide comprehensive patterns for integrating B3 Global Accounts into various types of applications. Each example includes proper error handling, loading states, and follows React best practices.

Next Steps

AnySpend SDK

Learn about cross-chain functionality.