Files
nebula/handlers/routes.go

210 lines
5.4 KiB
Go

package handlers
import (
"net/http"
"strconv"
"nebula/views"
)
func RegisterRoutes(mux *http.ServeMux) {
mux.HandleFunc("GET /", handleWelcome)
mux.HandleFunc("GET /welcome", handleWelcome)
mux.HandleFunc("GET /welcome/step/{step}", handleWelcomeStep)
mux.HandleFunc("GET /register", handleRegister)
mux.HandleFunc("GET /register/step/{step}", handleRegisterStep)
mux.HandleFunc("GET /register/capabilities", handleRegisterCapabilities)
mux.HandleFunc("POST /register/verify-code", handleRegisterVerifyCode)
mux.HandleFunc("GET /login", handleLogin)
mux.HandleFunc("GET /login/step/{step}", handleLoginStep)
mux.HandleFunc("GET /login/qr-status", handleLoginQRStatus)
mux.HandleFunc("GET /authorize", handleAuthorize)
mux.HandleFunc("POST /authorize/approve", handleAuthorizeApprove)
mux.HandleFunc("POST /authorize/deny", handleAuthorizeDeny)
mux.HandleFunc("GET /dashboard", handleDashboard)
}
// handleWelcome renders the full welcome page at step 1
func handleWelcome(w http.ResponseWriter, r *http.Request) {
views.WelcomePage(1).Render(r.Context(), w)
}
// handleWelcomeStep handles HTMX partial updates for step navigation
func handleWelcomeStep(w http.ResponseWriter, r *http.Request) {
stepStr := r.PathValue("step")
step, err := strconv.Atoi(stepStr)
if err != nil || step < 1 || step > 3 {
step = 1
}
// Check if this is an HTMX request
if r.Header.Get("HX-Request") == "true" {
// Return step content with OOB stepper update (HTMX 4 pattern)
views.WelcomeStepWithStepper(step).Render(r.Context(), w)
return
}
views.WelcomePage(step).Render(r.Context(), w)
}
func handleRegister(w http.ResponseWriter, r *http.Request) {
state := views.RegisterState{Step: 1}
views.RegisterPage(state).Render(r.Context(), w)
}
func handleRegisterStep(w http.ResponseWriter, r *http.Request) {
stepStr := r.PathValue("step")
step, err := strconv.Atoi(stepStr)
if err != nil || step < 1 || step > 3 {
step = 1
}
method := r.URL.Query().Get("method")
if method == "" {
method = "passkey"
}
state := views.RegisterState{Step: step, Method: method}
if r.Header.Get("HX-Request") == "true" {
views.RegisterStepWithStepper(state).Render(r.Context(), w)
return
}
views.RegisterPage(state).Render(r.Context(), w)
}
func handleRegisterCapabilities(w http.ResponseWriter, r *http.Request) {
caps := views.DeviceCapabilities{
Platform: true,
CrossPlatform: true,
Conditional: true,
}
views.CapabilitiesResult(caps).Render(r.Context(), w)
}
func handleRegisterVerifyCode(w http.ResponseWriter, r *http.Request) {
state := views.RegisterState{Step: 3}
if r.Header.Get("HX-Request") == "true" {
views.RegisterStepWithStepper(state).Render(r.Context(), w)
return
}
views.RegisterPage(state).Render(r.Context(), w)
}
func handleLogin(w http.ResponseWriter, r *http.Request) {
state := views.LoginState{Step: "1"}
views.LoginPage(state).Render(r.Context(), w)
}
func handleLoginStep(w http.ResponseWriter, r *http.Request) {
step := r.PathValue("step")
if step == "" {
step = "1"
}
state := views.LoginState{Step: step}
if r.Header.Get("HX-Request") == "true" {
views.LoginStepWithOOB(state).Render(r.Context(), w)
return
}
views.LoginPage(state).Render(r.Context(), w)
}
var qrPollCount = 0
func handleLoginQRStatus(w http.ResponseWriter, r *http.Request) {
qrPollCount++
if qrPollCount >= 3 {
qrPollCount = 0
views.QRStatusSuccess().Render(r.Context(), w)
return
}
views.QRStatusWaiting().Render(r.Context(), w)
}
func handleAuthorize(w http.ResponseWriter, r *http.Request) {
reqType := r.URL.Query().Get("type")
if reqType == "" {
reqType = "connect"
}
req := views.AuthRequest{
Type: reqType,
App: views.AppInfo{
Name: "Uniswap",
Domain: "app.uniswap.org",
LogoIcon: "cube",
Verified: true,
},
Wallet: views.WalletInfo{
Name: "Main Wallet",
Address: "sonr1x9f...7k2m",
Balance: "1,234.56 SNR",
},
Message: `Welcome to Uniswap!
Click to sign in and accept the Uniswap Terms of Service.
This request will not trigger a blockchain transaction or cost any gas fees.
Wallet address:
sonr1x9f4h2k8m3n5p7q2r4s6t8v0w3x5y7z9a1b3c5d7k2m
Nonce: 8f4a2b1c`,
MessageHex: "0x57656c636f6d6520746f20556e697377617021...",
Transaction: &views.TxDetails{
Type: "Swap",
FromToken: views.TokenAmount{
Symbol: "ETH",
Amount: "100.00",
USD: "$234,567.00",
Initials: "E",
},
ToToken: views.TokenAmount{
Symbol: "USDC",
Amount: "125,000",
USD: "$125,000.00",
Initials: "U",
},
Network: "Sonr Mainnet",
NetworkFee: "~$0.12",
MaxFee: "$0.26",
Slippage: "0.5%",
Contract: "0x7a25...3f8b",
Function: "swapExactTokensForTokens()",
RawData: "0x38ed1739\n0000000000000000000000000000000000000056bc75e2d63100000...",
},
}
views.AuthorizePage(req).Render(r.Context(), w)
}
func handleAuthorizeApprove(w http.ResponseWriter, r *http.Request) {
r.ParseForm()
actionType := r.FormValue("type")
if actionType == "" {
actionType = "connect"
}
views.AuthResultSuccess(actionType).Render(r.Context(), w)
}
func handleAuthorizeDeny(w http.ResponseWriter, r *http.Request) {
views.AuthResultDenied().Render(r.Context(), w)
}
func handleDashboard(w http.ResponseWriter, r *http.Request) {
tab := r.URL.Query().Get("tab")
if tab == "" {
tab = "accounts"
}
data := views.DefaultDashboardData()
views.DashboardPage(data, tab).Render(r.Context(), w)
}