From b812186b556e794e09026d892e4bd916170f0398 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:32:49 +0100 Subject: [PATCH 01/30] feat(frontend): add Connect Wallet integration on home page - Add ConnectWallet component using Stacks connect - Wire Connect/Disconnect and show truncated address when connected - Replace static hero buttons with ConnectWallet --- frontend/app/page.module.css | 33 --------------- frontend/app/page.tsx | 17 ++------ .../ConnectWallet/ConnectWallet.module.css | 42 +++++++++++++++++++ .../ConnectWallet/ConnectWallet.tsx | 29 +++++++++++++ 4 files changed, 74 insertions(+), 47 deletions(-) create mode 100644 frontend/components/ConnectWallet/ConnectWallet.module.css create mode 100644 frontend/components/ConnectWallet/ConnectWallet.tsx diff --git a/frontend/app/page.module.css b/frontend/app/page.module.css index 89a854d..ca249c3 100644 --- a/frontend/app/page.module.css +++ b/frontend/app/page.module.css @@ -48,39 +48,6 @@ line-height: 1.6; } -.actions { - display: flex; - gap: 1.5rem; - justify-content: center; -} - -.primaryBtn { - background: var(--primary); - color: white; - padding: 1rem 2.5rem; - border-radius: 12px; - font-weight: 600; - transition: var(--transition-smooth); -} - -.primaryBtn:hover { - transform: translateY(-2px); - box-shadow: 0 0 20px var(--primary-glow); -} - -.secondaryBtn { - border: 1px solid var(--glass-border); - color: var(--foreground); - padding: 1rem 2.5rem; - border-radius: 12px; - font-weight: 600; - transition: var(--transition-smooth); -} - -.secondaryBtn:hover { - background: rgba(255, 255, 255, 0.05); -} - @media (max-width: 768px) { .title { font-size: 3rem; diff --git a/frontend/app/page.tsx b/frontend/app/page.tsx index 2daab69..02b3287 100644 --- a/frontend/app/page.tsx +++ b/frontend/app/page.tsx @@ -1,4 +1,5 @@ import styles from "./page.module.css"; +import { ConnectWallet } from "@/components/ConnectWallet/ConnectWallet"; export default function Home() { return ( @@ -10,23 +11,11 @@ export default function Home() { Powered by Stacks.

- Experience the most premium payment gateway for the Bitcoin ecosystem. + Experience the most premium payment gateway for the Bitcoin ecosystem. Fast, decentralized, and built for modern commerce.

-
- - -
+ ); } -// Final polish 62 -// Final polish 63 -// Final polish 64 -// Final polish 65 -// Final polish 66 -// Final polish 67 -// Final polish 68 -// Final polish 69 -// Final polish 70 diff --git a/frontend/components/ConnectWallet/ConnectWallet.module.css b/frontend/components/ConnectWallet/ConnectWallet.module.css new file mode 100644 index 0000000..8855cab --- /dev/null +++ b/frontend/components/ConnectWallet/ConnectWallet.module.css @@ -0,0 +1,42 @@ +.actions { + display: flex; + gap: 1.5rem; + justify-content: center; + align-items: center; +} + +.address { + font-family: monospace; + font-size: 0.95rem; + color: var(--foreground); + background: rgba(255, 255, 255, 0.05); + padding: 0.5rem 1rem; + border-radius: 8px; +} + +.primaryBtn { + background: var(--primary); + color: white; + padding: 1rem 2.5rem; + border-radius: 12px; + font-weight: 600; + transition: var(--transition-smooth); +} + +.primaryBtn:hover { + transform: translateY(-2px); + box-shadow: 0 0 20px var(--primary-glow); +} + +.secondaryBtn { + border: 1px solid var(--glass-border); + color: var(--foreground); + padding: 1rem 2.5rem; + border-radius: 12px; + font-weight: 600; + transition: var(--transition-smooth); +} + +.secondaryBtn:hover { + background: rgba(255, 255, 255, 0.05); +} diff --git a/frontend/components/ConnectWallet/ConnectWallet.tsx b/frontend/components/ConnectWallet/ConnectWallet.tsx new file mode 100644 index 0000000..4649bfe --- /dev/null +++ b/frontend/components/ConnectWallet/ConnectWallet.tsx @@ -0,0 +1,29 @@ +"use client"; + +import { useStacks } from "@/context/StacksContext"; +import styles from "./ConnectWallet.module.css"; + +export function ConnectWallet() { + const { userData, handleConnect, handleDisconnect } = useStacks(); + const address = userData?.profile?.stxAddress?.mainnet ?? userData?.profile?.stxAddress?.testnet; + + return ( +
+ {address ? ( + <> + {address.slice(0, 6)}…{address.slice(-4)} + + + ) : ( + <> + + + + )} +
+ ); +} From dbbbf7ac65c03960f926b48e9f16bbf32524a2e6 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:35:52 +0100 Subject: [PATCH 02/30] feat(frontend): add Connect Wallet to Navbar - Wire useStacks in Navbar for connect/disconnect - Show truncated address when connected --- frontend/components/Navbar/Navbar.module.css | 15 +++++++++++++++ frontend/components/Navbar/Navbar.tsx | 13 ++++++++++++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/frontend/components/Navbar/Navbar.module.css b/frontend/components/Navbar/Navbar.module.css index ae3cf90..f2aa914 100644 --- a/frontend/components/Navbar/Navbar.module.css +++ b/frontend/components/Navbar/Navbar.module.css @@ -49,6 +49,21 @@ color: var(--foreground); } +.actions { + display: flex; + align-items: center; + gap: 1rem; +} + +.address { + font-family: monospace; + font-size: 0.85rem; + color: var(--foreground); + background: rgba(255, 255, 255, 0.05); + padding: 0.4rem 0.8rem; + border-radius: 8px; +} + .connectBtn { background: rgba(255, 255, 255, 0.05); border: 1px solid var(--glass-border); diff --git a/frontend/components/Navbar/Navbar.tsx b/frontend/components/Navbar/Navbar.tsx index b6b4cda..b93f752 100644 --- a/frontend/components/Navbar/Navbar.tsx +++ b/frontend/components/Navbar/Navbar.tsx @@ -1,9 +1,13 @@ "use client"; import Link from "next/link"; +import { useStacks } from "@/context/StacksContext"; import styles from "./Navbar.module.css"; export default function Navbar() { + const { userData, handleConnect, handleDisconnect } = useStacks(); + const addr = userData?.profile?.stxAddress?.mainnet ?? userData?.profile?.stxAddress?.testnet; + return ( From 03486f784bff958a67d84eff67f19fda6f9ee441 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:35:56 +0100 Subject: [PATCH 03/30] feat(frontend): add S-pay contract constants - SPAY_CONTRACT address and name for mainnet s-pay-v3 --- frontend/lib/constants.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 frontend/lib/constants.ts diff --git a/frontend/lib/constants.ts b/frontend/lib/constants.ts new file mode 100644 index 0000000..b1fb526 --- /dev/null +++ b/frontend/lib/constants.ts @@ -0,0 +1,10 @@ +/** + * S-pay contract configuration. + * Uses mainnet s-pay-v3 deployment. + */ +export const SPAY_CONTRACT = { + address: "SP2DBFGMT7SATSJPCCA38SDDPBNNQ86QWADJ3E6WT", + name: "s-pay-v3", +} as const; + +export const SPAY_FULL_CONTRACT = `${SPAY_CONTRACT.address}.${SPAY_CONTRACT.name}`; From 3c5492396d674111314dfee39a6d338d82346149 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:36:08 +0100 Subject: [PATCH 04/30] feat(frontend): add contract call helpers with @stacks/transactions - buildRegisterUserOptions, buildVaultDepositOptions, buildProcessPaymentOptions - Use stringAsciiCV, uintCV, principalCV from @stacks/transactions --- frontend/lib/contract-calls.ts | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 frontend/lib/contract-calls.ts diff --git a/frontend/lib/contract-calls.ts b/frontend/lib/contract-calls.ts new file mode 100644 index 0000000..19dd112 --- /dev/null +++ b/frontend/lib/contract-calls.ts @@ -0,0 +1,33 @@ +/** + * Contract call helpers using @stacks/transactions for Clarity types + * and @stacks/connect for openContractCall signing. + */ +import { stringAsciiCV, uintCV, principalCV } from "@stacks/transactions"; +import { SPAY_CONTRACT } from "./constants"; + +export function buildRegisterUserOptions(username: string) { + return { + contractAddress: SPAY_CONTRACT.address, + contractName: SPAY_CONTRACT.name, + functionName: "register-user", + functionArgs: [stringAsciiCV(username)], + }; +} + +export function buildVaultDepositOptions(amount: bigint | number) { + return { + contractAddress: SPAY_CONTRACT.address, + contractName: SPAY_CONTRACT.name, + functionName: "vault-deposit", + functionArgs: [uintCV(amount)], + }; +} + +export function buildProcessPaymentOptions(amount: bigint | number, recipient: string) { + return { + contractAddress: SPAY_CONTRACT.address, + contractName: SPAY_CONTRACT.name, + functionName: "process-payment", + functionArgs: [uintCV(amount), principalCV(recipient)], + }; +} From 17fad5222023d6325ed42901d734afdb5672e35a Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:36:26 +0100 Subject: [PATCH 05/30] feat(frontend): expose callContract via openContractCall in StacksContext - Add callContract to context using @stacks/connect openContractCall - Wire userSession and network for wallet signing --- frontend/context/StacksContext.tsx | 42 ++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 5 deletions(-) diff --git a/frontend/context/StacksContext.tsx b/frontend/context/StacksContext.tsx index 8ed417d..eae907e 100644 --- a/frontend/context/StacksContext.tsx +++ b/frontend/context/StacksContext.tsx @@ -1,8 +1,13 @@ "use client"; -import React, { createContext, useContext, useState, useEffect } from 'react'; -import { AppConfig, UserSession, showConnect } from '@stacks/connect'; -import { StacksMainnet } from '@stacks/network'; +import React, { createContext, useContext, useState, useEffect } from "react"; +import { + AppConfig, + UserSession, + showConnect, + openContractCall, +} from "@stacks/connect"; +import { StacksMainnet } from "@stacks/network"; export interface StacksUserData { profile: { @@ -13,12 +18,20 @@ export interface StacksUserData { }; } +export interface ContractCallBase { + contractAddress: string; + contractName: string; + functionName: string; + functionArgs: unknown[]; +} + interface StacksContextType { userSession: UserSession; userData: StacksUserData | null; handleConnect: () => void; handleDisconnect: () => void; - network: any; + network: unknown; + callContract: (options: ContractCallBase) => void; } const StacksContext = createContext(undefined); @@ -55,8 +68,27 @@ export function StacksProvider({ children }: { children: React.ReactNode }) { setUserData(null); }; + const callContract = (options: ContractCallBase) => { + openContractCall({ + ...options, + userSession, + network, + onFinish: () => {}, + onCancel: () => {}, + }); + }; + return ( - + {children} ); From c1c7d956aa1e3b1462de8f459921f931b9c0b4bd Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:36:36 +0100 Subject: [PATCH 06/30] feat(frontend): add Navbar to root layout - Show Connect Wallet on all pages --- frontend/app/layout.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/app/layout.tsx b/frontend/app/layout.tsx index f8b7082..01bed6c 100644 --- a/frontend/app/layout.tsx +++ b/frontend/app/layout.tsx @@ -1,6 +1,7 @@ import type { Metadata } from "next"; import "./globals.css"; import { StacksProvider } from "@/context/StacksContext"; +import Navbar from "@/components/Navbar/Navbar"; export const metadata: Metadata = { title: "S-pay | Premium Stacks Payments", @@ -21,6 +22,7 @@ export default function RootLayout({ + {children} From 61eb823802dfe8bdc497b8110a4b01788457a339 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:36:50 +0100 Subject: [PATCH 07/30] feat(frontend): add useRegisterUser and useVaultDeposit hooks - useRegisterUser uses buildRegisterUserOptions + callContract - useVaultDeposit uses buildVaultDepositOptions + callContract --- frontend/hooks/useRegisterUser.ts | 19 +++++++++++++++++++ frontend/hooks/useVaultDeposit.ts | 18 ++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 frontend/hooks/useRegisterUser.ts create mode 100644 frontend/hooks/useVaultDeposit.ts diff --git a/frontend/hooks/useRegisterUser.ts b/frontend/hooks/useRegisterUser.ts new file mode 100644 index 0000000..22e35fa --- /dev/null +++ b/frontend/hooks/useRegisterUser.ts @@ -0,0 +1,19 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { buildRegisterUserOptions } from "@/lib/contract-calls"; + +export function useRegisterUser() { + const { callContract, userData } = useStacks(); + + const registerUser = useCallback( + (username: string) => { + const opts = buildRegisterUserOptions(username); + callContract(opts); + }, + [callContract] + ); + + return { registerUser, isConnected: !!userData }; +} diff --git a/frontend/hooks/useVaultDeposit.ts b/frontend/hooks/useVaultDeposit.ts new file mode 100644 index 0000000..76b7162 --- /dev/null +++ b/frontend/hooks/useVaultDeposit.ts @@ -0,0 +1,18 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { buildVaultDepositOptions } from "@/lib/contract-calls"; + +export function useVaultDeposit() { + const { callContract } = useStacks(); + + const vaultDeposit = useCallback( + (amountMicroStx: bigint | number) => { + callContract(buildVaultDepositOptions(amountMicroStx)); + }, + [callContract] + ); + + return { vaultDeposit }; +} From 32032e61e304206686eb5ea57a94f82d3c08b8da Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:37:03 +0100 Subject: [PATCH 08/30] feat(frontend): add buildRegisterMerchantOptions to contract-calls - Uses stringAsciiCV from @stacks/transactions --- frontend/lib/contract-calls.ts | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/frontend/lib/contract-calls.ts b/frontend/lib/contract-calls.ts index 19dd112..ba2b7d4 100644 --- a/frontend/lib/contract-calls.ts +++ b/frontend/lib/contract-calls.ts @@ -31,3 +31,15 @@ export function buildProcessPaymentOptions(amount: bigint | number, recipient: s functionArgs: [uintCV(amount), principalCV(recipient)], }; } + +export function buildRegisterMerchantOptions( + businessName: string, + website: string +) { + return { + contractAddress: SPAY_CONTRACT.address, + contractName: SPAY_CONTRACT.name, + functionName: "register-merchant", + functionArgs: [stringAsciiCV(businessName), stringAsciiCV(website)], + }; +} From d861c201fbedf7d998ad78ba01b30bf6514d6bb6 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:37:03 +0100 Subject: [PATCH 09/30] feat(frontend): add useProcessPayment and useRegisterMerchant hooks - Both use callContract from StacksContext --- frontend/hooks/useProcessPayment.ts | 18 ++++++++++++++++++ frontend/hooks/useRegisterMerchant.ts | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 frontend/hooks/useProcessPayment.ts create mode 100644 frontend/hooks/useRegisterMerchant.ts diff --git a/frontend/hooks/useProcessPayment.ts b/frontend/hooks/useProcessPayment.ts new file mode 100644 index 0000000..461bbf2 --- /dev/null +++ b/frontend/hooks/useProcessPayment.ts @@ -0,0 +1,18 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { buildProcessPaymentOptions } from "@/lib/contract-calls"; + +export function useProcessPayment() { + const { callContract } = useStacks(); + + const processPayment = useCallback( + (amountMicroStx: bigint | number, recipient: string) => { + callContract(buildProcessPaymentOptions(amountMicroStx, recipient)); + }, + [callContract] + ); + + return { processPayment }; +} diff --git a/frontend/hooks/useRegisterMerchant.ts b/frontend/hooks/useRegisterMerchant.ts new file mode 100644 index 0000000..b2b1b7d --- /dev/null +++ b/frontend/hooks/useRegisterMerchant.ts @@ -0,0 +1,18 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { buildRegisterMerchantOptions } from "@/lib/contract-calls"; + +export function useRegisterMerchant() { + const { callContract } = useStacks(); + + const registerMerchant = useCallback( + (businessName: string, website: string) => { + callContract(buildRegisterMerchantOptions(businessName, website)); + }, + [callContract] + ); + + return { registerMerchant }; +} From 39f9fcab4b0142e94ed0158ed515336b73029dec Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:37:25 +0100 Subject: [PATCH 10/30] feat(frontend): add read-only contract calls with @stacks/transactions - callReadOnly uses cvToHex for encoding, deserializeCV for decoding --- frontend/lib/read-only.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 frontend/lib/read-only.ts diff --git a/frontend/lib/read-only.ts b/frontend/lib/read-only.ts new file mode 100644 index 0000000..e63c6a5 --- /dev/null +++ b/frontend/lib/read-only.ts @@ -0,0 +1,25 @@ +/** + * Read-only contract calls using @stacks/transactions for encoding. + */ +import { cvToHex, deserializeCV } from "@stacks/transactions"; +import type { ClarityValue } from "@stacks/transactions"; +import { SPAY_CONTRACT } from "./constants"; + +const API_BASE = "https://api.mainnet.hiro.so/v2"; + +export async function callReadOnly( + functionName: string, + functionArgs: ClarityValue[], + senderAddress: string +): Promise { + const args = functionArgs.map((cv) => cvToHex(cv)); + const url = `${API_BASE}/contracts/call-read/${SPAY_CONTRACT.address}/${SPAY_CONTRACT.name}/${functionName}`; + const res = await fetch(url, { + method: "POST", + headers: { "Content-Type": "application/json" }, + body: JSON.stringify({ sender: senderAddress, arguments: args }), + }); + if (!res.ok) throw new Error(`Read call failed: ${res.statusText}`); + const data = await res.json(); + return deserializeCV(data.result) as T; +} From 4f28067b9ed62dc3bde19cdb27c0ff28d6382dff Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:37:27 +0100 Subject: [PATCH 11/30] feat(frontend): add useUserData hook for get-user-data - Uses callReadOnly with principalCV from @stacks/transactions --- frontend/hooks/useUserData.ts | 36 +++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 frontend/hooks/useUserData.ts diff --git a/frontend/hooks/useUserData.ts b/frontend/hooks/useUserData.ts new file mode 100644 index 0000000..71a8e15 --- /dev/null +++ b/frontend/hooks/useUserData.ts @@ -0,0 +1,36 @@ +"use client"; + +import { useState, useEffect, useCallback } from "react"; +import { principalCV } from "@stacks/transactions"; +import { useStacks } from "@/context/StacksContext"; +import { callReadOnly } from "@/lib/read-only"; + +export function useUserData() { + const { userData } = useStacks(); + const [data, setData] = useState(null); + const [loading, setLoading] = useState(false); + + const address = + userData?.profile?.stxAddress?.mainnet ?? userData?.profile?.stxAddress?.testnet; + + const fetchUserData = useCallback(async () => { + if (!address) return; + setLoading(true); + try { + const result = await callReadOnly( + "get-user-data", + [principalCV(address)], + address + ); + setData(result); + } finally { + setLoading(false); + } + }, [address]); + + useEffect(() => { + fetchUserData(); + }, [fetchUserData]); + + return { userData: data, loading, refetch: fetchUserData }; +} From ee5049a9fb8f131761c6ecee301da1269cde11c0 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:37:37 +0100 Subject: [PATCH 12/30] feat(frontend): add RegisterUserForm component - Uses useRegisterUser hook and buildRegisterUserOptions --- .../RegisterUserForm.module.css | 26 ++++++++++++++ .../RegisterUserForm/RegisterUserForm.tsx | 35 +++++++++++++++++++ 2 files changed, 61 insertions(+) create mode 100644 frontend/components/RegisterUserForm/RegisterUserForm.module.css create mode 100644 frontend/components/RegisterUserForm/RegisterUserForm.tsx diff --git a/frontend/components/RegisterUserForm/RegisterUserForm.module.css b/frontend/components/RegisterUserForm/RegisterUserForm.module.css new file mode 100644 index 0000000..c864cbc --- /dev/null +++ b/frontend/components/RegisterUserForm/RegisterUserForm.module.css @@ -0,0 +1,26 @@ +.form { + display: flex; + gap: 0.75rem; +} + +.input { + padding: 0.6rem 1rem; + border-radius: 8px; + border: 1px solid var(--glass-border); + background: rgba(255, 255, 255, 0.05); + color: var(--foreground); + min-width: 200px; +} + +.btn { + background: var(--primary); + color: white; + padding: 0.6rem 1.25rem; + border-radius: 8px; + font-weight: 600; +} + +.hint { + color: #a0a0aa; + font-size: 0.9rem; +} diff --git a/frontend/components/RegisterUserForm/RegisterUserForm.tsx b/frontend/components/RegisterUserForm/RegisterUserForm.tsx new file mode 100644 index 0000000..86bb849 --- /dev/null +++ b/frontend/components/RegisterUserForm/RegisterUserForm.tsx @@ -0,0 +1,35 @@ +"use client"; + +import { useState } from "react"; +import { useRegisterUser } from "@/hooks/useRegisterUser"; +import styles from "./RegisterUserForm.module.css"; + +export function RegisterUserForm() { + const [username, setUsername] = useState(""); + const { registerUser, isConnected } = useRegisterUser(); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (username.trim()) registerUser(username.trim()); + }; + + if (!isConnected) { + return

Connect wallet to register

; + } + + return ( +
+ setUsername(e.target.value)} + placeholder="Username (max 24 chars)" + maxLength={24} + className={styles.input} + /> + +
+ ); +} From f45d81608d1160d66550fb07e122609981fabef6 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:37:45 +0100 Subject: [PATCH 13/30] feat(frontend): add /register page with RegisterUserForm --- frontend/app/register/page.tsx | 16 ++++++++++++++++ frontend/app/register/register.module.css | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 frontend/app/register/page.tsx create mode 100644 frontend/app/register/register.module.css diff --git a/frontend/app/register/page.tsx b/frontend/app/register/page.tsx new file mode 100644 index 0000000..977b569 --- /dev/null +++ b/frontend/app/register/page.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { RegisterUserForm } from "@/components/RegisterUserForm/RegisterUserForm"; +import styles from "./register.module.css"; + +export default function RegisterPage() { + return ( +
+

Register as User

+

+ Pick a unique username to join S-pay (string-ascii 24 max) +

+ +
+ ); +} diff --git a/frontend/app/register/register.module.css b/frontend/app/register/register.module.css new file mode 100644 index 0000000..180a9df --- /dev/null +++ b/frontend/app/register/register.module.css @@ -0,0 +1,18 @@ +.page { + min-height: 80vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; +} + +.title { + font-size: 2rem; + margin-bottom: 0.5rem; +} + +.subtitle { + color: #a0a0aa; + margin-bottom: 2rem; +} From f15735496439e161fd73962e3a892daae45da0d1 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:37:57 +0100 Subject: [PATCH 14/30] feat(frontend): add transferStx via openSTXTransfer from @stacks/connect --- frontend/context/StacksContext.tsx | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/frontend/context/StacksContext.tsx b/frontend/context/StacksContext.tsx index eae907e..f1fb025 100644 --- a/frontend/context/StacksContext.tsx +++ b/frontend/context/StacksContext.tsx @@ -6,6 +6,7 @@ import { UserSession, showConnect, openContractCall, + openSTXTransfer, } from "@stacks/connect"; import { StacksMainnet } from "@stacks/network"; @@ -32,6 +33,7 @@ interface StacksContextType { handleDisconnect: () => void; network: unknown; callContract: (options: ContractCallBase) => void; + transferStx: (recipient: string, amountMicroStx: bigint) => void; } const StacksContext = createContext(undefined); @@ -78,6 +80,17 @@ export function StacksProvider({ children }: { children: React.ReactNode }) { }); }; + const transferStx = (recipient: string, amountMicroStx: bigint) => { + openSTXTransfer({ + recipient, + amount: amountMicroStx, + userSession, + network, + onFinish: () => {}, + onCancel: () => {}, + }); + }; + return ( {children} From 6767497427a770496c3bf1258b13077955628262 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:38:01 +0100 Subject: [PATCH 15/30] feat(frontend): add Register link to Navbar --- frontend/components/Navbar/Navbar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/components/Navbar/Navbar.tsx b/frontend/components/Navbar/Navbar.tsx index b93f752..558dad8 100644 --- a/frontend/components/Navbar/Navbar.tsx +++ b/frontend/components/Navbar/Navbar.tsx @@ -15,6 +15,7 @@ export default function Navbar() { S-pay.
+ Register Payments Tokens Developers From faa1e802adf5ae4dd242e8ed921f6c5e1df86054 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:38:15 +0100 Subject: [PATCH 16/30] feat(frontend): add buildVaultWithdraw and buildMerchantWithdraw - Use uintCV from @stacks/transactions --- frontend/lib/contract-calls.ts | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/frontend/lib/contract-calls.ts b/frontend/lib/contract-calls.ts index ba2b7d4..f28328f 100644 --- a/frontend/lib/contract-calls.ts +++ b/frontend/lib/contract-calls.ts @@ -43,3 +43,21 @@ export function buildRegisterMerchantOptions( functionArgs: [stringAsciiCV(businessName), stringAsciiCV(website)], }; } + +export function buildVaultWithdrawOptions(amount: bigint | number) { + return { + contractAddress: SPAY_CONTRACT.address, + contractName: SPAY_CONTRACT.name, + functionName: "vault-withdraw", + functionArgs: [uintCV(amount)], + }; +} + +export function buildMerchantWithdrawOptions(amount: bigint | number) { + return { + contractAddress: SPAY_CONTRACT.address, + contractName: SPAY_CONTRACT.name, + functionName: "merchant-withdraw", + functionArgs: [uintCV(amount)], + }; +} From c845355b654c839b7803be77cbb3ad058ce662f7 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:38:15 +0100 Subject: [PATCH 17/30] feat(frontend): add useVaultWithdraw and useMerchantWithdraw hooks --- frontend/hooks/useMerchantWithdraw.ts | 18 ++++++++++++++++++ frontend/hooks/useVaultWithdraw.ts | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 frontend/hooks/useMerchantWithdraw.ts create mode 100644 frontend/hooks/useVaultWithdraw.ts diff --git a/frontend/hooks/useMerchantWithdraw.ts b/frontend/hooks/useMerchantWithdraw.ts new file mode 100644 index 0000000..d909113 --- /dev/null +++ b/frontend/hooks/useMerchantWithdraw.ts @@ -0,0 +1,18 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { buildMerchantWithdrawOptions } from "@/lib/contract-calls"; + +export function useMerchantWithdraw() { + const { callContract } = useStacks(); + + const merchantWithdraw = useCallback( + (amountMicroStx: bigint | number) => { + callContract(buildMerchantWithdrawOptions(amountMicroStx)); + }, + [callContract] + ); + + return { merchantWithdraw }; +} diff --git a/frontend/hooks/useVaultWithdraw.ts b/frontend/hooks/useVaultWithdraw.ts new file mode 100644 index 0000000..36bee29 --- /dev/null +++ b/frontend/hooks/useVaultWithdraw.ts @@ -0,0 +1,18 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { buildVaultWithdrawOptions } from "@/lib/contract-calls"; + +export function useVaultWithdraw() { + const { callContract } = useStacks(); + + const vaultWithdraw = useCallback( + (amountMicroStx: bigint | number) => { + callContract(buildVaultWithdrawOptions(amountMicroStx)); + }, + [callContract] + ); + + return { vaultWithdraw }; +} From 2451f9d69316d07c4c127e894e0f013492db26eb Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:38:33 +0100 Subject: [PATCH 18/30] feat(frontend): add useTransferStx hook for openSTXTransfer --- frontend/hooks/useTransferStx.ts | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 frontend/hooks/useTransferStx.ts diff --git a/frontend/hooks/useTransferStx.ts b/frontend/hooks/useTransferStx.ts new file mode 100644 index 0000000..6bdadfa --- /dev/null +++ b/frontend/hooks/useTransferStx.ts @@ -0,0 +1,17 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; + +export function useTransferStx() { + const { transferStx } = useStacks(); + + const transfer = useCallback( + (recipient: string, amountMicroStx: bigint) => { + transferStx(recipient, amountMicroStx); + }, + [transferStx] + ); + + return { transfer }; +} From fa9b190e1bb767c8b0c920baee637e1bf8517a74 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:38:34 +0100 Subject: [PATCH 19/30] feat(frontend): add getProtocolStatus to read-only lib --- frontend/lib/read-only.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/frontend/lib/read-only.ts b/frontend/lib/read-only.ts index e63c6a5..345aae3 100644 --- a/frontend/lib/read-only.ts +++ b/frontend/lib/read-only.ts @@ -23,3 +23,7 @@ export async function callReadOnly( const data = await res.json(); return deserializeCV(data.result) as T; } + +export async function getProtocolStatus(senderAddress: string) { + return callReadOnly("get-protocol-status", [], senderAddress); +} From b2251a328e0c15cee55d3c191f8fe0328f3903ae Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:38:34 +0100 Subject: [PATCH 20/30] feat(frontend): add useProtocolStatus hook --- frontend/hooks/useProtocolStatus.ts | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 frontend/hooks/useProtocolStatus.ts diff --git a/frontend/hooks/useProtocolStatus.ts b/frontend/hooks/useProtocolStatus.ts new file mode 100644 index 0000000..75dd10c --- /dev/null +++ b/frontend/hooks/useProtocolStatus.ts @@ -0,0 +1,25 @@ +"use client"; + +import { useState, useEffect, useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { getProtocolStatus } from "@/lib/read-only"; + +export function useProtocolStatus() { + const { userData } = useStacks(); + const [status, setStatus] = useState(null); + + const address = + userData?.profile?.stxAddress?.mainnet ?? userData?.profile?.stxAddress?.testnet; + + const fetchStatus = useCallback(async () => { + const sender = address ?? "SP2DBFGMT7SATSJPCCA38SDDPBNNQ86QWADJ3E6WT"; + const result = await getProtocolStatus(sender); + setStatus(result); + }, [address]); + + useEffect(() => { + fetchStatus(); + }, [fetchStatus]); + + return { status, refetch: fetchStatus }; +} From 8c0390548cc7e9988f24ce8c906ddc3c1fba93f8 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:39:26 +0100 Subject: [PATCH 21/30] feat(frontend): add buildReclaimStakeOptions and useReclaimStake --- frontend/hooks/useReclaimStake.ts | 15 +++++++++++++++ frontend/lib/contract-calls.ts | 9 +++++++++ 2 files changed, 24 insertions(+) create mode 100644 frontend/hooks/useReclaimStake.ts diff --git a/frontend/hooks/useReclaimStake.ts b/frontend/hooks/useReclaimStake.ts new file mode 100644 index 0000000..7270b0d --- /dev/null +++ b/frontend/hooks/useReclaimStake.ts @@ -0,0 +1,15 @@ +"use client"; + +import { useCallback } from "react"; +import { useStacks } from "@/context/StacksContext"; +import { buildReclaimStakeOptions } from "@/lib/contract-calls"; + +export function useReclaimStake() { + const { callContract } = useStacks(); + + const reclaimStake = useCallback(() => { + callContract(buildReclaimStakeOptions()); + }, [callContract]); + + return { reclaimStake }; +} diff --git a/frontend/lib/contract-calls.ts b/frontend/lib/contract-calls.ts index f28328f..cdf01e5 100644 --- a/frontend/lib/contract-calls.ts +++ b/frontend/lib/contract-calls.ts @@ -61,3 +61,12 @@ export function buildMerchantWithdrawOptions(amount: bigint | number) { functionArgs: [uintCV(amount)], }; } + +export function buildReclaimStakeOptions() { + return { + contractAddress: SPAY_CONTRACT.address, + contractName: SPAY_CONTRACT.name, + functionName: "reclaim-stake", + functionArgs: [], + }; +} From a0203ce94bd5ab9fdc421a53787bf504af233991 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:39:28 +0100 Subject: [PATCH 22/30] feat(frontend): add PaymentForm using useProcessPayment and buildProcessPaymentOptions --- .../PaymentForm/PaymentForm.module.css | 22 ++++++++++ .../components/PaymentForm/PaymentForm.tsx | 40 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 frontend/components/PaymentForm/PaymentForm.module.css create mode 100644 frontend/components/PaymentForm/PaymentForm.tsx diff --git a/frontend/components/PaymentForm/PaymentForm.module.css b/frontend/components/PaymentForm/PaymentForm.module.css new file mode 100644 index 0000000..4716d90 --- /dev/null +++ b/frontend/components/PaymentForm/PaymentForm.module.css @@ -0,0 +1,22 @@ +.form { + display: flex; + flex-direction: column; + gap: 0.75rem; + max-width: 400px; +} + +.input { + padding: 0.6rem 1rem; + border-radius: 8px; + border: 1px solid var(--glass-border); + background: rgba(255, 255, 255, 0.05); + color: var(--foreground); +} + +.btn { + background: var(--primary); + color: white; + padding: 0.75rem; + border-radius: 8px; + font-weight: 600; +} diff --git a/frontend/components/PaymentForm/PaymentForm.tsx b/frontend/components/PaymentForm/PaymentForm.tsx new file mode 100644 index 0000000..d6d5383 --- /dev/null +++ b/frontend/components/PaymentForm/PaymentForm.tsx @@ -0,0 +1,40 @@ +"use client"; + +import { useState } from "react"; +import { useProcessPayment } from "@/hooks/useProcessPayment"; +import styles from "./PaymentForm.module.css"; + +export function PaymentForm() { + const [recipient, setRecipient] = useState(""); + const [amountStx, setAmountStx] = useState(""); + const { processPayment } = useProcessPayment(); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const amount = BigInt(Math.floor(parseFloat(amountStx || "0") * 1e6)); + if (recipient && amount > 0n) processPayment(amount, recipient); + }; + + return ( +
+ setRecipient(e.target.value)} + placeholder="Recipient principal" + className={styles.input} + /> + setAmountStx(e.target.value)} + placeholder="Amount (STX)" + className={styles.input} + /> + +
+ ); +} From 044e7345b74dde57da4b170e17ab2bf1352f9107 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:39:35 +0100 Subject: [PATCH 23/30] feat(frontend): add /pay page with PaymentForm --- frontend/app/pay/page.tsx | 16 ++++++++++++++++ frontend/app/pay/pay.module.css | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 frontend/app/pay/page.tsx create mode 100644 frontend/app/pay/pay.module.css diff --git a/frontend/app/pay/page.tsx b/frontend/app/pay/page.tsx new file mode 100644 index 0000000..84c87da --- /dev/null +++ b/frontend/app/pay/page.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { PaymentForm } from "@/components/PaymentForm/PaymentForm"; +import styles from "./pay.module.css"; + +export default function PayPage() { + return ( +
+

Process Payment

+

+ Send STX via S-pay protocol (process-payment) +

+ +
+ ); +} diff --git a/frontend/app/pay/pay.module.css b/frontend/app/pay/pay.module.css new file mode 100644 index 0000000..180a9df --- /dev/null +++ b/frontend/app/pay/pay.module.css @@ -0,0 +1,18 @@ +.page { + min-height: 80vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; +} + +.title { + font-size: 2rem; + margin-bottom: 0.5rem; +} + +.subtitle { + color: #a0a0aa; + margin-bottom: 2rem; +} From 663e36c517fc8df7dab765dee9a3ee8155311ea3 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:39:40 +0100 Subject: [PATCH 24/30] feat(frontend): add Pay link to Navbar --- frontend/components/Navbar/Navbar.tsx | 1 + 1 file changed, 1 insertion(+) diff --git a/frontend/components/Navbar/Navbar.tsx b/frontend/components/Navbar/Navbar.tsx index 558dad8..746c891 100644 --- a/frontend/components/Navbar/Navbar.tsx +++ b/frontend/components/Navbar/Navbar.tsx @@ -16,6 +16,7 @@ export default function Navbar() {
Register + Pay Payments Tokens Developers From 6cb43efa8f90352803f9b5a8264483efd6b74665 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:39:56 +0100 Subject: [PATCH 25/30] feat(frontend): use cvToValue from @stacks/transactions for protocol status --- frontend/lib/read-only.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/frontend/lib/read-only.ts b/frontend/lib/read-only.ts index 345aae3..cd86b8c 100644 --- a/frontend/lib/read-only.ts +++ b/frontend/lib/read-only.ts @@ -1,7 +1,7 @@ /** - * Read-only contract calls using @stacks/transactions for encoding. + * Read-only contract calls using @stacks/transactions for encoding/decoding. */ -import { cvToHex, deserializeCV } from "@stacks/transactions"; +import { cvToHex, deserializeCV, cvToValue } from "@stacks/transactions"; import type { ClarityValue } from "@stacks/transactions"; import { SPAY_CONTRACT } from "./constants"; @@ -25,5 +25,6 @@ export async function callReadOnly( } export async function getProtocolStatus(senderAddress: string) { - return callReadOnly("get-protocol-status", [], senderAddress); + const cv = await callReadOnly("get-protocol-status", [], senderAddress); + return cvToValue(cv); } From 3b40bc47f34ce4ec1b68dbb8718fae9d4ec2ea69 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:40:09 +0100 Subject: [PATCH 26/30] feat(frontend): add RegisterMerchantForm using useRegisterMerchant --- .../RegisterMerchantForm.module.css | 26 +++++++++++ .../RegisterMerchantForm.tsx | 46 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 frontend/components/RegisterMerchantForm/RegisterMerchantForm.module.css create mode 100644 frontend/components/RegisterMerchantForm/RegisterMerchantForm.tsx diff --git a/frontend/components/RegisterMerchantForm/RegisterMerchantForm.module.css b/frontend/components/RegisterMerchantForm/RegisterMerchantForm.module.css new file mode 100644 index 0000000..d32b08f --- /dev/null +++ b/frontend/components/RegisterMerchantForm/RegisterMerchantForm.module.css @@ -0,0 +1,26 @@ +.form { + display: flex; + flex-direction: column; + gap: 0.75rem; + max-width: 400px; +} + +.input { + padding: 0.6rem 1rem; + border-radius: 8px; + border: 1px solid var(--glass-border); + background: rgba(255, 255, 255, 0.05); + color: var(--foreground); +} + +.btn { + background: var(--primary); + color: white; + padding: 0.75rem; + border-radius: 8px; + font-weight: 600; +} + +.hint { + color: #a0a0aa; +} diff --git a/frontend/components/RegisterMerchantForm/RegisterMerchantForm.tsx b/frontend/components/RegisterMerchantForm/RegisterMerchantForm.tsx new file mode 100644 index 0000000..dcf294b --- /dev/null +++ b/frontend/components/RegisterMerchantForm/RegisterMerchantForm.tsx @@ -0,0 +1,46 @@ +"use client"; + +import { useState } from "react"; +import { useRegisterMerchant } from "@/hooks/useRegisterMerchant"; +import { useStacks } from "@/context/StacksContext"; +import styles from "./RegisterMerchantForm.module.css"; + +export function RegisterMerchantForm() { + const [businessName, setBusinessName] = useState(""); + const [website, setWebsite] = useState(""); + const { registerMerchant } = useRegisterMerchant(); + const { userData } = useStacks(); + const isConnected = !!userData; + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + if (businessName.trim() && website.trim()) + registerMerchant(businessName.trim(), website.trim()); + }; + + if (!isConnected) return

Connect wallet first

; + + return ( +
+ setBusinessName(e.target.value)} + placeholder="Business name (max 64 chars)" + maxLength={64} + className={styles.input} + /> + setWebsite(e.target.value)} + placeholder="Website (max 128 chars)" + maxLength={128} + className={styles.input} + /> + +
+ ); +} From 24aa475491188e0288b9858a2c2d655b9ef9b1be Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:40:09 +0100 Subject: [PATCH 27/30] feat(frontend): add /merchant/register page --- frontend/app/merchant/register/page.tsx | 16 ++++++++++++++++ .../app/merchant/register/register.module.css | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 frontend/app/merchant/register/page.tsx create mode 100644 frontend/app/merchant/register/register.module.css diff --git a/frontend/app/merchant/register/page.tsx b/frontend/app/merchant/register/page.tsx new file mode 100644 index 0000000..ea3b917 --- /dev/null +++ b/frontend/app/merchant/register/page.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { RegisterMerchantForm } from "@/components/RegisterMerchantForm/RegisterMerchantForm"; +import styles from "./register.module.css"; + +export default function MerchantRegisterPage() { + return ( +
+

Register as Merchant

+

+ Requires 50 STX verification stake (register-merchant) +

+ +
+ ); +} diff --git a/frontend/app/merchant/register/register.module.css b/frontend/app/merchant/register/register.module.css new file mode 100644 index 0000000..180a9df --- /dev/null +++ b/frontend/app/merchant/register/register.module.css @@ -0,0 +1,18 @@ +.page { + min-height: 80vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; +} + +.title { + font-size: 2rem; + margin-bottom: 0.5rem; +} + +.subtitle { + color: #a0a0aa; + margin-bottom: 2rem; +} From 3b4219652d91790d537e8b662fa19cc138d2aba8 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:40:31 +0100 Subject: [PATCH 28/30] feat(frontend): add VaultDepositForm using useVaultDeposit --- .../VaultDepositForm.module.css | 21 ++++++++++++ .../VaultDepositForm/VaultDepositForm.tsx | 32 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 frontend/components/VaultDepositForm/VaultDepositForm.module.css create mode 100644 frontend/components/VaultDepositForm/VaultDepositForm.tsx diff --git a/frontend/components/VaultDepositForm/VaultDepositForm.module.css b/frontend/components/VaultDepositForm/VaultDepositForm.module.css new file mode 100644 index 0000000..3845ba4 --- /dev/null +++ b/frontend/components/VaultDepositForm/VaultDepositForm.module.css @@ -0,0 +1,21 @@ +.form { + display: flex; + gap: 0.75rem; +} + +.input { + padding: 0.6rem 1rem; + border-radius: 8px; + border: 1px solid var(--glass-border); + background: rgba(255, 255, 255, 0.05); + color: var(--foreground); + min-width: 150px; +} + +.btn { + background: var(--primary); + color: white; + padding: 0.6rem 1.25rem; + border-radius: 8px; + font-weight: 600; +} diff --git a/frontend/components/VaultDepositForm/VaultDepositForm.tsx b/frontend/components/VaultDepositForm/VaultDepositForm.tsx new file mode 100644 index 0000000..b8a1463 --- /dev/null +++ b/frontend/components/VaultDepositForm/VaultDepositForm.tsx @@ -0,0 +1,32 @@ +"use client"; + +import { useState } from "react"; +import { useVaultDeposit } from "@/hooks/useVaultDeposit"; +import styles from "./VaultDepositForm.module.css"; + +export function VaultDepositForm() { + const [amountStx, setAmountStx] = useState(""); + const { vaultDeposit } = useVaultDeposit(); + + const handleSubmit = (e: React.FormEvent) => { + e.preventDefault(); + const amount = BigInt(Math.floor(parseFloat(amountStx || "0") * 1e6)); + if (amount > 0n) vaultDeposit(amount); + }; + + return ( +
+ setAmountStx(e.target.value)} + placeholder="Amount (STX)" + className={styles.input} + /> + +
+ ); +} From 82862b2ba1239ec9df9c7334764d5c0590b09d54 Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:40:31 +0100 Subject: [PATCH 29/30] feat(frontend): add /vault page --- frontend/app/vault/page.tsx | 16 ++++++++++++++++ frontend/app/vault/vault.module.css | 18 ++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 frontend/app/vault/page.tsx create mode 100644 frontend/app/vault/vault.module.css diff --git a/frontend/app/vault/page.tsx b/frontend/app/vault/page.tsx new file mode 100644 index 0000000..5b9a8c8 --- /dev/null +++ b/frontend/app/vault/page.tsx @@ -0,0 +1,16 @@ +"use client"; + +import { VaultDepositForm } from "@/components/VaultDepositForm/VaultDepositForm"; +import styles from "./vault.module.css"; + +export default function VaultPage() { + return ( +
+

Vault Deposit

+

+ Deposit STX to your S-pay vault (vault-deposit) +

+ +
+ ); +} diff --git a/frontend/app/vault/vault.module.css b/frontend/app/vault/vault.module.css new file mode 100644 index 0000000..180a9df --- /dev/null +++ b/frontend/app/vault/vault.module.css @@ -0,0 +1,18 @@ +.page { + min-height: 80vh; + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: 2rem; +} + +.title { + font-size: 2rem; + margin-bottom: 0.5rem; +} + +.subtitle { + color: #a0a0aa; + margin-bottom: 2rem; +} From e963c6fa5b84dccd843cf839edf53c982bfd663c Mon Sep 17 00:00:00 2001 From: DevSolex Date: Tue, 17 Feb 2026 02:40:31 +0100 Subject: [PATCH 30/30] feat(frontend): add Vault and Merchant links to Navbar --- frontend/components/Navbar/Navbar.tsx | 2 ++ 1 file changed, 2 insertions(+) diff --git a/frontend/components/Navbar/Navbar.tsx b/frontend/components/Navbar/Navbar.tsx index 746c891..10f2525 100644 --- a/frontend/components/Navbar/Navbar.tsx +++ b/frontend/components/Navbar/Navbar.tsx @@ -17,6 +17,8 @@ export default function Navbar() {
Register Pay + Vault + Merchant Payments Tokens Developers