Contoh lengkap dan pola integrasi untuk B3 Global Accounts
import {
B3Provider,
SignInWithB3,
useB3
} from "@b3dotfun/sdk/global-account/react";
function AuthExample() {
return (
<B3Provider environment="production">
<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>Memuat akun Anda...</p>
</div>
);
}
return (
<div className="auth-container">
{isAuthenticated ? (
<div className="user-profile">
<img
src={account?.avatarUrl}
alt="Profil"
className="avatar"
/>
<h2>Selamat datang, {account?.displayName}!</h2>
<p>Email: {account?.email}</p>
<button onClick={signOut} className="sign-out-btn">
Keluar
</button>
</div>
) : (
<div className="sign-in-container">
<h2>Masuk ke B3</h2>
<SignInWithB3
provider={{ strategy: "google" }}
partnerId="your-partner-id"
onLoginSuccess={(globalAccount) => {
setAuthError(null);
console.log("Autentikasi berhasil:", globalAccount);
}}
onLoginError={(error) => {
setAuthError(error.message);
console.error("Autentikasi gagal:", error);
}}
/>
<SignInWithB3
provider={{ strategy: "discord" }}
partnerId="your-partner-id"
onLoginSuccess={(globalAccount) => {
setAuthError(null);
console.log("Autentikasi Discord berhasil:", globalAccount);
}}
onLoginError={(error) => {
setAuthError(error.message);
}}
/>
{authError && (
<div className="error-message">
<p>Autentikasi gagal: {authError}</p>
</div>
)}
</div>
)}
</div>
);
}
export default AuthExample;
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", // Kontrak game
"0x...", // Pasar NFT
"0x...", // Kontrak token
];
function GameApp() {
return (
<B3Provider environment="production">
<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>🎮 Game B3 Epik</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>🔐 Masuk</h2>
<p>Hubungkan Akun Global B3 Anda untuk mulai bermain</p>
<div className="auth-options">
<SignInWithB3
provider={{ strategy: "google" }}
partnerId="epic-game-studio"
onLoginSuccess={(account) => {
console.log("Selamat datang di game:", account.displayName);
}}
/>
<SignInWithB3
provider={{ strategy: "discord" }}
partnerId="epic-game-studio"
onLoginSuccess={(account) => {
console.log("Pemain Discord bergabung:", account.displayName);
}}
/>
</div>
</div>
);
}
function WalletConnectionStep() {
const { connect } = useAccountWallet();
return (
<div className="setup-step">
<h2>👛 Hubungkan Dompet</h2>
<p>Hubungkan dompet Anda untuk berinteraksi dengan game</p>
<button onClick={connect} className="connect-wallet-btn">
Hubungkan Dompet
</button>
</div>
);
}
function PermissionStep() {
const gamePermissions = {
approvedTargets: gameContracts,
startDate: new Date(),
endDate: new Date(Date.now() + 7 * 24 * 60 * 60 * 1000), // 7 hari
nativeTokenLimitPerTransaction: 0.001, // Batas ETH kecil untuk gas
};
return (
<div className="setup-step">
<h2>🛡️ Berikan Izin Game</h2>
<p>Izinkan game untuk melakukan aksi atas nama Anda</p>
<div className="permission-details">
<h3>Ini akan mengizinkan game untuk:</h3>
<ul>
<li>✅ Berinteraksi dengan kontrak game</li>
<li>✅ Berdagang NFT atas nama Anda</li>
<li>✅ Menghabiskan hingga 0.001 ETH per transaksi</li>
<li>✅ Berlaku selama 7 hari</li>
</ul>
</div>
<RequestPermissionsButton
chain={b3Chain}
sessionKeyAddress="0x..." // Alamat kunci sesi Anda
permissions={gamePermissions}
onSuccess={() => {
console.log("Izin game diberikan! Memulai game...");
}}
onError={(error) => {
console.error("Pemberian izin gagal:", error);
}}
/>
</div>
);
}
function GameReadyState() {
const { account } = useB3();
const { wallet } = useAccountWallet();
return (
<div className="game-ready">
<h2>🎯 Game Siap!</h2>
<div className="player-stats">
<div className="stat">
<label>Pemain:</label>
<span>{account?.displayName}</span>
</div>
<div className="stat">
<label>Dompet:</label>
<span>{wallet?.address?.substring(0, 6)}...{wallet?.address?.substring(-4)}</span>
</div>
<div className="stat">
<label>Saldo:</label>
<span>{wallet?.balance} ETH</span>
</div>
</div>
<div className="game-actions">
<button className="play-btn">Mulai Bermain</button>
<button className="inventory-btn">Lihat Inventaris</button>
<button className="marketplace-btn">Pasar</button>
</div>
</div>
);
}
export default GameApp;
import {
B3Provider,
SignInWithB3,
useB3,
useAccountAssets
} from "@b3dotfun/sdk/global-account/react";
function EcommerceApp() {
return (
<B3Provider environment="production">
<ShopContainer />
</B3Provider>
);
}
function ShopContainer() {
const { isAuthenticated } = useB3();
return (
<div className="shop-container">
<header className="shop-header">
<h1>🛍️ Pasar NFT B3</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="Profil" className="avatar" />
<div className="dropdown">
<span>{account?.displayName}</span>
<div className="dropdown-content">
<button>Koleksi Saya</button>
<button>Riwayat Pembelian</button>
<button onClick={signOut}>Keluar</button>
</div>
</div>
</div>
) : (
<div className="auth-buttons">
<SignInWithB3
provider={{ strategy: "google" }}
partnerId="nft-marketplace"
onLoginSuccess={(account) => {
console.log("Selamat datang di pasar:", account.displayName);
}}
/>
</div>
)}
</div>
);
}
function AuthenticatedShop() {
const { assets } = useAccountAssets();
return (
<div className="authenticated-shop">
<section className="user-collection">
<h2>Koleksi Anda</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>Pasar</h2>
<MarketplaceGrid />
</section>
</div>
);
}
function GuestShop() {
return (
<div className="guest-shop">
<section className="hero">
<h2>Temukan NFT Luar Biasa</h2>
<p>Masuk untuk mulai mengumpulkan dan berdagang</p>
<SignInWithB3
provider={{ strategy: "google" }}
partnerId="nft-marketplace"
onLoginSuccess={() => {
console.log("Pengguna bergabung dengan pasar!");
}}
/>
</section>
<section className="featured">
<h2>Koleksi Unggulan</h2>
<MarketplaceGrid />
</section>
</div>
);
}
function MarketplaceGrid() {
// Barang pasar tiruan
const items = [
{ id: 1, name: "NFT Keren #1", price: "0.1 ETH", image: "/nft1.jpg" },
{ id: 2, name: "Barang Langka #42", price: "0.5 ETH", image: "/nft2.jpg" },
// ... lebih banyak item
];
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">Beli Sekarang</button>
</div>
))}
</div>
);
}
export default EcommerceApp;
// 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">
<MainScreen />
</B3Provider>
);
}
function MainScreen() {
const { account, isAuthenticated, isLoading } = useB3();
if (isLoading) {
return (
<View style={styles.container}>
<Text>Memuat...</Text>
</View>
);
}
return (
<View style={styles.container}>
{isAuthenticated ? (
<AuthenticatedView account={account} />
) : (
<SignInView />
)}
</View>
);
}
function SignInView() {
return (
<View style={styles.signInContainer}>
<Text style={styles.title}>Selamat Datang di B3 Mobile</Text>
{/* Implementasi React Native akan menggunakan alur otentikasi asli */}
<TouchableOpacity style={styles.signInButton}>
<Text style={styles.buttonText}>Masuk dengan Google</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.signInButton}>
<Text style={styles.buttonText}>Masuk dengan Discord</Text>
</TouchableOpacity>
</View>
);
}
function AuthenticatedView({ account }) {
const { signOut } = useB3();
return (
<View style={styles.authenticatedContainer}>
<Text style={styles.welcomeText}>
Selamat datang, {account?.displayName}!
</Text>
<TouchableOpacity
style={styles.signOutButton}
onPress={signOut}
>
<Text style={styles.buttonText}>Keluar</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;
// 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">
{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>Memuat...</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>Selamat Datang di Aplikasi B3</h1>
<SignInWithB3
provider={{ strategy: "google" }}
partnerId="nextjs-app"
onLoginSuccess={(account) => {
console.log("Sukses autentikasi Next.js:", account);
}}
/>
</div>
);
}
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();
// Hitung kesiapan game
const isGameReady = isAuthenticated && hasPermissions && !isExpired && isConnected;
// Dapatkan aset khusus game (NFT, token)
const gameAssets = assets?.filter(asset =>
asset.contractAddress &&
permissions?.approvedTargets.includes(asset.contractAddress)
) || [];
// Hitung total nilai game
const totalGameValue = gameAssets.reduce((sum, asset) => sum + asset.value, 0);
// Objek status game
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 || [],