diff --git a/frontend/src/components/WalletConnect.vue b/frontend/src/components/WalletConnect.vue new file mode 100644 index 0000000..2729855 --- /dev/null +++ b/frontend/src/components/WalletConnect.vue @@ -0,0 +1,147 @@ + + + diff --git a/frontend/src/composables/useNostr.ts b/frontend/src/composables/useNostr.ts index ef52b38..cd09d31 100644 --- a/frontend/src/composables/useNostr.ts +++ b/frontend/src/composables/useNostr.ts @@ -23,6 +23,9 @@ interface BotData { winStreak: number bestStreak: number tier: number + satsWon: number + satsWagered: number + hasWallet: boolean } interface NostrWindow { @@ -140,6 +143,9 @@ export function useNostr() { winStreak: 0, bestStreak: 0, tier: 0, + satsWon: 0, + satsWagered: 0, + hasWallet: false, } store('bf_bot', bot.value) @@ -201,6 +207,9 @@ export function useNostr() { winStreak: 0, bestStreak: 0, tier: 0, + satsWon: 0, + satsWagered: 0, + hasWallet: false, } store('bf_bot', bot.value) diff --git a/frontend/src/pages/BotProfilePage.vue b/frontend/src/pages/BotProfilePage.vue index e0dc295..6c58fdc 100644 --- a/frontend/src/pages/BotProfilePage.vue +++ b/frontend/src/pages/BotProfilePage.vue @@ -4,6 +4,7 @@ import { useRoute, useRouter, RouterLink } from 'vue-router' import { useNostr } from '../composables/useNostr' import SpritePreview from '../components/SpritePreview.vue' import HumanPreview from '../components/HumanPreview.vue' +import WalletConnect from '../components/WalletConnect.vue' import type { SpriteCustomization } from '../game/sprites' const route = useRoute() @@ -39,6 +40,9 @@ interface BotStats { totalFights: number rank: number totalBots: number + satsWon: number + satsWagered: number + hasWallet: boolean createdAt: string recentFights: { id: string @@ -421,6 +425,23 @@ const tierClass = (t: number) => `tier-${t}` + +
+
+

{{ stats.satsWon || 0 }}

+

SATS WON

+
+
+

{{ stats.satsWagered || 0 }}

+

WAGERED

+
+
+ + +
+ +
+
diff --git a/frontend/src/pages/JoinBoutPage.vue b/frontend/src/pages/JoinBoutPage.vue index 41b899e..237fc46 100644 --- a/frontend/src/pages/JoinBoutPage.vue +++ b/frontend/src/pages/JoinBoutPage.vue @@ -2,11 +2,14 @@ import { ref, onMounted, onUnmounted } from 'vue' import { useRouter } from 'vue-router' import { useNostr } from '../composables/useNostr' +import { useWallet } from '../composables/useWallet' import SpritePreview from '../components/SpritePreview.vue' import HumanPreview from '../components/HumanPreview.vue' +import WalletConnect from '../components/WalletConnect.vue' const router = useRouter() const { pubkey, bot, profilePicUrl, isLoggedIn, hasExtension, isLoading, login, registerBot, registerHuman, logout } = useNostr() +const { isWalletConnected, payEntryFee, paymentStatus } = useWallet() // Steps: 'login' | 'choose-mode' | 'pick-character' | 'name-bot' | 'bot-setup' | 'add-webhook' | // 'pick-human-avatar' | 'name-human' | 'human-guide' | 'ready' @@ -15,6 +18,7 @@ const isHumanMode = ref(false) const selectedHumanSeed = ref('baby_fighter_1') const error = ref('') const isJoining = ref(false) +const isJoiningRanked = ref(false) const queueCount = ref(0) let pollHandle: ReturnType | null = null @@ -243,6 +247,30 @@ async function fight() { isJoining.value = false } +async function fightRanked() { + if (!bot.value || isJoiningRanked.value) return + isJoiningRanked.value = true + error.value = '' + try { + const paymentId = await payEntryFee(bot.value.id) + const res = await fetch(`/api/queue/join-ranked/${bot.value.id}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify({ paymentId }), + }) + if (res.ok) { + const data = await res.json() + router.push(`/arena/${data.fightId}`) + } else { + const data = await res.json() + error.value = data.error || 'Ranked match failed.' + } + } catch (err) { + error.value = err instanceof Error ? err.message : 'Ranked fight error.' + } + isJoiningRanked.value = false +} + function handleSignOut() { logout() step.value = 'login' @@ -787,6 +815,27 @@ function handleSignOut() { {{ (isHumanMode || bot.isHuman) ? 'Type your answers live against an AI' : 'Queue up against a real AI bot' }}

+ + + + + +