diff --git a/public/UnityBuild/bubbles/Build/prod.data b/public/UnityBuild/bubbles/Build/prod.data
index ddb6bc5..71bef42 100644
Binary files a/public/UnityBuild/bubbles/Build/prod.data and b/public/UnityBuild/bubbles/Build/prod.data differ
diff --git a/public/UnityBuild/bubbles/Build/prod.wasm b/public/UnityBuild/bubbles/Build/prod.wasm
index 8aafdd9..44e6cb1 100644
Binary files a/public/UnityBuild/bubbles/Build/prod.wasm and b/public/UnityBuild/bubbles/Build/prod.wasm differ
diff --git a/src/app/page.tsx b/src/app/page.tsx
index fce235c..d57e86c 100644
--- a/src/app/page.tsx
+++ b/src/app/page.tsx
@@ -3,6 +3,7 @@
import Footer from "@/components/Footer";
import Header from "@/components/Header";
import HeroSection from "@/components/HeroSection";
+import Leaderboard from "@/components/Leaderboard";
// import Leaderboard from "@/components/Leaderboard";
import { PrivyProvider } from "@privy-io/react-auth";
import { toSolanaWalletConnectors } from "@privy-io/react-auth/solana";
@@ -37,7 +38,7 @@ export default function Home() {
- {/* */}
+
>
diff --git a/src/components/GameSelection.tsx b/src/components/GameSelection.tsx
index 147de05..cc8e889 100644
--- a/src/components/GameSelection.tsx
+++ b/src/components/GameSelection.tsx
@@ -22,13 +22,15 @@ export function GameSelection({ games, selectedGame, onSelect }: GameSelectionPr
}`}
onClick={() => game.isAvailable && onSelect(game)}
>
-
+
+
+
{game.name}
{!game.isAvailable && (
Coming Soon
diff --git a/src/components/Leaderboard.tsx b/src/components/Leaderboard.tsx
index 4df8ff2..7c169aa 100644
--- a/src/components/Leaderboard.tsx
+++ b/src/components/Leaderboard.tsx
@@ -71,11 +71,12 @@ export default function Leaderboard() {
{entry.user_data?.username || "Anonymous"}
- {entry.user_data?.bio || "No bio"}
+ {entry.user_data?.bio || "No bio"}
-
+
{entry.wins}
- wins
+ wins
+ wins
(null);
const [isUsernameClaimModalOpen, setIsUsernameClaimModalOpen] = useState(false);
const [newUsername, setNewUsername] = useState("");
+ const [referralId, setReferralId] = useState("");
+
+ const [isReferreesModalOpen, setIsReferreesModalOpen] = useState(false);
+ const [referrees, setReferrees] = useState([]);
+ const [referralStats, setReferralStats] = useState({ earnings: 0, count: 0 });
const modalRef = useRef(null);
const updateSolWallet = () => {
@@ -239,6 +268,7 @@ export default function PrivyButton() {
} else {
setUsername(data.username || "Tester");
setBio(data.bio || "");
+ setRefId(data.ref_id || 0);
// Check if the user has a profile picture URL and update in database
const customProfileUrl = `${API_URL}profile_pics/${user.id}.jpg`;
@@ -341,16 +371,31 @@ export default function PrivyButton() {
}
};
+ useEffect(() => {
+ // Check for referral ID in URL when modal opens
+ if (isUsernameClaimModalOpen) {
+ const urlParams = new URLSearchParams(window.location.search);
+ const refId = urlParams.get('ref');
+ if (refId) {
+ setReferralId(refId);
+ }
+ }
+ }, [isUsernameClaimModalOpen]);
const handleUsernameClaim = async () => {
if (newUsername.trim()) {
- const apiUrl = `${API_URL}register.php?id=${user?.id}&username=${newUsername}`;
try {
- const response = await fetch(apiUrl);
- const data = await response.text();
- if (data == "0") {
+ // First register the user
+ const registerUrl = `${API_URL}register.php?id=${user?.id}&username=${newUsername}&ref_id=${referralId}`;
+ const registerResponse = await fetch(registerUrl);
+ const registerData = await registerResponse.text();
+
+ if (registerData == "0") {
+
+
toast.success("Username claimed successfully!");
setIsUsernameClaimModalOpen(false);
+ fetchUserData(); // Refresh user data to get the new username
} else {
toast.error("Failed to claim username.");
}
@@ -416,6 +461,7 @@ export default function PrivyButton() {
);
setGameImages(gameDataWithImages);
+ fetchReferralData();
} catch (err) {
console.error("Error fetching game history", err);
} finally {
@@ -431,6 +477,32 @@ export default function PrivyButton() {
window.open(`${EXPLORER_ADDRESS_TEMPLATE.replace("{address}",address)}`, "_blank");
};
+ const fetchReferralData = async () => {
+ if (!refId) return;
+
+ try {
+ const response = await axios.get(`${API_URL}get_users_by_referral.php?id=${refId}`);
+ const referreesData = response.data || [];
+
+ // Transform the data to match our Referee interface
+ const transformedReferrees = referreesData.map((ref: ApiReferee) => ({
+ ...ref,
+ profilePicture: ref.x_profile_url,
+ joinedAt: new Date().toISOString(), // Since join date isn't provided in API
+ earnings: 0.01 // Each referral gives 0.01 SOL
+ }));
+
+ setReferrees(transformedReferrees);
+ setReferralStats({
+ earnings: transformedReferrees.length * 0.01, // 0.01 SOL per referral
+ count: transformedReferrees.length
+ });
+ } catch (error) {
+ console.error('Failed to fetch referral data:', error);
+ toast.error('Failed to load referral data');
+ }
+ };
+
return (
<>
{user ? (
@@ -639,6 +711,69 @@ export default function PrivyButton() {
{/* Divider */}
+ {/* Referral Section */}
+ {ENABLE_REFERRAL_SYSTEM && (
+
+
Referral Program
+
+
+
+
Your Referral ID:
+
{user?.id?.slice(0, 8)}
+
{
+ navigator.clipboard.writeText(user?.id || '');
+ toast.success('Referral ID copied!');
+ }}
+ className="text-gray-400 hover:text-white transition p-1"
+ >
+
+
+
+
+
+
{
+ const referralLink = `${window.location.origin}?ref=${user?.id}`;
+ navigator.clipboard.writeText(referralLink);
+ toast.success('Referral link copied!');
+ }}
+ className="bg-[rgb(248,144,22)] hover:bg-[rgb(248,200,100)] text-black px-4 py-2 rounded-md text-sm font-semibold flex items-center gap-2"
+ >
+
+
+
+ Share
+
+
+
+
+
+
Referral Earnings
+
{referralStats.earnings.toFixed(2)} SOL
+
+
+
Total Referrals
+
{referralStats.count}
+
+
+
setIsReferreesModalOpen(true)}
+ className="bg-gray-700 hover:bg-gray-600 text-white px-4 py-2 rounded-md text-sm font-semibold flex items-center gap-2"
+ >
+
+
+
+ View Referrees
+
+
+
+
+ )}
+
+ {/* Divider */}
+
+
{/* Game History Section */}
Game History
@@ -684,18 +819,78 @@ export default function PrivyButton() {
)}
+ {/* Referrees Modal */}
+ {ENABLE_REFERRAL_SYSTEM && isReferreesModalOpen && (
+
+
+
+
Your Referrees
+
setIsReferreesModalOpen(false)}
+ className="text-gray-400 hover:text-white transition duration-300 hover:scale-105"
+ >
+
+
+
+
+
+
+ {referrees.length === 0 ? (
+
No referrees yet.
+ ) : (
+ referrees.map((referee, index) => (
+
+
+
+
+
{referee.username}
+
Joined {referee.joinedAt ? new Date(referee.joinedAt).toLocaleDateString() : 'Recently'}
+
+
+
{referee.earnings} SOL earned
+
+ ))
+ )}
+
+
+
+ )}
+
{/* Username Claim Modal */}
{isUsernameClaimModalOpen && (