mirror of
https://github.com/sonr-io/sonr.git
synced 2026-08-03 01:41:44 +00:00
feature/1115 execute ucan token (#1177)
- **deps: remove tigerbeetle-go dependency** - **refactor: remove unused landing page components and models** - **feat: add pin and publish vault handlers** - **refactor: move payment and credential services to webui browser package** - **refactor: remove unused credentials management components** - **feat: add landing page components and middleware for credentials and payments** - **refactor: remove unused imports in vault config** - **refactor: remove unused bank, DID, and DWN gRPC clients** - **refactor: rename client files and improve code structure** - **feat: add session middleware helpers and landing page components** - **feat: add user profile registration flow** - **feat: Implement WebAuthn registration flow** - **feat: add error view for users without WebAuthn devices** - **chore: update htmx to include extensions** - **refactor: rename pin handler to claim handler and update routes** - **chore: update import paths after moving UI components and styles** - **fix: address potential server errors by handling and logging them properly** - **refactor: move vault config to gateway package and update related dependencies** - **style: simplify form styling and remove unnecessary components** - **feat: improve UI design for registration flow** - **feat: implement passkey-based authentication** - **refactor: migrate registration forms to use reusable form components** - **refactor: remove tailwindcss setup and use CDN instead** - **style: update submit button style to use outline variant** - **refactor: refactor server and IPFS client, remove MPC encryption** - **refactor: Abstract keyshare functionality and improve message encoding** - **refactor: improve keyset JSON marshaling and error handling** - **feat: add support for digital signatures using MPC keys** - **fix: Refactor MarshalJSON to use standard json.Marshal for Message serialization** - **fix: Encode messages before storing in keyshare structs** - **style: update form input styles for improved user experience** - **refactor: improve code structure in registration handlers** - **refactor: consolidate signer middleware and IPFS interaction** - **refactor: rename MPC signing and refresh protocol functions** - **refactor: update hway configuration loading mechanism** - **feat: integrate database support for sessions and users** - **refactor: remove devnet infrastructure and simplify build process** - **docs(guides): add Sonr DID module guide** - **feat: integrate progress bar into registration form** - **refactor: migrate WebAuthn dependencies to protocol package** - **feat: enhance user registration with passkey integration and improved form styling** - **refactor: move gateway view handlers to internal pages package** - **refactor: Move address package to MPC module** - **feat: integrate turnstile for registration** - **style: remove unnecessary size attribute from buttons** - **refactor: rename cookie package to session/cookie** - **refactor: remove unnecessary types.Session dependency** - **refactor: rename pkg/core to pkg/chain** - **refactor: simplify deployment process by removing testnet-specific Taskfile and devbox configuration** - **feat: add error redirect functionality and improve routes** - **feat: implement custom error handling for gateway** - **chore: update version number to 0.0.7 in template** - **feat: add IPFS client implementation** - **feat: Implement full IPFS client interface with comprehensive methods** - **refactor: improve IPFS client path handling** - **refactor: Move UCAN middleware to controller package** - **feat: add UCAN middleware to motr** - **refactor: update libp2p dependency** - **docs: add UCAN specification document** - **refactor: move UCAN controller logic to common package** - **refactor: rename exports.go to common.go** - **feat: add UCAN token support** - **refactor: migrate UCAN token parsing to dedicated package** - **refactor: improve CometBFT and app config initialization** - **refactor: improve deployment scripts and documentation** - **feat: integrate IPFS and producer middleware** - **refactor: rename agent directory to aider** - **fix: correct libp2p import path** - **refactor: remove redundant dependency** - **cleanup: remove unnecessary test files** - **refactor: move attention types to crypto/ucan package** - **feat: expand capabilities and resource types for UCANs** - **refactor: rename sonr.go to codec.go and update related imports** - **feat: add IPFS-based token store** - **feat: Implement IPFS-based token store with caching and UCAN integration** - **feat: Add dynamic attenuation constructor for UCAN presets** - **fix: Handle missing or invalid attenuation data with EmptyAttenuation** - **fix: Update UCAN attenuation tests with correct capability types** - **feat: integrate UCAN-based authorization into the producer middleware** - **refactor: remove unused dependency on go-ucan** - **refactor: Move address handling logic to DID module** - **feat: Add support for compressed and uncompressed Secp256k1 public keys in didkey** - **test: Add test for generating DID key from MPC keyshares** - **feat: Add methods for extracting compressed and uncompressed public keys in share types** - **feat: Add BaseKeyshare struct with public key conversion methods** - **refactor: Use compressed and uncompressed public keys in keyshare, fix public key usage in tests and verification** - **feat: add support for key generation policy type** - **fix: correct typo in VaultPermissions constant** - **refactor: move JWT related code to ucan package** - **refactor: move UCAN JWT and source code to spec package**
This commit is contained in:
@@ -0,0 +1,7 @@
|
||||
package handlers
|
||||
|
||||
import "github.com/labstack/echo/v4"
|
||||
|
||||
func HandleConnect(c echo.Context) error {
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
func HandleDash(c echo.Context) error {
|
||||
return c.Render(http.StatusOK, "index.templ", nil)
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package handlers
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/onsonr/sonr/pkg/common/response"
|
||||
"github.com/onsonr/sonr/pkg/vault/internal/pages/index"
|
||||
"github.com/onsonr/sonr/pkg/vault/internal/session"
|
||||
)
|
||||
|
||||
func HandleIndex(c echo.Context) error {
|
||||
if isInitial(c) {
|
||||
return response.TemplEcho(c, index.InitialView())
|
||||
}
|
||||
if isExpired(c) {
|
||||
return response.TemplEcho(c, index.ReturningView())
|
||||
}
|
||||
return c.Render(http.StatusOK, "index.templ", nil)
|
||||
}
|
||||
|
||||
// ╭─────────────────────────────────────────────────────────╮
|
||||
// │ Utility Functions │
|
||||
// ╰─────────────────────────────────────────────────────────╯
|
||||
|
||||
// Initial users have no authorization, user handle, or vault address
|
||||
func isInitial(c echo.Context) bool {
|
||||
noAuth := !session.HasAuthorization(c)
|
||||
noUserHandle := !session.HasUserHandle(c)
|
||||
noVaultAddress := !session.HasVaultAddress(c)
|
||||
return noUserHandle && noVaultAddress && noAuth
|
||||
}
|
||||
|
||||
// Expired users have either a user handle or vault address
|
||||
func isExpired(c echo.Context) bool {
|
||||
noAuth := !session.HasAuthorization(c)
|
||||
hasUserHandle := session.HasUserHandle(c)
|
||||
hasVaultAddress := session.HasVaultAddress(c)
|
||||
return noAuth && hasUserHandle || noAuth && hasVaultAddress
|
||||
}
|
||||
|
||||
// Returning users have a valid authorization, and either a user handle or vault address
|
||||
func isReturning(c echo.Context) bool {
|
||||
hasAuth := session.HasAuthorization(c)
|
||||
hasUserHandle := session.HasUserHandle(c)
|
||||
hasVaultAddress := session.HasVaultAddress(c)
|
||||
return hasAuth && (hasUserHandle || hasVaultAddress)
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package handlers
|
||||
@@ -0,0 +1,93 @@
|
||||
package handlers
|
||||
|
||||
//
|
||||
// // Constants for supported payment methods
|
||||
// const (
|
||||
// MethodCard = "basic-card"
|
||||
// MethodGooglePay = "https://google.com/pay"
|
||||
// MethodApplePay = "https://apple.com/apple-pay"
|
||||
// MethodSonrWallet = "https://sonr.id/wallet"
|
||||
// )
|
||||
//
|
||||
// // InitiatePayment starts the payment request flow
|
||||
// func InitiatePayment(c echo.Context, request PaymentRequest) error {
|
||||
// return StartPayment(request).Render(c.Request().Context(), c.Response().Writer)
|
||||
// }
|
||||
//
|
||||
// // Helper functions to create payment requests
|
||||
// func NewBasicCardPayment(amount float64, currency string, label string) PaymentRequest {
|
||||
// return PaymentRequest{
|
||||
// MethodData: []PaymentMethodData{
|
||||
// {
|
||||
// SupportedMethods: MethodCard,
|
||||
// Data: map[string]any{
|
||||
// "supportedNetworks": []string{"visa", "mastercard"},
|
||||
// "supportedTypes": []string{"credit", "debit"},
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// Details: PaymentDetails{
|
||||
// Total: PaymentItem{
|
||||
// Label: label,
|
||||
// Amount: Money{
|
||||
// Currency: currency,
|
||||
// Value: formatAmount(amount),
|
||||
// },
|
||||
// },
|
||||
// },
|
||||
// Options: PaymentOptions{
|
||||
// RequestPayerName: true,
|
||||
// RequestPayerEmail: true,
|
||||
// },
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// // Example usage:
|
||||
// func PaymentHandler(c echo.Context) error {
|
||||
// request := NewBasicCardPayment(99.99, "USD", "Product Purchase")
|
||||
//
|
||||
// // Add display items
|
||||
// request.Details.DisplayItems = []PaymentItem{
|
||||
// {
|
||||
// Label: "Product Price",
|
||||
// Amount: Money{
|
||||
// Currency: "USD",
|
||||
// Value: "89.99",
|
||||
// },
|
||||
// },
|
||||
// {
|
||||
// Label: "Tax",
|
||||
// Amount: Money{
|
||||
// Currency: "USD",
|
||||
// Value: "10.00",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// // Add shipping options
|
||||
// request.Details.ShippingOptions = []ShippingOption{
|
||||
// {
|
||||
// ID: "standard",
|
||||
// Label: "Standard Shipping",
|
||||
// Amount: Money{
|
||||
// Currency: "USD",
|
||||
// Value: "0.00",
|
||||
// },
|
||||
// Selected: true,
|
||||
// },
|
||||
// {
|
||||
// ID: "express",
|
||||
// Label: "Express Shipping",
|
||||
// Amount: Money{
|
||||
// Currency: "USD",
|
||||
// Value: "10.00",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
//
|
||||
// return InitiatePayment(c, request)
|
||||
// }
|
||||
//
|
||||
// func formatAmount(amount float64) string {
|
||||
// return fmt.Sprintf("%.2f", amount)
|
||||
// }
|
||||
@@ -0,0 +1,7 @@
|
||||
package authorize
|
||||
|
||||
type AuthorizeRequest struct {
|
||||
Subject string
|
||||
Action string
|
||||
Origin string
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
package authorize
|
||||
|
||||
type AuthorizeRequest struct {
|
||||
Subject string
|
||||
Action string
|
||||
Origin string
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
package dash
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
templ ProfileView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Sonr.ID
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
The decentralized identity layer for the web.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
templ FeedView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Welcome Back!
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
Continue with your existing Sonr.ID.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package dash
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
func ProfileView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Sonr.ID</h1><p class=\"text-lg text-zinc-500\">The decentralized identity layer for the web.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Get Started</button></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func FeedView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Welcome Back!</h1><p class=\"text-lg text-zinc-500\">Continue with your existing Sonr.ID.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Login</button></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var3.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,29 @@
|
||||
package index
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
templ NoWebauthnErrorView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
No WebAuthn Devices
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
You don't have any WebAuthn devices connected to your computer.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package index
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
func NoWebauthnErrorView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">No WebAuthn Devices</h1><p class=\"text-lg text-zinc-500\">You don't have any WebAuthn devices connected to your computer.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Get Started</button></div></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,25 @@
|
||||
package internal
|
||||
|
||||
templ IntroView() {
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="relative text-center">
|
||||
<div class="flex flex-col mb-6 space-y-2">
|
||||
<span>
|
||||
<wa-qr-code size="140" value="https://shoelace.style/"></wa-qr-code>
|
||||
</span>
|
||||
<h1 class="text-2xl lg:text-3xl font-bold pb-3">
|
||||
<span>Shoelace</span>
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
A lightweight library for building accessible, high-performance UI components with
|
||||
no dependencies.
|
||||
</p>
|
||||
</div>
|
||||
<div class="max-w-xs mx-auto sm:max-w-none sm:inline-flex sm:justify-center space-y-4 sm:space-y-0 sm:space-x-4">
|
||||
<button class="inline-flex items-center justify-center w-full h-10 px-4 py-2 text-sm font font-medium text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900">
|
||||
Get started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package internal
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func IntroView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"relative text-center\"><div class=\"flex flex-col mb-6 space-y-2\"><span><wa-qr-code size=\"140\" value=\"https://shoelace.style/\"></wa-qr-code></span><h1 class=\"text-2xl lg:text-3xl font-bold pb-3\"><span>Shoelace</span></h1><p class=\"text-lg text-zinc-500\">A lightweight library for building accessible, high-performance UI components with no dependencies.</p></div><div class=\"max-w-xs mx-auto sm:max-w-none sm:inline-flex sm:justify-center space-y-4 sm:space-y-0 sm:space-x-4\"><button class=\"inline-flex items-center justify-center w-full h-10 px-4 py-2 text-sm font font-medium text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900\">Get started</button></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,25 @@
|
||||
package internal
|
||||
|
||||
templ ProfileForm() {
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="relative text-center">
|
||||
<div class="flex flex-col mb-6 space-y-2">
|
||||
<span>
|
||||
<wa-qr-code size="140" value="https://shoelace.style/"></wa-qr-code>
|
||||
</span>
|
||||
<h1 class="text-2xl lg:text-3xl font-bold pb-3">
|
||||
<span>Shoelace</span>
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
A lightweight library for building accessible, high-performance UI components with
|
||||
no dependencies.
|
||||
</p>
|
||||
</div>
|
||||
<div class="max-w-xs mx-auto sm:max-w-none sm:inline-flex sm:justify-center space-y-4 sm:space-y-0 sm:space-x-4">
|
||||
<button class="inline-flex items-center justify-center w-full h-10 px-4 py-2 text-sm font-medium text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900">
|
||||
Get started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package internal
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func ProfileForm() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"relative text-center\"><div class=\"flex flex-col mb-6 space-y-2\"><span><wa-qr-code size=\"140\" value=\"https://shoelace.style/\"></wa-qr-code></span><h1 class=\"text-2xl lg:text-3xl font-bold pb-3\"><span>Shoelace</span></h1><p class=\"text-lg text-zinc-500\">A lightweight library for building accessible, high-performance UI components with no dependencies.</p></div><div class=\"max-w-xs mx-auto sm:max-w-none sm:inline-flex sm:justify-center space-y-4 sm:space-y-0 sm:space-x-4\"><button class=\"inline-flex items-center justify-center w-full h-10 px-4 py-2 text-sm font-medium text-white transition-colors duration-200 rounded-md bg-neutral-950 hover:bg-neutral-900 focus:ring-2 focus:ring-offset-2 focus:ring-neutral-900\">Get started</button></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,57 @@
|
||||
package index
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
templ InitialView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Sonr.ID
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
The decentralized identity layer for the web.
|
||||
</p>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="pt-3 flex flex-col items-center justify-center h-full">
|
||||
<div hx-get="/register" hx-swap="outerHTML" class="pointer:cursor-pointer btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Get Started
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
templ ReturningView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Welcome Back!
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
Continue with your existing Sonr.ID.
|
||||
</p>
|
||||
</div>
|
||||
<br/>
|
||||
<div class="pt-3 flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package index
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
func InitialView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Sonr.ID</h1><p class=\"text-lg text-zinc-500\">The decentralized identity layer for the web.</p></div><br><div class=\"pt-3 flex flex-col items-center justify-center h-full\"><div hx-get=\"/register\" hx-swap=\"outerHTML\" class=\"pointer:cursor-pointer btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Get Started</div></div></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func ReturningView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Welcome Back!</h1><p class=\"text-lg text-zinc-500\">Continue with your existing Sonr.ID.</p></div><br><div class=\"pt-3 flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Login</button></div></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,43 @@
|
||||
package wallet
|
||||
|
||||
// Payment types
|
||||
type PaymentMethodData struct {
|
||||
SupportedMethods string `json:"supportedMethods"`
|
||||
Data map[string]any `json:"data,omitempty"`
|
||||
}
|
||||
|
||||
type PaymentItem struct {
|
||||
Label string `json:"label"`
|
||||
Amount Money `json:"amount"`
|
||||
}
|
||||
|
||||
type Money struct {
|
||||
Currency string `json:"currency"`
|
||||
Value string `json:"value"` // Decimal as string for precision
|
||||
}
|
||||
|
||||
type PaymentOptions struct {
|
||||
RequestPayerName bool `json:"requestPayerName,omitempty"`
|
||||
RequestPayerEmail bool `json:"requestPayerEmail,omitempty"`
|
||||
RequestPayerPhone bool `json:"requestPayerPhone,omitempty"`
|
||||
RequestShipping bool `json:"requestShipping,omitempty"`
|
||||
}
|
||||
|
||||
type PaymentDetails struct {
|
||||
Total PaymentItem `json:"total"`
|
||||
DisplayItems []PaymentItem `json:"displayItems,omitempty"`
|
||||
ShippingOptions []ShippingOption `json:"shippingOptions,omitempty"`
|
||||
}
|
||||
|
||||
type ShippingOption struct {
|
||||
ID string `json:"id"`
|
||||
Label string `json:"label"`
|
||||
Amount Money `json:"amount"`
|
||||
Selected bool `json:"selected,omitempty"`
|
||||
}
|
||||
|
||||
type PaymentRequest struct {
|
||||
MethodData []PaymentMethodData `json:"methodData"`
|
||||
Details PaymentDetails `json:"details"`
|
||||
Options PaymentOptions `json:"options,omitempty"`
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
package wallet
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
templ DepositFundsView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Sonr.ID
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
The decentralized identity layer for the web.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
templ SwapTokensView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Sonr.ID
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
The decentralized identity layer for the web.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
templ ConfirmPasscodeView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Sonr.ID
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
The decentralized identity layer for the web.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Get Started
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
|
||||
templ TransferTokensView() {
|
||||
@layout.Root("Sonr.ID") {
|
||||
<div class="flex fixed inset-0 z-[99] w-screen h-screen bg-white">
|
||||
<div class="relative flex flex-wrap items-center w-full h-full px-8">
|
||||
<div class="relative w-full max-w-sm mx-auto lg:mb-0">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<h1 class="text-3xl font-bold text-zinc-900 mb-4">
|
||||
Welcome Back!
|
||||
</h1>
|
||||
<p class="text-lg text-zinc-500">
|
||||
Continue with your existing Sonr.ID.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-col items-center justify-center h-full">
|
||||
<button class="btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow">
|
||||
Login
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
{ children... }
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,233 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package wallet
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
import "github.com/onsonr/sonr/pkg/styles/layout"
|
||||
|
||||
func DepositFundsView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Sonr.ID</h1><p class=\"text-lg text-zinc-500\">The decentralized identity layer for the web.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Get Started</button></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func SwapTokensView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var4 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Sonr.ID</h1><p class=\"text-lg text-zinc-500\">The decentralized identity layer for the web.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Get Started</button></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var3.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func ConfirmPasscodeView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var6 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Sonr.ID</h1><p class=\"text-lg text-zinc-500\">The decentralized identity layer for the web.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Get Started</button></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var5.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
func TransferTokensView() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var7 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var7 == nil {
|
||||
templ_7745c5c3_Var7 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<div class=\"flex fixed inset-0 z-[99] w-screen h-screen bg-white\"><div class=\"relative flex flex-wrap items-center w-full h-full px-8\"><div class=\"relative w-full max-w-sm mx-auto lg:mb-0\"><div class=\"flex flex-col items-center justify-center h-full\"><div class=\"flex flex-col items-center justify-center h-full\"><h1 class=\"text-3xl font-bold text-zinc-900 mb-4\">Welcome Back!</h1><p class=\"text-lg text-zinc-500\">Continue with your existing Sonr.ID.</p></div><div class=\"flex flex-col items-center justify-center h-full\"><button class=\"btn btn-sm text-zinc-100 bg-zinc-900 hover:bg-zinc-800 w-full shadow\">Login</button></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templ_7745c5c3_Var7.Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = layout.Root("Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,107 @@
|
||||
package wallet
|
||||
|
||||
var paymentsHandle = templ.NewOnceHandle()
|
||||
|
||||
// Base payments script template
|
||||
templ PaymentsScripts() {
|
||||
@paymentsHandle.Once() {
|
||||
<script type="text/javascript">
|
||||
// Check if Payment Request API is supported
|
||||
function isPaymentRequestSupported() {
|
||||
return window.PaymentRequest !== undefined;
|
||||
}
|
||||
|
||||
// Create and show payment request
|
||||
async function showPaymentRequest(request) {
|
||||
try {
|
||||
const paymentMethods = request.methodData;
|
||||
const details = request.details;
|
||||
const options = request.options || {};
|
||||
|
||||
const paymentRequest = new PaymentRequest(
|
||||
paymentMethods,
|
||||
details,
|
||||
options
|
||||
);
|
||||
|
||||
// Handle shipping address changes if shipping is requested
|
||||
if (options.requestShipping) {
|
||||
paymentRequest.addEventListener('shippingaddresschange', event => {
|
||||
event.updateWith(Promise.resolve(details));
|
||||
});
|
||||
}
|
||||
|
||||
// Handle shipping option changes
|
||||
if (details.shippingOptions && details.shippingOptions.length > 0) {
|
||||
paymentRequest.addEventListener('shippingoptionchange', event => {
|
||||
event.updateWith(Promise.resolve(details));
|
||||
});
|
||||
}
|
||||
|
||||
const response = await paymentRequest.show();
|
||||
|
||||
// Create response object
|
||||
const result = {
|
||||
methodName: response.methodName,
|
||||
details: response.details,
|
||||
};
|
||||
|
||||
if (options.requestPayerName) {
|
||||
result.payerName = response.payerName;
|
||||
}
|
||||
if (options.requestPayerEmail) {
|
||||
result.payerEmail = response.payerEmail;
|
||||
}
|
||||
if (options.requestPayerPhone) {
|
||||
result.payerPhone = response.payerPhone;
|
||||
}
|
||||
if (options.requestShipping) {
|
||||
result.shippingAddress = response.shippingAddress;
|
||||
result.shippingOption = response.shippingOption;
|
||||
}
|
||||
|
||||
// Complete the payment
|
||||
await response.complete('success');
|
||||
|
||||
// Dispatch success event
|
||||
window.dispatchEvent(new CustomEvent('paymentComplete', {
|
||||
detail: result
|
||||
}));
|
||||
|
||||
} catch (err) {
|
||||
// Dispatch error event
|
||||
window.dispatchEvent(new CustomEvent('paymentError', {
|
||||
detail: err.message
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
// Abort payment request
|
||||
function abortPaymentRequest() {
|
||||
if (window.currentPaymentRequest) {
|
||||
window.currentPaymentRequest.abort();
|
||||
}
|
||||
}
|
||||
</script>
|
||||
}
|
||||
}
|
||||
|
||||
// StartPayment for initiating payment request
|
||||
templ StartPayment(request PaymentRequest) {
|
||||
@PaymentsScripts()
|
||||
<script>
|
||||
(async () => {
|
||||
try {
|
||||
if (!isPaymentRequestSupported()) {
|
||||
throw new Error("Payment Request API is not supported in this browser");
|
||||
}
|
||||
const request = { templ.JSONString(request) };
|
||||
await showPaymentRequest(request);
|
||||
} catch (err) {
|
||||
window.dispatchEvent(new CustomEvent('paymentError', {
|
||||
detail: err.message
|
||||
}));
|
||||
}
|
||||
})();
|
||||
</script>
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.2.793
|
||||
package wallet
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
var paymentsHandle = templ.NewOnceHandle()
|
||||
|
||||
// Base payments script template
|
||||
func PaymentsScripts() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script type=\"text/javascript\">\n // Check if Payment Request API is supported\n function isPaymentRequestSupported() {\n return window.PaymentRequest !== undefined;\n }\n\n // Create and show payment request\n async function showPaymentRequest(request) {\n try {\n const paymentMethods = request.methodData;\n const details = request.details;\n const options = request.options || {};\n\n const paymentRequest = new PaymentRequest(\n paymentMethods,\n details,\n options\n );\n\n // Handle shipping address changes if shipping is requested\n if (options.requestShipping) {\n paymentRequest.addEventListener('shippingaddresschange', event => {\n event.updateWith(Promise.resolve(details));\n });\n }\n\n // Handle shipping option changes\n if (details.shippingOptions && details.shippingOptions.length > 0) {\n paymentRequest.addEventListener('shippingoptionchange', event => {\n event.updateWith(Promise.resolve(details));\n });\n }\n\n const response = await paymentRequest.show();\n \n // Create response object\n const result = {\n methodName: response.methodName,\n details: response.details,\n };\n\n if (options.requestPayerName) {\n result.payerName = response.payerName;\n }\n if (options.requestPayerEmail) {\n result.payerEmail = response.payerEmail;\n }\n if (options.requestPayerPhone) {\n result.payerPhone = response.payerPhone;\n }\n if (options.requestShipping) {\n result.shippingAddress = response.shippingAddress;\n result.shippingOption = response.shippingOption;\n }\n\n // Complete the payment\n await response.complete('success');\n\n // Dispatch success event\n window.dispatchEvent(new CustomEvent('paymentComplete', {\n detail: result\n }));\n\n } catch (err) {\n // Dispatch error event\n window.dispatchEvent(new CustomEvent('paymentError', {\n detail: err.message\n }));\n }\n }\n\n // Abort payment request\n function abortPaymentRequest() {\n if (window.currentPaymentRequest) {\n window.currentPaymentRequest.abort();\n }\n }\n </script>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
templ_7745c5c3_Err = paymentsHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
// StartPayment for initiating payment request
|
||||
func StartPayment(request PaymentRequest) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = PaymentsScripts().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<script>\n (async () => {\n try {\n if (!isPaymentRequestSupported()) {\n throw new Error(\"Payment Request API is not supported in this browser\");\n }\n const request = { templ.JSONString(request) };\n await showPaymentRequest(request);\n } catch (err) {\n window.dispatchEvent(new CustomEvent('paymentError', {\n detail: err.message\n }));\n }\n })();\n </script>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return templ_7745c5c3_Err
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
@@ -0,0 +1,156 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"regexp"
|
||||
"strings"
|
||||
|
||||
"github.com/go-webauthn/webauthn/protocol"
|
||||
"github.com/go-webauthn/webauthn/protocol/webauthncose"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/segmentio/ksuid"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
)
|
||||
|
||||
const kWebAuthnTimeout = 6000
|
||||
|
||||
// TODO: Returns fixed chain ID for testing.
|
||||
func GetChainID(c echo.Context) string {
|
||||
return "sonr-testnet-1"
|
||||
}
|
||||
|
||||
// SetVaultAddress sets the address of the vault
|
||||
func SetVaultAddress(c echo.Context, address string) error {
|
||||
return common.WriteCookie(c, common.SonrAddress, address)
|
||||
}
|
||||
|
||||
// SetVaultAuthorization sets the UCAN CID of the vault
|
||||
func SetVaultAuthorization(c echo.Context, ucanCID string) error {
|
||||
common.HeaderWrite(c, common.Authorization, formatAuth(ucanCID))
|
||||
return nil
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Initialization │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func loadOrGenKsuid(c echo.Context) error {
|
||||
var (
|
||||
sessionID string
|
||||
err error
|
||||
)
|
||||
|
||||
// Setup genKsuid function
|
||||
genKsuid := func() string {
|
||||
return ksuid.New().String()
|
||||
}
|
||||
|
||||
// Attempt to read the session ID from the "session" cookie
|
||||
if ok := common.CookieExists(c, common.SessionID); !ok {
|
||||
sessionID = genKsuid()
|
||||
} else {
|
||||
sessionID, err = common.ReadCookie(c, common.SessionID)
|
||||
if err != nil {
|
||||
sessionID = genKsuid()
|
||||
}
|
||||
}
|
||||
common.WriteCookie(c, common.SessionID, sessionID)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Extraction │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func extractPeerInfo(c echo.Context) (string, string) {
|
||||
var chal protocol.URLEncodedBase64
|
||||
id, _ := common.ReadCookie(c, common.SessionID)
|
||||
chalRaw, _ := common.ReadCookieBytes(c, common.SessionChallenge)
|
||||
chal.UnmarshalJSON(chalRaw)
|
||||
|
||||
return id, common.Base64Encode(chal)
|
||||
}
|
||||
|
||||
func extractBrowserInfo(c echo.Context) (string, string) {
|
||||
secCHUA := common.HeaderRead(c, common.UserAgent)
|
||||
|
||||
// If common.is empty, return empty BrowserInfo
|
||||
if secCHUA == "" {
|
||||
return "N/A", "-1"
|
||||
}
|
||||
|
||||
// Split the common.into individual browser entries
|
||||
var (
|
||||
name string
|
||||
ver string
|
||||
)
|
||||
entries := strings.Split(strings.TrimSpace(secCHUA), ",")
|
||||
for _, entry := range entries {
|
||||
// Remove leading/trailing spaces and quotes
|
||||
entry = strings.TrimSpace(entry)
|
||||
|
||||
// Use regex to extract the browser name and version
|
||||
re := regexp.MustCompile(`"([^"]+)";v="([^"]+)"`)
|
||||
matches := re.FindStringSubmatch(entry)
|
||||
|
||||
if len(matches) == 3 {
|
||||
browserName := matches[1]
|
||||
version := matches[2]
|
||||
|
||||
// Skip "Not A;Brand"
|
||||
if !validBrowser(browserName) {
|
||||
continue
|
||||
}
|
||||
|
||||
// Store the first valid browser info as fallback
|
||||
name = browserName
|
||||
ver = version
|
||||
}
|
||||
}
|
||||
return name, ver
|
||||
}
|
||||
|
||||
func validBrowser(name string) bool {
|
||||
return name != common.BrowserNameUnknown.String() && name != common.BrowserNameChromium.String()
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Authentication │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func buildUserEntity(userID string) protocol.UserEntity {
|
||||
return protocol.UserEntity{
|
||||
ID: userID,
|
||||
}
|
||||
}
|
||||
|
||||
// returns the base options for registering a new user without challenge or user entity.
|
||||
func baseRegisterOptions() *protocol.PublicKeyCredentialCreationOptions {
|
||||
return &protocol.PublicKeyCredentialCreationOptions{
|
||||
Timeout: kWebAuthnTimeout,
|
||||
Attestation: protocol.PreferDirectAttestation,
|
||||
AuthenticatorSelection: protocol.AuthenticatorSelection{
|
||||
AuthenticatorAttachment: "platform",
|
||||
ResidentKey: protocol.ResidentKeyRequirementPreferred,
|
||||
UserVerification: "preferred",
|
||||
},
|
||||
Parameters: []protocol.CredentialParameter{
|
||||
{
|
||||
Type: "public-key",
|
||||
Algorithm: webauthncose.AlgES256,
|
||||
},
|
||||
{
|
||||
Type: "public-key",
|
||||
Algorithm: webauthncose.AlgES256K,
|
||||
},
|
||||
{
|
||||
Type: "public-key",
|
||||
Algorithm: webauthncose.AlgEdDSA,
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func formatAuth(ucanCID string) string {
|
||||
return "Bearer " + ucanCID
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"net/http"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
"github.com/onsonr/sonr/pkg/vault/types"
|
||||
)
|
||||
|
||||
type SessionCtx interface {
|
||||
ID() string
|
||||
BrowserName() string
|
||||
BrowserVersion() string
|
||||
}
|
||||
|
||||
type contextKey string
|
||||
|
||||
// Context keys
|
||||
const (
|
||||
DataContextKey contextKey = "http_session_data"
|
||||
)
|
||||
|
||||
// Get returns the session.Context from the echo context.
|
||||
func Get(c echo.Context) (SessionCtx, error) {
|
||||
ctx, ok := c.(*HTTPContext)
|
||||
if !ok {
|
||||
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Session Context not found")
|
||||
}
|
||||
return ctx, nil
|
||||
}
|
||||
|
||||
// WebNodeMiddleware establishes a Session Cookie.
|
||||
func Middleware(config *types.Config) echo.MiddlewareFunc {
|
||||
return func(next echo.HandlerFunc) echo.HandlerFunc {
|
||||
return func(c echo.Context) error {
|
||||
err := injectConfig(c, config)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
cc := injectSession(c, common.RoleMotr)
|
||||
return next(cc)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func injectConfig(c echo.Context, config *types.Config) error {
|
||||
common.HeaderWrite(c, common.SonrAPIURL, config.SonrApiUrl)
|
||||
common.HeaderWrite(c, common.SonrRPCURL, config.SonrRpcUrl)
|
||||
|
||||
common.WriteCookie(c, common.SonrAddress, config.MotrAddress)
|
||||
schemaBz, err := json.Marshal(config.VaultSchema)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
common.WriteCookieBytes(c, common.VaultSchema, schemaBz)
|
||||
return nil
|
||||
}
|
||||
|
||||
// injectSession returns the session injectSession from the cookies.
|
||||
func injectSession(c echo.Context, role common.PeerRole) *HTTPContext {
|
||||
if c == nil {
|
||||
return initHTTPContext(nil)
|
||||
}
|
||||
|
||||
common.WriteCookie(c, common.SessionRole, role.String())
|
||||
|
||||
// Continue even if there are errors, just ensure we have valid session data
|
||||
if err := loadOrGenKsuid(c); err != nil {
|
||||
// Log error but continue
|
||||
}
|
||||
return initHTTPContext(c)
|
||||
}
|
||||
|
||||
// HasAuthorization checks if the request has an authorization header
|
||||
func HasAuthorization(c echo.Context) bool {
|
||||
return common.HeaderExists(c, common.Authorization)
|
||||
}
|
||||
|
||||
// HasUserHandle checks if the request has a user handle cookie
|
||||
func HasUserHandle(c echo.Context) bool {
|
||||
return common.CookieExists(c, common.UserHandle)
|
||||
}
|
||||
|
||||
// HasVaultAddress checks if the request has a vault address cookie
|
||||
func HasVaultAddress(c echo.Context) bool {
|
||||
return common.CookieExists(c, common.SonrAddress)
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
package session
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common"
|
||||
)
|
||||
|
||||
// HTTPContext is the context for HTTP endpoints.
|
||||
type HTTPContext struct {
|
||||
echo.Context
|
||||
role common.PeerRole
|
||||
id string
|
||||
chal string
|
||||
bn string
|
||||
bv string
|
||||
}
|
||||
|
||||
// initHTTPContext loads the headers from the request.
|
||||
func initHTTPContext(c echo.Context) *HTTPContext {
|
||||
if c == nil {
|
||||
return &HTTPContext{}
|
||||
}
|
||||
|
||||
id, chal := extractPeerInfo(c)
|
||||
bn, bv := extractBrowserInfo(c)
|
||||
|
||||
cc := &HTTPContext{
|
||||
Context: c,
|
||||
role: common.PeerRole(common.ReadCookieUnsafe(c, common.SessionRole)),
|
||||
id: id,
|
||||
chal: chal,
|
||||
bn: bn,
|
||||
bv: bv,
|
||||
}
|
||||
|
||||
// Set the session data in both contexts
|
||||
return cc
|
||||
}
|
||||
|
||||
func (s *HTTPContext) ID() string {
|
||||
return s.id
|
||||
}
|
||||
|
||||
func (s *HTTPContext) BrowserName() string {
|
||||
return s.bn
|
||||
}
|
||||
|
||||
func (s *HTTPContext) BrowserVersion() string {
|
||||
return s.bv
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
package middleware
|
||||
@@ -1 +0,0 @@
|
||||
package middleware
|
||||
+7
-2
@@ -1,16 +1,21 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
// Package vault provides the routes for the Decentralized Web Node (...or Sonr Motr).
|
||||
package vault
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/vault/handlers"
|
||||
"github.com/onsonr/sonr/pkg/vault/internal/session"
|
||||
"github.com/onsonr/sonr/pkg/vault/types"
|
||||
)
|
||||
|
||||
// RegisterAPI registers the Decentralized Web Node API routes.
|
||||
func RegisterAPI(e *echo.Echo) {
|
||||
// RegisterRoutes registers the Decentralized Web Node API routes.
|
||||
func RegisterRoutes(e *echo.Echo, config *types.Config) {
|
||||
e.Use(session.Middleware(config))
|
||||
|
||||
e.GET("/register/:subject/start", handlers.RegisterSubjectStart)
|
||||
e.POST("/register/:subject/finish", handlers.RegisterSubjectFinish)
|
||||
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
package types
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"strings"
|
||||
|
||||
"github.com/onsonr/sonr/pkg/common/models"
|
||||
)
|
||||
|
||||
const SchemaVersion = 1
|
||||
|
||||
// DefaultSchema returns the default schema
|
||||
func DefaultSchema() *Schema {
|
||||
return &Schema{
|
||||
Version: SchemaVersion,
|
||||
Account: getSchema(&models.Account{}),
|
||||
Asset: getSchema(&models.Asset{}),
|
||||
Chain: getSchema(&models.Chain{}),
|
||||
Credential: getSchema(&models.Credential{}),
|
||||
Grant: getSchema(&models.Grant{}),
|
||||
Keyshare: getSchema(&models.Keyshare{}),
|
||||
Profile: getSchema(&models.Profile{}),
|
||||
}
|
||||
}
|
||||
|
||||
func getSchema(structType interface{}) string {
|
||||
t := reflect.TypeOf(structType)
|
||||
if t.Kind() == reflect.Ptr {
|
||||
t = t.Elem()
|
||||
}
|
||||
|
||||
if t.Kind() != reflect.Struct {
|
||||
return ""
|
||||
}
|
||||
|
||||
var fields []string
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
fieldName := toCamelCase(field.Name)
|
||||
fields = append(fields, fieldName)
|
||||
}
|
||||
|
||||
// Add "++" at the beginning, separated by a comma
|
||||
return "++, " + strings.Join(fields, ", ")
|
||||
}
|
||||
|
||||
func toCamelCase(s string) string {
|
||||
if s == "" {
|
||||
return s
|
||||
}
|
||||
if len(s) == 1 {
|
||||
return strings.ToLower(s)
|
||||
}
|
||||
return strings.ToLower(s[:1]) + s[1:]
|
||||
}
|
||||
@@ -1,137 +0,0 @@
|
||||
package types
|
||||
|
||||
func NewWebManifest() WebManifest {
|
||||
return baseWebManifest
|
||||
}
|
||||
|
||||
var baseWebManifest = WebManifest{
|
||||
Name: "Sonr Vault",
|
||||
ShortName: "Sonr.ID",
|
||||
StartURL: "/index.html",
|
||||
Display: "standalone",
|
||||
DisplayOverride: []string{
|
||||
"fullscreen",
|
||||
"minimal-ui",
|
||||
},
|
||||
Icons: []IconDefinition{
|
||||
{
|
||||
Src: "/icons/icon-192x192.png",
|
||||
Sizes: "192x192",
|
||||
Type: "image/png",
|
||||
},
|
||||
},
|
||||
ServiceWorker: ServiceWorker{
|
||||
Scope: "/",
|
||||
Src: "/sw.js",
|
||||
UseCache: true,
|
||||
},
|
||||
ProtocolHandlers: []ProtocolHandler{
|
||||
{
|
||||
Scheme: "did.sonr",
|
||||
URL: "/resolve/sonr/%s",
|
||||
},
|
||||
{
|
||||
Scheme: "did.eth",
|
||||
URL: "/resolve/eth/%s",
|
||||
},
|
||||
{
|
||||
Scheme: "did.btc",
|
||||
URL: "/resolve/btc/%s",
|
||||
},
|
||||
{
|
||||
Scheme: "did.usdc",
|
||||
URL: "/resolve/usdc/%s",
|
||||
},
|
||||
{
|
||||
Scheme: "did.ipfs",
|
||||
URL: "/resolve/ipfs/%s",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
type WebManifest struct {
|
||||
// Required fields
|
||||
Name string `json:"name"` // Full name of the application
|
||||
ShortName string `json:"short_name"` // Short version of the name
|
||||
|
||||
// Display and appearance
|
||||
Description string `json:"description,omitempty"` // Purpose and features of the application
|
||||
Display string `json:"display,omitempty"` // Preferred display mode: fullscreen, standalone, minimal-ui, browser
|
||||
DisplayOverride []string `json:"display_override,omitempty"`
|
||||
ThemeColor string `json:"theme_color,omitempty"` // Default theme color for the application
|
||||
BackgroundColor string `json:"background_color,omitempty"` // Background color during launch
|
||||
Orientation string `json:"orientation,omitempty"` // Default orientation: any, natural, landscape, portrait
|
||||
|
||||
// URLs and scope
|
||||
StartURL string `json:"start_url"` // Starting URL when launching
|
||||
Scope string `json:"scope,omitempty"` // Navigation scope of the web application
|
||||
ServiceWorker ServiceWorker `json:"service_worker,omitempty"`
|
||||
|
||||
// Icons
|
||||
Icons []IconDefinition `json:"icons,omitempty"`
|
||||
|
||||
// Optional features
|
||||
RelatedApplications []RelatedApplication `json:"related_applications,omitempty"`
|
||||
PreferRelatedApplications bool `json:"prefer_related_applications,omitempty"`
|
||||
Shortcuts []Shortcut `json:"shortcuts,omitempty"`
|
||||
|
||||
// Experimental features (uncomment if needed)
|
||||
FileHandlers []FileHandler `json:"file_handlers,omitempty"`
|
||||
ProtocolHandlers []ProtocolHandler `json:"protocol_handlers,omitempty"`
|
||||
}
|
||||
|
||||
type FileHandler struct {
|
||||
Action string `json:"action"`
|
||||
Accept map[string][]string `json:"accept"`
|
||||
}
|
||||
|
||||
type LaunchHandler struct {
|
||||
Action string `json:"action"`
|
||||
}
|
||||
|
||||
type IconDefinition struct {
|
||||
Src string `json:"src"`
|
||||
Sizes string `json:"sizes"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Purpose string `json:"purpose,omitempty"`
|
||||
}
|
||||
|
||||
type ProtocolHandler struct {
|
||||
Scheme string `json:"scheme"`
|
||||
URL string `json:"url"`
|
||||
}
|
||||
|
||||
type RelatedApplication struct {
|
||||
Platform string `json:"platform"`
|
||||
URL string `json:"url,omitempty"`
|
||||
ID string `json:"id,omitempty"`
|
||||
}
|
||||
|
||||
type Shortcut struct {
|
||||
Name string `json:"name"`
|
||||
ShortName string `json:"short_name,omitempty"`
|
||||
Description string `json:"description,omitempty"`
|
||||
URL string `json:"url"`
|
||||
Icons []IconDefinition `json:"icons,omitempty"`
|
||||
}
|
||||
|
||||
type ServiceWorker struct {
|
||||
Scope string `json:"scope"`
|
||||
Src string `json:"src"`
|
||||
UseCache bool `json:"use_cache"`
|
||||
}
|
||||
|
||||
// Example usage:
|
||||
// manifest := WebManifest{
|
||||
// Name: "My Amazing App",
|
||||
// ShortName: "MyApp",
|
||||
// StartURL: "/",
|
||||
// Display: "standalone",
|
||||
// Icons: []IconDefinition{
|
||||
// {
|
||||
// Src: "/icons/icon-192x192.png",
|
||||
// Sizes: "192x192",
|
||||
// Type: "image/png",
|
||||
// },
|
||||
// },
|
||||
// }
|
||||
Reference in New Issue
Block a user