feature/simplify ucan mpc did (#1195)

* feat: enable DID auth middleware

* feat: implement passkey creation flow

* feat: persist user address in cookie and retrieve user profile using address cookie

* feat: implement human verification challenge during session initialization

* refactor: remove unnecessary random number generation in profile creation

* refactor: rename credential validation handler and update related routes

* feat: improve profile validation and user experience

* feat: add page rendering for profile and passkey creation

* refactor: remove unused register handler and update routes

* refactor: remove unused imports and simplify credential validation

* fix: Correct insecure gRPC client connection

* refactor: rename models files for better organization

* refactor: refactor grpc client creation and management

* refactor: refactor common clients package

* <no value>

* feat: add CapAccount, CapInterchain, CapVault enums

* feat: add ChainId to ResAccount and ResInterchain

* feat: add asset code to resource account enumeration

* refactor: rename services package to providers

* feat: implement gateway database interactions

* refactor: move gateway repository to internal/gateway

* refactor: Migrate database provider to use sqlx

* refactor: Rename Vaults to VaultProvider in HTTPContext struct

* refactor: Migrate from GORM to sqlc Queries in database context methods

* refactor: Replace GORM with standard SQL and simplify database initialization

* refactor: Migrate session management from GORM to sqlc with type conversion

* refactor: Update import paths and model references in context package

* fix: Resolve session type conversion and middleware issues

* refactor: Migrate database from GORM to sqlx

* refactor: Move models to pkg/common, improve code structure

* refactor: move repository package to internal directory

* refactor: move gateway internal packages to context directory

* refactor: migrate database provider to use sqlx queries

* feat: add session ID to HTTP context and use it to load session data

* feat: implement vault creation API endpoint

* feat: add DIDKey generation from PubKey

* refactor: remove unused DIDAuth components

* refactor: move DID auth controller to vault context

* chore: remove unused DIDAuth package

* refactor: improve clarity of enclave refresh function

* feat: implement nonce-based key encryption for improved security

* feat: Add Export and Import methods with comprehensive tests for Enclave

* fix: Validate AES key length in keyshare encryption and decryption

* fix: Resolve key length validation by hashing input keys

* refactor: Update keyshare import to use protocol decoding

* feat: Refactor enclave encryption to support full enclave export/import

* refactor: Simplify Enclave interface methods by removing role parameter

* refactor: remove unnecessary serialization from enclave interface

* refactor: rename models package in gateway context

* refactor: rename keystore vault constants

* refactor: remove context parameter from Resolver methods

* feat: add CurrentBlock context function and update related components

* refactor: rename resolver.go to resolvers.go

* feat: Add SQLite random() generation for session and profile initialization

* refactor: Update SQL queries to use SQLite-style parameter placeholders

* refactor: Replace '?' placeholders with '$n' PostgreSQL parameter syntax

* <no value>

* refactor: refactor gateway to use middleware for database interactions and improve modularity

* feat: implement gateway for Sonr highway

* refactor: Remove unused gateway context and refactor cookie/header handling

* refactor: improve server initialization and middleware handling

* feat: implement human verification for profile creation

* feat: implement session management middleware

* refactor: refactor common models and config to internal package

* refactor: move env config to internal/config

* refactor: move database-related code to  directory

* refactor: move IPFS client to common package and improve code structure

* refactor: move querier to common package and rename to chain_query

* refactor: move webworker model to internal/models

* feat: add initial view template for Sonr.ID

* docs(concepts): Add documentation for cosmos-proto

* docs: move IBC transfer documentation to tools section

* refactor: rename initpkl.go to pkl_init.go for better naming consistency

* docs(theme): update dark mode toggle icons

* refactor: update sqlite3 driver to ncruces/go-sqlite3

* feat: add Vault model and database interactions

* refactor: Improve SQLite schema with better constraints and indexes

* chore: update project dependencies

* fix: use grpc.WithInsecure() for gRPC connection

* config: set localhost as default Sonr gRPC URL

* refactor: improve gateway middleware and refactor server initialization

* refactor: Remove foreign key pragma from schema SQL

* refactor: Remove foreign key constraints from database schema

* refactor: Convert primary key columns from INTEGER to TEXT

* refactor: Remove unnecessary redirect in error handling
This commit is contained in:
Prad Nukala
2024-12-16 20:29:54 +00:00
committed by GitHub
parent 6d27b926f6
commit 7c4586ce90
196 changed files with 4480 additions and 3192 deletions
+80
View File
@@ -0,0 +1,80 @@
package common
import (
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
nodev1beta1 "github.com/cosmos/cosmos-sdk/client/grpc/node"
didv1 "github.com/onsonr/sonr/api/did/v1"
dwnv1 "github.com/onsonr/sonr/api/dwn/v1"
svcv1 "github.com/onsonr/sonr/api/svc/v1"
"google.golang.org/grpc"
)
type (
StatusResponse = nodev1beta1.StatusResponse // StatusResponse is the response type for the Service.Status RPC method.
StatusRequest = nodev1beta1.StatusRequest // StatusRequest is the request type for the Service.Status RPC method.
BalanceRequest = bankv1beta1.QueryBalanceRequest // BalanceRequest is the request type for the Bank.Balance RPC method.
BalanceResponse = bankv1beta1.QueryBalanceResponse // BalanceResponse is the response type for the Bank.Balance RPC method.
AllBalancesRequest = bankv1beta1.QueryAllBalancesRequest // AllBalancesRequest is the request type for the Bank.AllBalances RPC method.
AllBalancesResponse = bankv1beta1.QueryAllBalancesResponse // AllBalancesResponse is the response type for the Bank.AllBalances RPC method.
TotalSupplyRequest = bankv1beta1.QueryTotalSupplyRequest // TotalSupplyRequest is the request type for the Bank.TotalSupply RPC method.
TotalSupplyResponse = bankv1beta1.QueryTotalSupplyResponse // TotalSupplyResponse is the response type for the Bank.TotalSupply RPC method.
DenomMetadataRequest = bankv1beta1.QueryDenomMetadataRequest // DenomMetadataRequest is the request type for the Bank.DenomMetadata RPC method.
DenomMetadataResponse = bankv1beta1.QueryDenomMetadataResponse // DenomMetadataResponse is the response type for the Bank.DenomMetadata RPC method.
BankParamsRequest = bankv1beta1.QueryParamsRequest // BankParamsRequest is the request type for the Bank.Params RPC method.
BankParamsResponse = bankv1beta1.QueryParamsResponse // BankParamsResponse is the response type for the Bank.Params RPC method.
DIDParamsRequest = didv1.QueryRequest // DIDParamsRequest is the request type for the DID.Params RPC method.
DIDParamsResponse = didv1.QueryParamsResponse // DIDParamsResponse is the response type for the DID.Params RPC method.
DIDResolveResponse = didv1.QueryResolveResponse // DIDResolveResponse is the response type for the DID.Resolve RPC method.
DWNParamsRequest = dwnv1.QueryParamsRequest // DWNParamsRequest is the request type for the DWN.Params RPC method.
DWNParamsResponse = dwnv1.QueryParamsResponse // DWNParamsResponse is the response type for the DWN.Params RPC method.
SVCParamsRequest = svcv1.QueryParamsRequest // SVCParamsRequest is the request type for the SVC.Params RPC method.
SVCParamsResponse = svcv1.QueryParamsResponse // SVCParamsResponse is the response type for the SVC.Params RPC method.
)
func conn(addr string) (*grpc.ClientConn, error) {
grpcConn, err := grpc.NewClient(addr, grpc.WithInsecure())
if err != nil {
return nil, err
}
return grpcConn, nil
}
func NewBankClient(addr string) (bankv1beta1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return bankv1beta1.NewQueryClient(conn), nil
}
func NewDIDClient(addr string) (didv1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return didv1.NewQueryClient(conn), nil
}
func NewDWNClient(addr string) (dwnv1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return dwnv1.NewQueryClient(conn), nil
}
func NewNodeClient(addr string) (nodev1beta1.ServiceClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return nodev1beta1.NewServiceClient(conn), nil
}
func NewSVCClient(addr string) (svcv1.QueryClient, error) {
conn, err := conn(addr)
if err != nil {
return nil, err
}
return svcv1.NewQueryClient(conn), nil
}
-49
View File
@@ -1,49 +0,0 @@
package common
import (
"encoding/base64"
)
type Payment struct {
IsPayment bool `json:"isPayment"`
}
type LargeBlob struct {
Support string `json:"support"`
Write string `json:"write"`
}
type BrowserName string
const (
BrowserNameUnknown BrowserName = " Not A;Brand"
BrowserNameChromium BrowserName = "Chromium"
)
func (n BrowserName) String() string {
return string(n)
}
type PeerRole string
const (
RoleUnknown PeerRole = "none"
RoleHway PeerRole = "hway"
RoleMotr PeerRole = "motr"
)
func (r PeerRole) Is(role PeerRole) bool {
return r == role
}
func (r PeerRole) String() string {
return string(r)
}
func Base64Encode(data []byte) string {
return base64.RawURLEncoding.EncodeToString(data)
}
func Base64Decode(data string) ([]byte, error) {
return base64.RawURLEncoding.DecodeString(data)
}
-124
View File
@@ -1,124 +0,0 @@
package common
import (
"encoding/base64"
"net/http"
"time"
"github.com/labstack/echo/v4"
)
// CookieKey is a type alias for string.
type CookieKey string
const (
// SessionID is the key for the session ID cookie.
SessionID CookieKey = "session.id"
// SessionChallenge is the key for the session challenge cookie.
SessionChallenge CookieKey = "session.challenge"
// SessionRole is the key for the session role cookie.
SessionRole CookieKey = "session.role"
// SonrAddress is the key for the Sonr address cookie.
SonrAddress CookieKey = "sonr.address"
// SonrDID is the key for the Sonr DID cookie.
SonrDID CookieKey = "sonr.did"
// UserAvatar is the key for the User Avatar cookie.
UserAvatar CookieKey = "user.avatar"
// UserHandle is the key for the User Handle cookie.
UserHandle CookieKey = "user.handle"
// UserName is the key for the User Name cookie.
UserName CookieKey = "user.full_name"
// VaultAddress is the key for the Vault address cookie.
VaultAddress CookieKey = "vault.address"
// VaultCID is the key for the Vault CID cookie.
VaultCID CookieKey = "vault.cid"
// VaultSchema is the key for the Vault schema cookie.
VaultSchema CookieKey = "vault.schema"
)
// String returns the string representation of the CookieKey.
func (c CookieKey) String() string {
return string(c)
}
// ╭───────────────────────────────────────────────────────────╮
// │ Utility Methods │
// ╰───────────────────────────────────────────────────────────╯
func CookieExists(c echo.Context, key CookieKey) bool {
ck, err := c.Cookie(key.String())
if err != nil {
return false
}
return ck != nil
}
func ReadCookie(c echo.Context, key CookieKey) (string, error) {
cookie, err := c.Cookie(key.String())
if err != nil {
// Cookie not found or other error
return "", err
}
if cookie == nil || cookie.Value == "" {
// Cookie is empty
return "", http.ErrNoCookie
}
return cookie.Value, nil
}
func ReadCookieBytes(c echo.Context, key CookieKey) ([]byte, error) {
cookie, err := c.Cookie(key.String())
if err != nil {
// Cookie not found or other error
return nil, err
}
if cookie == nil || cookie.Value == "" {
// Cookie is empty
return nil, http.ErrNoCookie
}
return base64.RawURLEncoding.DecodeString(cookie.Value)
}
func ReadCookieUnsafe(c echo.Context, key CookieKey) string {
ck, err := c.Cookie(key.String())
if err != nil {
return ""
}
return ck.Value
}
func WriteCookie(c echo.Context, key CookieKey, value string) error {
cookie := &http.Cookie{
Name: key.String(),
Value: value,
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
Path: "/",
// Add Secure and SameSite attributes as needed
}
c.SetCookie(cookie)
return nil
}
func WriteCookieBytes(c echo.Context, key CookieKey, value []byte) error {
cookie := &http.Cookie{
Name: key.String(),
Value: base64.RawURLEncoding.EncodeToString(value),
Expires: time.Now().Add(24 * time.Hour),
HttpOnly: true,
Path: "/",
// Add Secure and SameSite attributes as needed
}
c.SetCookie(cookie)
return nil
}
-52
View File
@@ -1,52 +0,0 @@
package common
import "github.com/labstack/echo/v4"
type HeaderKey string
const (
Authorization HeaderKey = "Authorization"
// User Agent
Architecture HeaderKey = "Sec-CH-UA-Arch"
Bitness HeaderKey = "Sec-CH-UA-Bitness"
FullVersionList HeaderKey = "Sec-CH-UA-Full-Version-List"
Mobile HeaderKey = "Sec-CH-UA-Mobile"
Model HeaderKey = "Sec-CH-UA-Model"
Platform HeaderKey = "Sec-CH-UA-Platform"
PlatformVersion HeaderKey = "Sec-CH-UA-Platform-Version"
UserAgent HeaderKey = "Sec-CH-UA"
// Sonr Injected
SonrAPIURL HeaderKey = "X-Sonr-API"
SonrgRPCURL HeaderKey = "X-Sonr-GRPC"
SonrRPCURL HeaderKey = "X-Sonr-RPC"
SonrWSURL HeaderKey = "X-Sonr-WS"
)
func (h HeaderKey) String() string {
return string(h)
}
// ╭───────────────────────────────────────────────────────────╮
// │ Utility Methods │
// ╰───────────────────────────────────────────────────────────╯
func HeaderEquals(c echo.Context, key HeaderKey, value string) bool {
return c.Response().Header().Get(key.String()) == value
}
// HeaderExists returns true if the request has the header Key.
func HeaderExists(c echo.Context, key HeaderKey) bool {
return c.Response().Header().Get(key.String()) != ""
}
// HeaderRead returns the header value for the Key.
func HeaderRead(c echo.Context, key HeaderKey) string {
return c.Response().Header().Get(key.String())
}
// HeaderWrite sets the header value for the Key.
func HeaderWrite(c echo.Context, key HeaderKey, value string) {
c.Response().Header().Set(key.String(), value)
}
@@ -1,4 +1,4 @@
package ipfsapi
package common
import (
"bytes"
@@ -9,13 +9,40 @@ import (
"github.com/ipfs/boxo/files"
"github.com/ipfs/boxo/path"
"github.com/ipfs/kubo/client/rpc"
"github.com/ipfs/kubo/core/coreiface/options"
)
// IPFS represents a wrapper interface abstracting the localhost api
type IPFS interface {
Add(data []byte) (string, error)
AddFile(file File) (string, error)
AddFolder(folder Folder) (string, error)
Exists(cid string) (bool, error)
Get(cid string) ([]byte, error)
IsPinned(ipns string) (bool, error)
Ls(cid string) ([]string, error)
Pin(cid string, name string) error
Unpin(cid string) error
}
type File interface {
files.File
Name() string
}
func NewFileMap(vs []File) map[string]files.Node {
m := make(map[string]files.Node)
for _, f := range vs {
m[f.Name()] = f
}
return m
}
type client struct {
api *rpc.HttpApi
}
func NewClient() (Client, error) {
func NewIPFS() (IPFS, error) {
api, err := rpc.NewLocalApi()
if err != nil {
return nil, err
@@ -55,7 +82,7 @@ func (c *client) Get(cid string) ([]byte, error) {
return buf.Bytes(), nil
}
func (c *client) IsPublished(ipns string) (bool, error) {
func (c *client) IsPinned(ipns string) (bool, error) {
_, err := c.api.Name().Resolve(context.Background(), ipns)
if err != nil {
return false, nil
@@ -75,12 +102,12 @@ func (c *client) Exists(cid string) (bool, error) {
return true, nil
}
func (c *client) Pin(cid string) error {
func (c *client) Pin(cid string, name string) error {
p, err := path.NewPath(cid)
if err != nil {
return err
}
return c.api.Pin().Add(context.Background(), p)
return c.api.Pin().Add(context.Background(), p, options.Pin.Name(name))
}
func (c *client) Unpin(cid string) error {
@@ -91,18 +118,6 @@ func (c *client) Unpin(cid string) error {
return c.api.Pin().Rm(context.Background(), p)
}
func (c *client) Publish(cid string, name string) (string, error) {
p, err := path.NewPath(cid)
if err != nil {
return "", err
}
result, err := c.api.Name().Publish(context.Background(), p)
if err != nil {
return "", err
}
return result.String(), nil
}
func (c *client) Ls(cid string) ([]string, error) {
p, err := path.NewPath(cid)
if err != nil {
@@ -1,4 +1,4 @@
package ipfsapi
package common
import (
"context"
@@ -1,4 +1,4 @@
package ipfsapi
package common
import (
"context"
@@ -9,7 +9,7 @@ import (
type Folder = files.Directory
func NewFolder(fs ...File) Folder {
return files.NewMapDirectory(convertFilesToMap(fs))
return files.NewMapDirectory(NewFileMap(fs))
}
func (c *client) AddFolder(folder Folder) (string, error) {
-20
View File
@@ -1,20 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type Account struct {
Id string `pkl:"id" json:"id,omitempty" query:"id"`
Name string `pkl:"name" json:"name,omitempty"`
Address any `pkl:"address" json:"address,omitempty"`
PublicKey string `pkl:"publicKey" json:"publicKey,omitempty"`
ChainCode uint `pkl:"chainCode" json:"chainCode,omitempty"`
Index int `pkl:"index" json:"index,omitempty"`
Controller string `pkl:"controller" json:"controller,omitempty"`
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty"`
}
-16
View File
@@ -1,16 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type Asset struct {
Id string `pkl:"id" json:"id,omitempty" query:"id"`
Name string `pkl:"name" json:"name,omitempty"`
Symbol string `pkl:"symbol" json:"symbol,omitempty"`
Decimals int `pkl:"decimals" json:"decimals,omitempty"`
ChainCode uint `pkl:"chainCode" json:"chainCode,omitempty"`
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty"`
}
-14
View File
@@ -1,14 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type Chain struct {
Id string `pkl:"id" json:"id,omitempty" query:"id"`
Name string `pkl:"name" json:"name,omitempty"`
NetworkId string `pkl:"networkId" json:"networkId,omitempty"`
ChainCode uint `pkl:"chainCode" json:"chainCode,omitempty"`
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty"`
}
-40
View File
@@ -1,40 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type Credential struct {
Id string `pkl:"id" json:"id,omitempty" query:"id"`
Subject string `pkl:"subject" json:"subject,omitempty"`
Controller string `pkl:"controller" json:"controller,omitempty"`
AttestationType string `pkl:"attestationType" json:"attestationType,omitempty"`
Origin string `pkl:"origin" json:"origin,omitempty"`
Label *string `pkl:"label" json:"label,omitempty"`
DeviceId *string `pkl:"deviceId" json:"deviceId,omitempty"`
CredentialId string `pkl:"credentialId" json:"credentialId,omitempty"`
PublicKey string `pkl:"publicKey" json:"publicKey,omitempty"`
Transport []string `pkl:"transport" json:"transport,omitempty"`
SignCount uint `pkl:"signCount" json:"signCount,omitempty"`
UserPresent bool `pkl:"userPresent" json:"userPresent,omitempty"`
UserVerified bool `pkl:"userVerified" json:"userVerified,omitempty"`
BackupEligible bool `pkl:"backupEligible" json:"backupEligible,omitempty"`
BackupState bool `pkl:"backupState" json:"backupState,omitempty"`
CloneWarning bool `pkl:"cloneWarning" json:"cloneWarning,omitempty"`
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty"`
UpdatedAt *string `pkl:"updatedAt" json:"updatedAt,omitempty"`
}
-28
View File
@@ -1,28 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
import (
"github.com/onsonr/sonr/pkg/common/models/keyalgorithm"
"github.com/onsonr/sonr/pkg/common/models/keycurve"
"github.com/onsonr/sonr/pkg/common/models/keyencoding"
"github.com/onsonr/sonr/pkg/common/models/keyrole"
"github.com/onsonr/sonr/pkg/common/models/keytype"
)
type DID struct {
Id string `pkl:"id" json:"id,omitempty" query:"id"`
Role keyrole.KeyRole `pkl:"role"`
Algorithm keyalgorithm.KeyAlgorithm `pkl:"algorithm"`
Encoding keyencoding.KeyEncoding `pkl:"encoding"`
Curve keycurve.KeyCurve `pkl:"curve"`
KeyType keytype.KeyType `pkl:"key_type"`
Raw string `pkl:"raw"`
Jwk *JWK `pkl:"jwk"`
}
-20
View File
@@ -1,20 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type Grant struct {
Id uint `pkl:"id" json:"id,omitempty" query:"id"`
Subject string `pkl:"subject" json:"subject,omitempty"`
Controller string `pkl:"controller" json:"controller,omitempty"`
Origin string `pkl:"origin" json:"origin,omitempty"`
Token string `pkl:"token" json:"token,omitempty"`
Scopes []string `pkl:"scopes" json:"scopes,omitempty"`
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty"`
UpdatedAt *string `pkl:"updatedAt" json:"updatedAt,omitempty"`
}
-16
View File
@@ -1,16 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type JWK struct {
Kty string `pkl:"kty" json:"kty,omitempty"`
Crv string `pkl:"crv" json:"crv,omitempty"`
X string `pkl:"x" json:"x,omitempty"`
Y string `pkl:"y" json:"y,omitempty"`
N string `pkl:"n" json:"n,omitempty"`
E string `pkl:"e" json:"e,omitempty"`
}
-14
View File
@@ -1,14 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type Keyshare struct {
Id string `pkl:"id" json:"id,omitempty" query:"id"`
Data string `pkl:"data" json:"data,omitempty"`
Role int `pkl:"role" json:"role,omitempty"`
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty"`
LastRefreshed *string `pkl:"lastRefreshed" json:"lastRefreshed,omitempty"`
}
-39
View File
@@ -1,39 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
import (
"context"
"github.com/apple/pkl-go/pkl"
)
type Models struct {
DbName string `pkl:"db_name"`
DbVersion int `pkl:"db_version"`
}
// LoadFromPath loads the pkl module at the given path and evaluates it into a Models
func LoadFromPath(ctx context.Context, path string) (ret *Models, err error) {
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
if err != nil {
return nil, err
}
defer func() {
cerr := evaluator.Close()
if err == nil {
err = cerr
}
}()
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
return ret, err
}
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a Models
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (*Models, error) {
var ret Models
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
return nil, err
}
return &ret, nil
}
-20
View File
@@ -1,20 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
type Profile struct {
Id string `pkl:"id" json:"id,omitempty" query:"id"`
Subject string `pkl:"subject" json:"subject,omitempty"`
Controller string `pkl:"controller" json:"controller,omitempty"`
OriginUri *string `pkl:"originUri" json:"originUri,omitempty"`
PublicMetadata *string `pkl:"publicMetadata" json:"publicMetadata,omitempty"`
PrivateMetadata *string `pkl:"privateMetadata" json:"privateMetadata,omitempty"`
CreatedAt *string `pkl:"createdAt" json:"createdAt,omitempty"`
UpdatedAt *string `pkl:"updatedAt" json:"updatedAt,omitempty"`
}
@@ -1,46 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package assettype
import (
"encoding"
"fmt"
)
type AssetType string
const (
Native AssetType = "native"
Wrapped AssetType = "wrapped"
Staking AssetType = "staking"
Pool AssetType = "pool"
Ibc AssetType = "ibc"
Cw20 AssetType = "cw20"
)
// String returns the string representation of AssetType
func (rcv AssetType) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(AssetType)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for AssetType.
func (rcv *AssetType) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "native":
*rcv = Native
case "wrapped":
*rcv = Wrapped
case "staking":
*rcv = Staking
case "pool":
*rcv = Pool
case "ibc":
*rcv = Ibc
case "cw20":
*rcv = Cw20
default:
return fmt.Errorf(`illegal: "%s" is not a valid AssetType`, str)
}
return nil
}
@@ -1,52 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package didmethod
import (
"encoding"
"fmt"
)
type DIDMethod string
const (
Ipfs DIDMethod = "ipfs"
Sonr DIDMethod = "sonr"
Bitcoin DIDMethod = "bitcoin"
Ethereum DIDMethod = "ethereum"
Ibc DIDMethod = "ibc"
Webauthn DIDMethod = "webauthn"
Dwn DIDMethod = "dwn"
Service DIDMethod = "service"
)
// String returns the string representation of DIDMethod
func (rcv DIDMethod) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(DIDMethod)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for DIDMethod.
func (rcv *DIDMethod) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "ipfs":
*rcv = Ipfs
case "sonr":
*rcv = Sonr
case "bitcoin":
*rcv = Bitcoin
case "ethereum":
*rcv = Ethereum
case "ibc":
*rcv = Ibc
case "webauthn":
*rcv = Webauthn
case "dwn":
*rcv = Dwn
case "service":
*rcv = Service
default:
return fmt.Errorf(`illegal: "%s" is not a valid DIDMethod`, str)
}
return nil
}
-17
View File
@@ -1,17 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package models
import "github.com/apple/pkl-go/pkl"
func init() {
pkl.RegisterMapping("sonr.orm.Models", Models{})
pkl.RegisterMapping("sonr.orm.Models#Account", Account{})
pkl.RegisterMapping("sonr.orm.Models#Asset", Asset{})
pkl.RegisterMapping("sonr.orm.Models#Chain", Chain{})
pkl.RegisterMapping("sonr.orm.Models#Credential", Credential{})
pkl.RegisterMapping("sonr.orm.Models#DID", DID{})
pkl.RegisterMapping("sonr.orm.Models#JWK", JWK{})
pkl.RegisterMapping("sonr.orm.Models#Grant", Grant{})
pkl.RegisterMapping("sonr.orm.Models#Keyshare", Keyshare{})
pkl.RegisterMapping("sonr.orm.Models#Profile", Profile{})
}
@@ -1,46 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package keyalgorithm
import (
"encoding"
"fmt"
)
type KeyAlgorithm string
const (
Es256 KeyAlgorithm = "es256"
Es384 KeyAlgorithm = "es384"
Es512 KeyAlgorithm = "es512"
Eddsa KeyAlgorithm = "eddsa"
Es256k KeyAlgorithm = "es256k"
Ecdsa KeyAlgorithm = "ecdsa"
)
// String returns the string representation of KeyAlgorithm
func (rcv KeyAlgorithm) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(KeyAlgorithm)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for KeyAlgorithm.
func (rcv *KeyAlgorithm) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "es256":
*rcv = Es256
case "es384":
*rcv = Es384
case "es512":
*rcv = Es512
case "eddsa":
*rcv = Eddsa
case "es256k":
*rcv = Es256k
case "ecdsa":
*rcv = Ecdsa
default:
return fmt.Errorf(`illegal: "%s" is not a valid KeyAlgorithm`, str)
}
return nil
}
@@ -1,58 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package keycurve
import (
"encoding"
"fmt"
)
type KeyCurve string
const (
P256 KeyCurve = "p256"
P384 KeyCurve = "p384"
P521 KeyCurve = "p521"
X25519 KeyCurve = "x25519"
X448 KeyCurve = "x448"
Ed25519 KeyCurve = "ed25519"
Ed448 KeyCurve = "ed448"
Secp256k1 KeyCurve = "secp256k1"
Bls12381 KeyCurve = "bls12381"
Keccak256 KeyCurve = "keccak256"
)
// String returns the string representation of KeyCurve
func (rcv KeyCurve) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(KeyCurve)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for KeyCurve.
func (rcv *KeyCurve) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "p256":
*rcv = P256
case "p384":
*rcv = P384
case "p521":
*rcv = P521
case "x25519":
*rcv = X25519
case "x448":
*rcv = X448
case "ed25519":
*rcv = Ed25519
case "ed448":
*rcv = Ed448
case "secp256k1":
*rcv = Secp256k1
case "bls12381":
*rcv = Bls12381
case "keccak256":
*rcv = Keccak256
default:
return fmt.Errorf(`illegal: "%s" is not a valid KeyCurve`, str)
}
return nil
}
@@ -1,37 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package keyencoding
import (
"encoding"
"fmt"
)
type KeyEncoding string
const (
Raw KeyEncoding = "raw"
Hex KeyEncoding = "hex"
Multibase KeyEncoding = "multibase"
)
// String returns the string representation of KeyEncoding
func (rcv KeyEncoding) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(KeyEncoding)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for KeyEncoding.
func (rcv *KeyEncoding) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "raw":
*rcv = Raw
case "hex":
*rcv = Hex
case "multibase":
*rcv = Multibase
default:
return fmt.Errorf(`illegal: "%s" is not a valid KeyEncoding`, str)
}
return nil
}
-40
View File
@@ -1,40 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package keyrole
import (
"encoding"
"fmt"
)
type KeyRole string
const (
Authentication KeyRole = "authentication"
Assertion KeyRole = "assertion"
Delegation KeyRole = "delegation"
Invocation KeyRole = "invocation"
)
// String returns the string representation of KeyRole
func (rcv KeyRole) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(KeyRole)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for KeyRole.
func (rcv *KeyRole) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "authentication":
*rcv = Authentication
case "assertion":
*rcv = Assertion
case "delegation":
*rcv = Delegation
case "invocation":
*rcv = Invocation
default:
return fmt.Errorf(`illegal: "%s" is not a valid KeyRole`, str)
}
return nil
}
@@ -1,34 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package keysharerole
import (
"encoding"
"fmt"
)
type KeyShareRole string
const (
User KeyShareRole = "user"
Validator KeyShareRole = "validator"
)
// String returns the string representation of KeyShareRole
func (rcv KeyShareRole) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(KeyShareRole)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for KeyShareRole.
func (rcv *KeyShareRole) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "user":
*rcv = User
case "validator":
*rcv = Validator
default:
return fmt.Errorf(`illegal: "%s" is not a valid KeyShareRole`, str)
}
return nil
}
-55
View File
@@ -1,55 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package keytype
import (
"encoding"
"fmt"
)
type KeyType string
const (
Octet KeyType = "octet"
Elliptic KeyType = "elliptic"
Rsa KeyType = "rsa"
Symmetric KeyType = "symmetric"
Hmac KeyType = "hmac"
Mpc KeyType = "mpc"
Zk KeyType = "zk"
Webauthn KeyType = "webauthn"
Bip32 KeyType = "bip32"
)
// String returns the string representation of KeyType
func (rcv KeyType) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(KeyType)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for KeyType.
func (rcv *KeyType) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "octet":
*rcv = Octet
case "elliptic":
*rcv = Elliptic
case "rsa":
*rcv = Rsa
case "symmetric":
*rcv = Symmetric
case "hmac":
*rcv = Hmac
case "mpc":
*rcv = Mpc
case "zk":
*rcv = Zk
case "webauthn":
*rcv = Webauthn
case "bip32":
*rcv = Bip32
default:
return fmt.Errorf(`illegal: "%s" is not a valid KeyType`, str)
}
return nil
}
@@ -1,46 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package permissiongrant
import (
"encoding"
"fmt"
)
type PermissionGrant string
const (
None PermissionGrant = "none"
Read PermissionGrant = "read"
Write PermissionGrant = "write"
Verify PermissionGrant = "verify"
Broadcast PermissionGrant = "broadcast"
Admin PermissionGrant = "admin"
)
// String returns the string representation of PermissionGrant
func (rcv PermissionGrant) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(PermissionGrant)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for PermissionGrant.
func (rcv *PermissionGrant) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "none":
*rcv = None
case "read":
*rcv = Read
case "write":
*rcv = Write
case "verify":
*rcv = Verify
case "broadcast":
*rcv = Broadcast
case "admin":
*rcv = Admin
default:
return fmt.Errorf(`illegal: "%s" is not a valid PermissionGrant`, str)
}
return nil
}
@@ -1,49 +0,0 @@
// Code generated from Pkl module `sonr.orm.Models`. DO NOT EDIT.
package permissionscope
import (
"encoding"
"fmt"
)
type PermissionScope string
const (
Profile PermissionScope = "profile"
Metadata PermissionScope = "metadata"
Permissions PermissionScope = "permissions"
Wallets PermissionScope = "wallets"
Transactions PermissionScope = "transactions"
User PermissionScope = "user"
Validator PermissionScope = "validator"
)
// String returns the string representation of PermissionScope
func (rcv PermissionScope) String() string {
return string(rcv)
}
var _ encoding.BinaryUnmarshaler = new(PermissionScope)
// UnmarshalBinary implements encoding.BinaryUnmarshaler for PermissionScope.
func (rcv *PermissionScope) UnmarshalBinary(data []byte) error {
switch str := string(data); str {
case "profile":
*rcv = Profile
case "metadata":
*rcv = Metadata
case "permissions":
*rcv = Permissions
case "wallets":
*rcv = Wallets
case "transactions":
*rcv = Transactions
case "user":
*rcv = User
case "validator":
*rcv = Validator
default:
return fmt.Errorf(`illegal: "%s" is not a valid PermissionScope`, str)
}
return nil
}
-18
View File
@@ -1,18 +0,0 @@
package response
import (
"net/http"
"github.com/labstack/echo/v4"
)
func RedirectOnError(target string) echo.HTTPErrorHandler {
return func(err error, c echo.Context) {
if he, ok := err.(*echo.HTTPError); ok {
// Log the error if needed
c.Logger().Errorf("Error: %v", he.Message)
}
// Redirect to main site
c.Redirect(http.StatusFound, target)
}
}
-19
View File
@@ -1,19 +0,0 @@
package response
import (
"net/http"
"github.com/labstack/echo/v4"
)
func RedirectLanding(c echo.Context) error {
return c.Redirect(http.StatusFound, "http://localhost:3000")
}
func RedirectIPFS(c echo.Context, cid string) error {
return c.Redirect(http.StatusFound, cid)
}
func RedirectAuth(c echo.Context) error {
return c.Redirect(http.StatusFound, "http://auth.localhost:3000")
}
-67
View File
@@ -1,67 +0,0 @@
package response
import (
"bytes"
"context"
"github.com/a-h/templ"
"github.com/labstack/echo/v4"
)
// Templ renders a component to the response
func Templ(cmp templ.Component) echo.HandlerFunc {
return func(c echo.Context) error {
// Create a buffer to store the rendered HTML
buf := &bytes.Buffer{}
// Render the component to the buffer
err := cmp.Render(c.Request().Context(), buf)
if err != nil {
return err
}
// Set the content type
c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML)
// Write the buffered content to the response
_, err = c.Response().Write(buf.Bytes())
if err != nil {
return err
}
c.Response().WriteHeader(200)
return nil
}
}
// TemplEcho renders a component to the response
func TemplEcho(c echo.Context, cmp templ.Component) error {
// Create a buffer to store the rendered HTML
buf := &bytes.Buffer{}
// Render the component to the buffer
err := cmp.Render(c.Request().Context(), buf)
if err != nil {
return err
}
// Set the content type
c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML)
// Write the buffered content to the response
_, err = c.Response().Write(buf.Bytes())
if err != nil {
return err
}
c.Response().WriteHeader(200)
return nil
}
// / TemplRawBytes renders a component to a byte slice
func TemplRawBytes(cmp templ.Component) ([]byte, error) {
// Create a buffer to store the rendered HTML
w := bytes.NewBuffer(nil)
err := cmp.Render(context.Background(), w)
if err != nil {
return nil, err
}
dat := w.Bytes()
return dat, nil
}
@@ -1,4 +1,4 @@
package ipfsapi
package common
import (
"context"
@@ -22,12 +22,12 @@ type IPFSTokenStore interface {
// for CID strings to be used as keys for retrieving tokens.
type ipfsUCANStore struct {
sync.Mutex
ipfs Client
ipfs IPFS
cache map[string]string
}
// NewUCANStore creates a new IPFS-backed token store
func NewUCANStore(ipfsClient Client) IPFSTokenStore {
func NewUCANStore(ipfsClient IPFS) IPFSTokenStore {
return &ipfsUCANStore{
ipfs: ipfsClient,
cache: make(map[string]string),
-211
View File
@@ -1,211 +0,0 @@
//go:build js && wasm
// +build js,wasm
package wasm
import (
"bytes"
"fmt"
"io"
"net/http"
"net/http/httptest"
"strings"
"sync"
"syscall/js"
)
var (
// Global buffer pool to reduce allocations
bufferPool = sync.Pool{
New: func() interface{} {
return new(bytes.Buffer)
},
}
// Cached JS globals
jsGlobal = js.Global()
jsUint8Array = jsGlobal.Get("Uint8Array")
jsResponse = jsGlobal.Get("Response")
jsPromise = jsGlobal.Get("Promise")
jsWasmHTTP = jsGlobal.Get("wasmhttp")
)
// ServeFetch serves HTTP requests with optimized handler management
func ServeFetch(handler http.Handler) func() {
h := handler
if h == nil {
h = http.DefaultServeMux
}
// Optimize prefix handling
prefix := strings.TrimRight(jsWasmHTTP.Get("path").String(), "/")
if prefix != "" {
mux := http.NewServeMux()
mux.Handle(prefix+"/", http.StripPrefix(prefix, h))
h = mux
}
// Create request handler function
cb := js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
promise, resolve, reject := newPromiseOptimized()
go handleRequest(h, args[1], resolve, reject)
return promise
})
jsWasmHTTP.Call("setHandler", cb)
return cb.Release
}
// handleRequest processes the request with panic recovery
func handleRequest(h http.Handler, jsReq js.Value, resolve, reject func(interface{})) {
defer func() {
if r := recover(); r != nil {
var errMsg string
if err, ok := r.(error); ok {
errMsg = fmt.Sprintf("wasmhttp: panic: %+v", err)
} else {
errMsg = fmt.Sprintf("wasmhttp: panic: %v", r)
}
reject(errMsg)
}
}()
recorder := newResponseRecorder()
h.ServeHTTP(recorder, buildRequest(jsReq))
resolve(recorder.jsResponse())
}
// buildRequest creates an http.Request from JS Request
func buildRequest(jsReq js.Value) *http.Request {
// Get request body
arrayBuffer, err := awaitPromiseOptimized(jsReq.Call("arrayBuffer"))
if err != nil {
panic(err)
}
// Create body buffer
jsBody := jsUint8Array.New(arrayBuffer)
bodyLen := jsBody.Get("length").Int()
body := make([]byte, bodyLen)
js.CopyBytesToGo(body, jsBody)
// Create request
req := httptest.NewRequest(
jsReq.Get("method").String(),
jsReq.Get("url").String(),
bytes.NewReader(body),
)
// Set headers efficiently
headers := jsReq.Get("headers")
headersIt := headers.Call("entries")
for {
entry := headersIt.Call("next")
if entry.Get("done").Bool() {
break
}
pair := entry.Get("value")
req.Header.Set(pair.Index(0).String(), pair.Index(1).String())
}
return req
}
// ResponseRecorder with optimized buffer handling
type ResponseRecorder struct {
*httptest.ResponseRecorder
buffer *bytes.Buffer
}
func newResponseRecorder() *ResponseRecorder {
return &ResponseRecorder{
ResponseRecorder: httptest.NewRecorder(),
buffer: bufferPool.Get().(*bytes.Buffer),
}
}
// jsResponse creates a JS Response with optimized memory usage
func (rr *ResponseRecorder) jsResponse() js.Value {
defer func() {
rr.buffer.Reset()
bufferPool.Put(rr.buffer)
}()
res := rr.Result()
defer res.Body.Close()
// Prepare response body
body := js.Undefined()
if res.ContentLength != 0 {
if _, err := io.Copy(rr.buffer, res.Body); err != nil {
panic(err)
}
bodyBytes := rr.buffer.Bytes()
body = jsUint8Array.New(len(bodyBytes))
js.CopyBytesToJS(body, bodyBytes)
}
// Prepare response init object
init := make(map[string]interface{}, 3)
if res.StatusCode != 0 {
init["status"] = res.StatusCode
}
if len(res.Header) > 0 {
headers := make(map[string]interface{}, len(res.Header))
for k, v := range res.Header {
if len(v) > 0 {
headers[k] = v[0]
}
}
init["headers"] = headers
}
return jsResponse.New(body, init)
}
// newPromiseOptimized creates a new JavaScript Promise with optimized callback handling
func newPromiseOptimized() (js.Value, func(interface{}), func(interface{})) {
var (
resolve func(interface{})
reject func(interface{})
promiseFunc = js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
resolve = func(v interface{}) { args[0].Invoke(v) }
reject = func(v interface{}) { args[1].Invoke(v) }
return js.Undefined()
})
)
defer promiseFunc.Release()
return jsPromise.New(promiseFunc), resolve, reject
}
// awaitPromiseOptimized waits for Promise resolution with optimized channel handling
func awaitPromiseOptimized(promise js.Value) (js.Value, error) {
done := make(chan struct{})
var (
result js.Value
err error
)
thenFunc := js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
result = args[0]
close(done)
return nil
})
defer thenFunc.Release()
catchFunc := js.FuncOf(func(_ js.Value, args []js.Value) interface{} {
err = js.Error{Value: args[0]}
close(done)
return nil
})
defer catchFunc.Release()
promise.Call("then", thenFunc).Call("catch", catchFunc)
<-done
return result, err
}
-34
View File
@@ -1,34 +0,0 @@
//go:build js && wasm
// +build js,wasm
package wasm
import (
"encoding/base64"
"encoding/json"
"github.com/labstack/echo/v4"
)
func ContextMiddleware(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// Extract WASM context from headers
if wasmCtx := c.Request().Header.Get("X-Wasm-Context"); wasmCtx != "" {
if ctx, err := DecodeWasmContext(wasmCtx); err == nil {
c.Set("wasm_context", ctx)
}
}
return next(c)
}
}
// decodeWasmContext decodes the WASM context from a base64 encoded string
func DecodeWasmContext(ctx string) (map[string]any, error) {
decoded, err := base64.StdEncoding.DecodeString(ctx)
if err != nil {
return nil, err
}
var ctxData map[string]any
err = json.Unmarshal(decoded, &ctxData)
return ctxData, err
}
-124
View File
@@ -1,124 +0,0 @@
package embed
import "encoding/json"
func newWebManifestBytes() ([]byte, error) {
return json.Marshal(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"`
}
-14
View File
@@ -1,14 +0,0 @@
package embed
import (
_ "embed"
)
//go:embed index.html
var IndexHTML []byte
//go:embed main.js
var MainJS []byte
//go:embed sw.js
var WorkerJS []byte
-46
View File
@@ -1,46 +0,0 @@
package config
import (
"context"
"github.com/apple/pkl-go/pkl"
hwayconfig "github.com/onsonr/sonr/pkg/config/hway"
)
// LoadFromBytes loads the environment from the given bytes
func LoadHwayFromBytes(data []byte) (hwayconfig.Hway, error) {
text := string(data)
return LoadHwayFromString(text)
}
// LoadFromString loads the environment from the given string
func LoadHwayFromString(text string) (hwayconfig.Hway, error) {
evaluator, err := pkl.NewEvaluator(context.Background(), pkl.PreconfiguredOptions)
if err != nil {
return nil, err
}
defer func() {
cerr := evaluator.Close()
if err == nil {
err = cerr
}
}()
ret, err := hwayconfig.Load(context.Background(), evaluator, pkl.TextSource(text))
return ret, err
}
// LoadFromURL loads the environment from the given URL
func LoadFromURL(url string) (hwayconfig.Hway, error) {
evaluator, err := pkl.NewEvaluator(context.Background(), pkl.PreconfiguredOptions)
if err != nil {
return nil, err
}
defer func() {
cerr := evaluator.Close()
if err == nil {
err = cerr
}
}()
ret, err := hwayconfig.Load(context.Background(), evaluator, pkl.UriSource(url))
return ret, err
}
-103
View File
@@ -1,103 +0,0 @@
// Code generated from Pkl module `sonr.net.Hway`. DO NOT EDIT.
package hway
import (
"context"
"github.com/apple/pkl-go/pkl"
)
type Hway interface {
GetServePort() int
GetSqliteFile() string
GetChainId() string
GetIpfsGatewayUrl() string
GetSonrApiUrl() string
GetSonrGrpcUrl() string
GetSonrRpcUrl() string
GetPsqlDSN() string
}
var _ Hway = (*HwayImpl)(nil)
type HwayImpl struct {
ServePort int `pkl:"servePort"`
SqliteFile string `pkl:"sqliteFile"`
ChainId string `pkl:"chainId"`
IpfsGatewayUrl string `pkl:"ipfsGatewayUrl"`
SonrApiUrl string `pkl:"sonrApiUrl"`
SonrGrpcUrl string `pkl:"sonrGrpcUrl"`
SonrRpcUrl string `pkl:"sonrRpcUrl"`
PsqlDSN string `pkl:"psqlDSN"`
}
func (rcv *HwayImpl) GetServePort() int {
return rcv.ServePort
}
func (rcv *HwayImpl) GetSqliteFile() string {
return rcv.SqliteFile
}
func (rcv *HwayImpl) GetChainId() string {
return rcv.ChainId
}
func (rcv *HwayImpl) GetIpfsGatewayUrl() string {
return rcv.IpfsGatewayUrl
}
func (rcv *HwayImpl) GetSonrApiUrl() string {
return rcv.SonrApiUrl
}
func (rcv *HwayImpl) GetSonrGrpcUrl() string {
return rcv.SonrGrpcUrl
}
func (rcv *HwayImpl) GetSonrRpcUrl() string {
return rcv.SonrRpcUrl
}
func (rcv *HwayImpl) GetPsqlDSN() string {
return rcv.PsqlDSN
}
// LoadFromPath loads the pkl module at the given path and evaluates it into a Hway
func LoadFromPath(ctx context.Context, path string) (ret Hway, err error) {
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
if err != nil {
return nil, err
}
defer func() {
cerr := evaluator.Close()
if err == nil {
err = cerr
}
}()
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
return ret, err
}
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a Hway
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (Hway, error) {
var ret HwayImpl
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
return nil, err
}
return &ret, nil
}
-8
View File
@@ -1,8 +0,0 @@
// Code generated from Pkl module `sonr.net.Hway`. DO NOT EDIT.
package hway
import "github.com/apple/pkl-go/pkl"
func init() {
pkl.RegisterMapping("sonr.net.Hway", HwayImpl{})
}
-18
View File
@@ -1,18 +0,0 @@
// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT.
package motr
type Config struct {
IpfsGatewayUrl string `pkl:"ipfsGatewayUrl" json:"ipfsGatewayUrl,omitempty"`
MotrToken string `pkl:"motrToken" json:"motrToken,omitempty"`
MotrAddress string `pkl:"motrAddress" json:"motrAddress,omitempty"`
SonrApiUrl string `pkl:"sonrApiUrl" json:"sonrApiUrl,omitempty"`
SonrRpcUrl string `pkl:"sonrRpcUrl" json:"sonrRpcUrl,omitempty"`
SonrChainId string `pkl:"sonrChainId" json:"sonrChainId,omitempty"`
VaultSchema *Schema `pkl:"vaultSchema" json:"vaultSchema,omitempty"`
}
-14
View File
@@ -1,14 +0,0 @@
// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT.
package motr
type Environment struct {
IsDevelopment bool `pkl:"isDevelopment" json:"isDevelopment,omitempty"`
CacheVersion string `pkl:"cacheVersion" json:"cacheVersion,omitempty"`
HttpserverPath string `pkl:"httpserverPath" json:"httpserverPath,omitempty"`
WasmExecPath string `pkl:"wasmExecPath" json:"wasmExecPath,omitempty"`
WasmPath string `pkl:"wasmPath" json:"wasmPath,omitempty"`
}
-36
View File
@@ -1,36 +0,0 @@
// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT.
package motr
import (
"context"
"github.com/apple/pkl-go/pkl"
)
type Motr struct {
}
// LoadFromPath loads the pkl module at the given path and evaluates it into a Motr
func LoadFromPath(ctx context.Context, path string) (ret *Motr, err error) {
evaluator, err := pkl.NewEvaluator(ctx, pkl.PreconfiguredOptions)
if err != nil {
return nil, err
}
defer func() {
cerr := evaluator.Close()
if err == nil {
err = cerr
}
}()
ret, err = Load(ctx, evaluator, pkl.FileSource(path))
return ret, err
}
// Load loads the pkl module at the given source and evaluates it with the given evaluator into a Motr
func Load(ctx context.Context, evaluator pkl.Evaluator, source *pkl.ModuleSource) (*Motr, error) {
var ret Motr
if err := evaluator.EvaluateModule(ctx, source, &ret); err != nil {
return nil, err
}
return &ret, nil
}
-22
View File
@@ -1,22 +0,0 @@
// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT.
package motr
type Schema struct {
Version int `pkl:"version"`
Account string `pkl:"account" json:"account,omitempty"`
Asset string `pkl:"asset" json:"asset,omitempty"`
Chain string `pkl:"chain" json:"chain,omitempty"`
Credential string `pkl:"credential" json:"credential,omitempty"`
Jwk string `pkl:"jwk" json:"jwk,omitempty"`
Grant string `pkl:"grant" json:"grant,omitempty"`
Keyshare string `pkl:"keyshare" json:"keyshare,omitempty"`
Profile string `pkl:"profile" json:"profile,omitempty"`
}
-11
View File
@@ -1,11 +0,0 @@
// Code generated from Pkl module `sonr.net.Motr`. DO NOT EDIT.
package motr
import "github.com/apple/pkl-go/pkl"
func init() {
pkl.RegisterMapping("sonr.net.Motr", Motr{})
pkl.RegisterMapping("sonr.net.Motr#Config", Config{})
pkl.RegisterMapping("sonr.net.Motr#Schema", Schema{})
pkl.RegisterMapping("sonr.net.Motr#Environment", Environment{})
}
-57
View File
@@ -1,57 +0,0 @@
package controller
import (
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/crypto/mpc/spec"
)
// ControllerConfig defines the configuration for UCAN middleware
type ControllerConfig struct {
// Skipper defines a function to skip middleware
Skipper func(c echo.Context) bool
// KeySource provides the source for validating UCANs
KeySource spec.KeyshareSource
// TokenLookup is a string in the form of "<source>:<name>" that is used
// to extract token from the request.
// Optional. Default value "header:Authorization".
// Possible values:
// - "header:<name>"
// - "query:<name>"
// - "param:<name>"
// - "cookie:<name>"
TokenLookup string
// AuthScheme to be used in the Authorization header.
// Optional. Default value "Bearer".
AuthScheme string
}
// DefaultControllerConfig is the default UCAN middleware config
var DefaultControllerConfig = ControllerConfig{
Skipper: nil,
TokenLookup: "header:Authorization",
AuthScheme: "Bearer",
}
type Option func(c *ControllerConfig)
func WithSkipper(skipper func(c echo.Context) bool) Option {
return func(c *ControllerConfig) {
c.Skipper = skipper
}
}
func WithAuthScheme(scheme string) Option {
return func(c *ControllerConfig) {
c.AuthScheme = scheme
}
}
// WithTokenLookup sets the token lookup strategy
func WithTokenLookup(lookup string) Option {
return func(c *ControllerConfig) {
c.TokenLookup = lookup
}
}
-122
View File
@@ -1,122 +0,0 @@
//go:build js && wasm
// +build js,wasm
package controller
import (
"fmt"
"strings"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/crypto/mpc/spec"
)
// Middleware returns middleware to validate Middleware tokens
func Middleware(source spec.KeyshareSource, opts ...Option) echo.MiddlewareFunc {
c := DefaultControllerConfig
for _, opt := range opts {
opt(&c)
}
c.KeySource = source
return initWithConfig(c)
}
// initWithConfig returns UCAN middleware with custom config
func initWithConfig(config ControllerConfig) echo.MiddlewareFunc {
// Defaults
if config.Skipper == nil {
config.Skipper = DefaultControllerConfig.Skipper
}
if config.TokenLookup == "" {
config.TokenLookup = DefaultControllerConfig.TokenLookup
}
if config.AuthScheme == "" {
config.AuthScheme = DefaultControllerConfig.AuthScheme
}
// Initialize
parts := strings.Split(config.TokenLookup, ":")
extractor := tokenFromHeader(parts[1], config.AuthScheme)
switch parts[0] {
case "query":
extractor = tokenFromQuery(parts[1])
case "param":
extractor = tokenFromParam(parts[1])
case "cookie":
extractor = tokenFromCookie(parts[1])
}
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
if config.Skipper != nil && config.Skipper(c) {
return next(c)
}
auth, err := extractor(c)
if err != nil {
return echo.NewHTTPError(401, err.Error())
}
parser := config.KeySource.UCANParser()
token, err := parser.ParseAndVerify(c.Request().Context(), auth)
if err != nil {
return echo.NewHTTPError(401, "invalid UCAN token")
}
// Store token in context
c.Set("ucan", token)
return next(c)
}
}
}
// tokenFromHeader extracts token from header
func tokenFromHeader(header string, authScheme string) func(echo.Context) (string, error) {
return func(c echo.Context) (string, error) {
auth := c.Request().Header.Get(header)
if auth == "" {
return "", fmt.Errorf("missing auth token")
}
if authScheme == "" {
return auth, nil
}
l := len(authScheme)
if len(auth) > l+1 && auth[:l] == authScheme {
return auth[l+1:], nil
}
return "", fmt.Errorf("invalid auth scheme")
}
}
// tokenFromQuery extracts token from query string
func tokenFromQuery(param string) func(echo.Context) (string, error) {
return func(c echo.Context) (string, error) {
token := c.QueryParam(param)
if token == "" {
return "", fmt.Errorf("missing auth token")
}
return token, nil
}
}
// tokenFromParam extracts token from url param
func tokenFromParam(param string) func(echo.Context) (string, error) {
return func(c echo.Context) (string, error) {
token := c.Param(param)
if token == "" {
return "", fmt.Errorf("missing auth token")
}
return token, nil
}
}
// tokenFromCookie extracts token from cookie
func tokenFromCookie(name string) func(echo.Context) (string, error) {
return func(c echo.Context) (string, error) {
cookie, err := c.Cookie(name)
if err != nil {
return "", fmt.Errorf("missing auth token")
}
return cookie.Value, nil
}
}
-2
View File
@@ -1,2 +0,0 @@
// Package didauth provides middleware and utilities for DID-based authentication
package didauth
-19
View File
@@ -1,19 +0,0 @@
package producer
import (
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/crypto/ucan"
"github.com/onsonr/sonr/pkg/ipfsapi"
)
type ProducerContext struct {
echo.Context
// TokenParser is the attentuations assigned to the producer service
TokenParser *ucan.TokenParser
// TokenStore is the token store used to store and retrieve tokens
TokenStore ipfsapi.IPFSTokenStore
// IPFSClient is the IPFS client used to resolve the UCAN
IPFSClient ipfsapi.Client
}
-37
View File
@@ -1,37 +0,0 @@
package producer
import (
"github.com/onsonr/sonr/crypto/mpc"
"github.com/onsonr/sonr/crypto/ucan"
"github.com/onsonr/sonr/pkg/ipfsapi"
"github.com/labstack/echo/v4"
)
// Middleware returns middleware to spawn controllers and validate UCAN tokens
func Middleware(ipc ipfsapi.Client, perms ucan.Permissions) echo.MiddlewareFunc {
// Setup token store and parser
store := ipfsapi.NewUCANStore(ipc)
parser := ucan.NewTokenParser(perms.GetConstructor(), store, store)
// Return middleware
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
ctx := ProducerContext{
Context: c,
IPFSClient: ipc,
TokenParser: parser,
TokenStore: store,
}
return next(ctx)
}
}
}
func NewKeyset(c echo.Context) (mpc.Enclave, error) {
ks, err := mpc.GenEnclave()
if err != nil {
return nil, err
}
return ks, nil
}
-35
View File
@@ -1,35 +0,0 @@
package resolver
import (
"net/http"
"github.com/labstack/echo/v4"
config "github.com/onsonr/sonr/pkg/config/hway"
"google.golang.org/grpc"
)
type ClientsContext struct {
echo.Context
addr string
}
func GetClientConn(c echo.Context) (*grpc.ClientConn, error) {
cc, ok := c.(*ClientsContext)
if !ok {
return nil, echo.NewHTTPError(http.StatusInternalServerError, "ClientsContext not found")
}
grpcConn, err := grpc.NewClient(cc.addr, grpc.WithInsecure())
if err != nil {
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Failed to dial gRPC")
}
return grpcConn, nil
}
func Middleware(env config.Hway) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
cc := &ClientsContext{Context: c, addr: env.GetSonrGrpcUrl()}
return next(cc)
}
}
}
-41
View File
@@ -1,41 +0,0 @@
package resolver
import (
bankv1beta1 "cosmossdk.io/api/cosmos/bank/v1beta1"
"github.com/labstack/echo/v4"
didv1 "github.com/onsonr/sonr/api/did/v1"
dwnv1 "github.com/onsonr/sonr/api/dwn/v1"
svcv1 "github.com/onsonr/sonr/api/svc/v1"
)
func BankQueryClient(c echo.Context) (bankv1beta1.QueryClient, error) {
conn, err := GetClientConn(c)
if err != nil {
return nil, err
}
return bankv1beta1.NewQueryClient(conn), nil
}
func DIDQueryClient(c echo.Context) (didv1.QueryClient, error) {
conn, err := GetClientConn(c)
if err != nil {
return nil, err
}
return didv1.NewQueryClient(conn), nil
}
func DWNQueryClient(c echo.Context) (dwnv1.QueryClient, error) {
conn, err := GetClientConn(c)
if err != nil {
return nil, err
}
return dwnv1.NewQueryClient(conn), nil
}
func SVCQueryClient(c echo.Context) (svcv1.QueryClient, error) {
conn, err := GetClientConn(c)
if err != nil {
return nil, err
}
return svcv1.NewQueryClient(conn), nil
}
+45
View File
@@ -0,0 +1,45 @@
// Package gateway provides the default routes for the Sonr hway.
package gateway
import (
"github.com/labstack/echo-contrib/echoprometheus"
"github.com/labstack/echo/v4"
echomiddleware "github.com/labstack/echo/v4/middleware"
config "github.com/onsonr/sonr/internal/config/hway"
"github.com/onsonr/sonr/internal/database"
"github.com/onsonr/sonr/pkg/common"
"github.com/onsonr/sonr/pkg/gateway/middleware"
"github.com/onsonr/sonr/pkg/gateway/routes"
)
type Gateway = *echo.Echo
// New returns a new Gateway instance
func New(env config.Hway, ipc common.IPFS) (Gateway, error) {
db, err := database.NewDB(env)
if err != nil {
return nil, err
}
e := echo.New()
// Override default behaviors
e.IPExtractor = echo.ExtractIPDirect()
e.HTTPErrorHandler = redirectOnError("http://localhost:3000")
// Built-in middleware
e.Use(echoprometheus.NewMiddleware("hway"))
e.Use(echomiddleware.Logger())
e.Use(echomiddleware.Recover())
e.Use(middleware.UseGateway(env, ipc, db))
routes.Register(e)
return e, nil
}
func redirectOnError(target string) echo.HTTPErrorHandler {
return func(err error, c echo.Context) {
if he, ok := err.(*echo.HTTPError); ok {
// Log the error if needed
c.Logger().Errorf("Error: %v", he.Message)
middleware.RenderError(c, he)
}
}
}
+33
View File
@@ -0,0 +1,33 @@
package handlers
import (
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/gateway/middleware"
"github.com/onsonr/sonr/internal/nebula/input"
)
// ValidateProfileHandle finds the chosen handle and verifies it is unique
func ValidateProfileHandle(c echo.Context) error {
handle := c.FormValue("handle")
//
// if ok {
// return middleware.Render(c, input.HandleError(handle))
// }
//
return middleware.Render(c, input.HandleSuccess(handle))
}
// ValidateProfileHandle finds the chosen handle and verifies it is unique
func ValidateIsHumanSum(c echo.Context) error {
// data := context.GetCreateProfileData(c)
// value := c.FormValue("is_human")
// intValue, err := strconv.Atoi(value)
// if err != nil {
// return middleware.Render(c, input.HumanSliderError(data.FirstNumber, data.LastNumber))
// }
// if intValue != data.Sum() {
// return middleware.Render(c, input.HumanSliderError(data.FirstNumber, data.LastNumber))
// }
return middleware.Render(c, input.HumanSliderSuccess())
}
+16
View File
@@ -0,0 +1,16 @@
package handlers
import (
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/gateway/middleware"
)
func RenderIndex(c echo.Context) error {
// Initialize the session
err := middleware.NewSession(c)
if err != nil {
return middleware.RenderError(c, err)
}
// Render the initial view
return middleware.RenderInitial(c)
}
+25
View File
@@ -0,0 +1,25 @@
package handlers
import (
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/gateway/middleware"
"github.com/onsonr/sonr/pkg/gateway/types"
"github.com/onsonr/sonr/pkg/gateway/views"
)
func RenderProfileCreate(c echo.Context) error {
// numF, numL := middleware.GetHumanVerificationNumbers(c)
params := types.CreateProfileParams{
FirstNumber: int(middleware.CurrentBlock(c)),
LastNumber: int(middleware.CurrentBlock(c)),
}
return middleware.Render(c, views.RegisterProfileView(params))
}
func RenderPasskeyCreate(c echo.Context) error {
return middleware.Render(c, views.RegisterPasskeyView(types.CreatePasskeyParams{}))
}
func RenderVaultLoading(c echo.Context) error {
return middleware.Render(c, views.LoadingView())
}
+29
View File
@@ -0,0 +1,29 @@
package handlers
import (
"encoding/json"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/gateway/types"
"github.com/onsonr/sonr/pkg/gateway/middleware"
)
// SubmitProfileHandle submits a profile handle
func SubmitProfileHandle(c echo.Context) error {
return nil
}
// SubmitPublicKeyCredential submits a public key credential
func SubmitPublicKeyCredential(c echo.Context) error {
credentialJSON := c.FormValue("credential")
cred := &types.CredentialDescriptor{}
// Unmarshal the credential JSON
if err := json.Unmarshal([]byte(credentialJSON), cred); err != nil {
return middleware.RenderError(c, err)
}
err := middleware.SubmitCredential(c, cred)
if err != nil {
return middleware.RenderError(c, err)
}
return nil
}
+44
View File
@@ -0,0 +1,44 @@
package middleware
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/internal/database/repository"
"github.com/onsonr/sonr/pkg/gateway/types"
)
func ListCredentials(c echo.Context, handle string) ([]*types.CredentialDescriptor, error) {
cc, ok := c.(*GatewayContext)
if !ok {
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Credentials Context not found")
}
creds, err := cc.dbq.GetCredentialsByHandle(bgCtx(), handle)
if err != nil {
return nil, err
}
return types.CredentialArrayToDescriptors(creds), nil
}
func SubmitCredential(c echo.Context, cred *types.CredentialDescriptor) error {
origin := GetOrigin(c)
handle := GetHandle(c)
md := cred.ToModel(handle, origin)
cc, ok := c.(*GatewayContext)
if !ok {
return echo.NewHTTPError(http.StatusInternalServerError, "Credentials Context not found")
}
_, err := cc.dbq.InsertCredential(bgCtx(), repository.InsertCredentialParams{
Handle: handle,
CredentialID: md.CredentialID,
Origin: origin,
Type: md.Type,
Transports: md.Transports,
})
if err != nil {
return err
}
return nil
}
+40
View File
@@ -0,0 +1,40 @@
package middleware
import (
"database/sql"
"github.com/labstack/echo/v4"
"github.com/medama-io/go-useragent"
"github.com/onsonr/sonr/crypto/mpc"
"github.com/onsonr/sonr/internal/config/hway"
"github.com/onsonr/sonr/internal/database/repository"
"github.com/onsonr/sonr/pkg/common"
)
type GatewayContext struct {
echo.Context
agent useragent.UserAgent
id string
dbq *repository.Queries
ipfsClient common.IPFS
tokenStore common.IPFSTokenStore
stagedEnclaves map[string]mpc.Enclave
grpcAddr string
}
func UseGateway(env hway.Hway, ipc common.IPFS, db *sql.DB) echo.MiddlewareFunc {
return func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
ua := useragent.NewParser()
ctx := &GatewayContext{
agent: ua.Parse(c.Request().UserAgent()),
Context: c,
dbq: repository.New(db),
ipfsClient: ipc,
grpcAddr: env.GetSonrGrpcUrl(),
tokenStore: common.NewUCANStore(ipc),
}
return next(ctx)
}
}
}
+100
View File
@@ -0,0 +1,100 @@
package middleware
import (
"net/http"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/internal/context"
"github.com/onsonr/sonr/internal/database/repository"
)
func CheckHandleUnique(c echo.Context, handle string) bool {
ctx, ok := c.(*GatewayContext)
if !ok {
return false
}
ok, err := ctx.dbq.CheckHandleExists(bgCtx(), handle)
if err != nil {
return false
}
if ok {
return false
}
context.WriteCookie(c, context.UserHandle, handle)
return true
}
func CreateProfile(c echo.Context) (*repository.Profile, error) {
ctx, ok := c.(*GatewayContext)
if !ok {
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Profile Context not found")
}
address := c.FormValue("address")
handle := c.FormValue("handle")
origin := c.FormValue("origin")
name := c.FormValue("name")
profile, err := ctx.dbq.InsertProfile(bgCtx(), repository.InsertProfileParams{
Address: address,
Handle: handle,
Origin: origin,
Name: name,
})
if err != nil {
return nil, err
}
// Update session with profile id
sid := GetSessionID(c)
_, err = ctx.dbq.UpdateSessionWithProfileID(bgCtx(), repository.UpdateSessionWithProfileIDParams{
ProfileID: profile.ID,
ID: sid,
})
if err != nil {
return nil, err
}
return &profile, nil
}
func UpdateProfile(c echo.Context) (*repository.Profile, error) {
ctx, ok := c.(*GatewayContext)
if !ok {
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Profile Context not found")
}
address := c.FormValue("address")
handle := c.FormValue("handle")
name := c.FormValue("name")
profile, err := ctx.dbq.UpdateProfile(bgCtx(), repository.UpdateProfileParams{
Address: address,
Handle: handle,
Name: name,
})
if err != nil {
return nil, err
}
return &profile, nil
}
func ReadProfile(c echo.Context) (*repository.Profile, error) {
ctx, ok := c.(*GatewayContext)
if !ok {
return nil, echo.NewHTTPError(http.StatusInternalServerError, "Profile Context not found")
}
handle := c.Param("handle")
profile, err := ctx.dbq.GetProfileByHandle(bgCtx(), handle)
if err != nil {
return nil, err
}
return &profile, nil
}
func DeleteProfile(c echo.Context) error {
ctx, ok := c.(*GatewayContext)
if !ok {
return echo.NewHTTPError(http.StatusInternalServerError, "Profile Context not found")
}
address := c.Param("address")
err := ctx.dbq.SoftDeleteProfile(bgCtx(), address)
if err != nil {
return err
}
return nil
}
+42
View File
@@ -0,0 +1,42 @@
package middleware
import (
"bytes"
"github.com/a-h/templ"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/gateway/views"
)
func Render(c echo.Context, cmp templ.Component) error {
// Create a buffer to store the rendered HTML
buf := &bytes.Buffer{}
// Render the component to the buffer
err := cmp.Render(c.Request().Context(), buf)
if err != nil {
return err
}
// Set the content type
c.Response().Header().Set(echo.HeaderContentType, echo.MIMETextHTML)
// Write the buffered content to the response
_, err = c.Response().Write(buf.Bytes())
if err != nil {
return err
}
c.Response().WriteHeader(200)
return nil
}
func RenderError(c echo.Context, err error) error {
return Render(c, views.ErrorView(err.Error()))
}
func RenderInitial(c echo.Context) error {
return Render(c, views.InitialView())
}
func RenderLoading(c echo.Context) error {
return Render(c, views.LoadingView())
}
+113
View File
@@ -0,0 +1,113 @@
package middleware
import (
"errors"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/common"
)
// CurrentBlock returns the current block
func CurrentBlock(c echo.Context) uint64 {
cc, ok := c.(*GatewayContext)
if !ok {
return 0
}
qc, err := common.NewNodeClient(cc.grpcAddr)
if err != nil {
return 0
}
resp, err := qc.Status(bgCtx(), &common.StatusRequest{})
if err != nil {
return 0
}
return resp.GetHeight()
}
// GetBankParams returns the bank params
func GetBankParams(c echo.Context) (*common.BankParamsResponse, error) {
cc, ok := c.(*GatewayContext)
if !ok {
return nil, errors.New("gateway context not found")
}
cl, err := common.NewBankClient(cc.grpcAddr)
if err != nil {
return nil, err
}
resp, err := cl.Params(bgCtx(), &common.BankParamsRequest{})
if err != nil {
return nil, err
}
return resp, nil
}
// GetDIDParams returns the DID params
func GetDIDParams(c echo.Context) (*common.DIDParamsResponse, error) {
cc, ok := c.(*GatewayContext)
if !ok {
return nil, errors.New("gateway context not found")
}
cl, err := common.NewDIDClient(cc.grpcAddr)
if err != nil {
return nil, err
}
resp, err := cl.Params(bgCtx(), &common.DIDParamsRequest{})
if err != nil {
return nil, err
}
return resp, nil
}
// GetDWNParams returns the DWN params
func GetDWNParams(c echo.Context) (*common.DWNParamsResponse, error) {
cc, ok := c.(*GatewayContext)
if !ok {
return nil, errors.New("gateway context not found")
}
cl, err := common.NewDWNClient(cc.grpcAddr)
if err != nil {
return nil, err
}
resp, err := cl.Params(bgCtx(), &common.DWNParamsRequest{})
if err != nil {
return nil, err
}
return resp, nil
}
// GetNodeStatus returns the node status
func GetNodeStatus(c echo.Context) (*common.StatusResponse, error) {
cc, ok := c.(*GatewayContext)
if !ok {
return nil, errors.New("gateway context not found")
}
cl, err := common.NewNodeClient(cc.grpcAddr)
if err != nil {
return nil, err
}
resp, err := cl.Status(bgCtx(), &common.StatusRequest{})
if err != nil {
return nil, err
}
return resp, nil
}
// GetSVCParams returns the SVC params
func GetSVCParams(c echo.Context) (*common.SVCParamsResponse, error) {
cc, ok := c.(*GatewayContext)
if !ok {
return nil, errors.New("gateway context not found")
}
cl, err := common.NewSVCClient(cc.grpcAddr)
if err != nil {
return nil, err
}
resp, err := cl.Params(bgCtx(), &common.SVCParamsRequest{})
if err != nil {
return nil, err
}
return resp, nil
}
+109
View File
@@ -0,0 +1,109 @@
package middleware
import (
gocontext "context"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/internal/context"
"github.com/onsonr/sonr/internal/database"
)
func NewSession(c echo.Context) error {
cc, ok := c.(*GatewayContext)
if !ok {
return nil
}
baseSessionCreateParams := database.BaseSessionCreateParams(cc)
cc.id = baseSessionCreateParams.ID
if _, err := cc.dbq.CreateSession(bgCtx(), baseSessionCreateParams); err != nil {
return err
}
// Set Cookie
if err := context.WriteCookie(c, context.SessionID, cc.id); err != nil {
return err
}
return nil
}
// ForbiddenDevice returns true if the device is unavailable
func ForbiddenDevice(c echo.Context) bool {
cc, ok := c.(*GatewayContext)
if !ok {
return true
}
return cc.agent.IsBot() || cc.agent.IsTV()
}
func GetOrigin(c echo.Context) string {
return c.Request().Host
}
func GetSessionID(c echo.Context) string {
// Check from context
cc, ok := c.(*GatewayContext)
if !ok {
return ""
}
// check from cookie
if cc.id == "" {
if ok := context.CookieExists(c, context.SessionID); !ok {
return ""
}
cc.id = context.ReadCookieUnsafe(c, context.SessionID)
}
return cc.id
}
func GetSessionChallenge(c echo.Context) string {
cc, ok := c.(*GatewayContext)
if !ok {
return ""
}
s, err := cc.dbq.GetChallengeBySessionID(bgCtx(), cc.id)
if err != nil {
return ""
}
return s
}
func GetHandle(c echo.Context) string {
// First check for the cookie
handle := context.ReadCookieUnsafe(c, context.UserHandle)
if handle != "" {
return handle
}
// Then check the session
cc, ok := c.(*GatewayContext)
if !ok {
return ""
}
s, err := cc.dbq.GetSessionByID(bgCtx(), cc.id)
if err != nil {
return ""
}
profile, err := cc.dbq.GetProfileByID(bgCtx(), s.ProfileID)
if err != nil {
return ""
}
return profile.Handle
}
//
// func GetHumanVerificationNumbers(c echo.Context) (int64, int64) {
// cc, ok := c.(*GatewayContext)
// if !ok {
// return 0, 0
// }
// s, err := cc.dbq.GetHumanVerificationNumbers(bgCtx(), cc.id)
// if err != nil {
// return 0, 0
// }
// return s.IsHumanFirst, s.IsHumanLast
// }
// utility function to get a context
func bgCtx() gocontext.Context {
ctx := gocontext.Background()
return ctx
}
+57
View File
@@ -0,0 +1,57 @@
package middleware
import (
"fmt"
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/crypto/mpc"
"github.com/onsonr/sonr/internal/context"
"github.com/onsonr/sonr/pkg/gateway/types"
"lukechampine.com/blake3"
)
func Spawn(c echo.Context) (types.CreatePasskeyParams, error) {
cc := c.(*GatewayContext)
block := fmt.Sprintf("%d", CurrentBlock(c))
handle := GetHandle(c)
origin := GetOrigin(c)
challenge := GetSessionChallenge(c)
sid := GetSessionID(c)
nonce, err := calcNonce(sid)
if err != nil {
return types.DefaultCreatePasskeyParams(), err
}
encl, err := mpc.GenEnclave(nonce)
if err != nil {
return types.DefaultCreatePasskeyParams(), err
}
cc.stagedEnclaves[sid] = encl
context.WriteCookie(c, context.SonrAddress, encl.Address())
return types.CreatePasskeyParams{
Address: encl.Address(),
Handle: handle,
Name: origin,
Challenge: challenge,
CreationBlock: block,
}, nil
}
func Claim() (types.CreatePasskeyParams, error) {
return types.CreatePasskeyParams{}, nil
}
// Uses blake3 to hash the sessionID to generate a nonce of length 12 bytes
func calcNonce(sessionID string) ([]byte, error) {
hash := blake3.New(32, nil)
_, err := hash.Write([]byte(sessionID))
if err != nil {
return nil, err
}
// Read the hash into a byte slice
nonce := make([]byte, 12)
_, err = hash.Write(nonce)
if err != nil {
return nil, err
}
return nonce, nil
}
+21
View File
@@ -0,0 +1,21 @@
package routes
import (
"github.com/labstack/echo/v4"
"github.com/onsonr/sonr/pkg/gateway/handlers"
)
func Register(e *echo.Echo) error {
// Register View Handlers
e.GET("/", handlers.RenderIndex)
e.GET("/register", handlers.RenderProfileCreate)
e.POST("/register/passkey", handlers.RenderPasskeyCreate)
e.POST("/register/finish", handlers.RenderVaultLoading)
// Register Validation Handlers
e.POST("/register/profile/handle", handlers.ValidateProfileHandle)
e.POST("/register/profile/is_human", handlers.ValidateIsHumanSum)
e.POST("/submit/profile/handle", handlers.SubmitProfileHandle)
e.POST("/submit/credential", handlers.SubmitPublicKeyCredential)
return nil
}
@@ -4,7 +4,8 @@ import (
"encoding/json"
"github.com/ipfs/boxo/files"
config "github.com/onsonr/sonr/pkg/config/motr"
config "github.com/onsonr/sonr/internal/config/motr"
"github.com/onsonr/sonr/internal/models"
)
const SchemaVersion = 1
@@ -18,7 +19,7 @@ const (
// spawnVaultDirectory creates a new directory with the default files
func NewVaultFS(cfg *config.Config) (files.Directory, error) {
manifestBz, err := newWebManifestBytes()
manifestBz, err := models.NewWebManifest()
if err != nil {
return nil, err
}
@@ -47,3 +48,17 @@ func NewVaultConfig(addr string, ucanCID string) *config.Config {
VaultSchema: DefaultSchema(),
}
}
// DefaultSchema returns the default schema
func DefaultSchema() *config.Schema {
return &config.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{}),
}
}
@@ -1,26 +1,19 @@
package embed
import (
_ "embed"
"reflect"
"strings"
"github.com/onsonr/sonr/pkg/common/models"
config "github.com/onsonr/sonr/pkg/config/motr"
)
// DefaultSchema returns the default schema
func DefaultSchema() *config.Schema {
return &config.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{}),
}
}
//go:embed index.html
var IndexHTML []byte
//go:embed main.js
var MainJS []byte
//go:embed sw.js
var WorkerJS []byte
func getSchema(structType interface{}) string {
t := reflect.TypeOf(structType)
+50
View File
@@ -0,0 +1,50 @@
package types
// ╭───────────────────────────────────────────────────────────╮
// │ Create Passkey (/register/passkey) │
// ╰───────────────────────────────────────────────────────────╯
// DefaultCreatePasskeyParams returns a default CreatePasskeyParams
func DefaultCreatePasskeyParams() CreatePasskeyParams {
return CreatePasskeyParams{
Address: "",
Handle: "",
Name: "",
Challenge: "",
CreationBlock: "",
}
}
// CreatePasskeyParams represents the parameters for creating a passkey
type CreatePasskeyParams struct {
Address string
Handle string
Name string
Challenge string
CreationBlock string
}
// ╭───────────────────────────────────────────────────────────╮
// │ Create Profile (/register/profile) │
// ╰───────────────────────────────────────────────────────────╯
// DefaultCreateProfileParams returns a default CreateProfileParams
func DefaultCreateProfileParams() CreateProfileParams {
return CreateProfileParams{
TurnstileSiteKey: "",
FirstNumber: 0,
LastNumber: 0,
}
}
// CreateProfileParams represents the parameters for creating a profile
type CreateProfileParams struct {
TurnstileSiteKey string
FirstNumber int
LastNumber int
}
// Sum returns the sum of the first and last number
func (d CreateProfileParams) Sum() int {
return d.FirstNumber + d.LastNumber
}
+43
View File
@@ -0,0 +1,43 @@
package types
import "github.com/onsonr/sonr/internal/database/repository"
// Define the credential structure matching our frontend data
type CredentialDescriptor struct {
ID string `json:"id"`
RawID string `json:"rawId"`
Type string `json:"type"`
AuthenticatorAttachment string `json:"authenticatorAttachment"`
Transports string `json:"transports"`
ClientExtensionResults map[string]string `json:"clientExtensionResults"`
Response struct {
AttestationObject string `json:"attestationObject"`
ClientDataJSON string `json:"clientDataJSON"`
} `json:"response"`
}
func (c *CredentialDescriptor) ToModel(handle, origin string) *repository.Credential {
return &repository.Credential{
Handle: handle,
Origin: origin,
CredentialID: c.ID,
Type: c.Type,
Transports: c.Transports,
AuthenticatorAttachment: c.AuthenticatorAttachment,
}
}
func CredentialArrayToDescriptors(credentials []repository.Credential) []*CredentialDescriptor {
var descriptors []*CredentialDescriptor
for _, cred := range credentials {
cd := &CredentialDescriptor{
ID: cred.CredentialID,
RawID: cred.CredentialID,
Type: cred.Type,
AuthenticatorAttachment: cred.AuthenticatorAttachment,
Transports: cred.Transports,
}
descriptors = append(descriptors, cd)
}
return descriptors
}
+19
View File
@@ -0,0 +1,19 @@
package views
import (
"github.com/onsonr/sonr/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/layout"
)
templ ErrorView(err string) {
@layout.View("Error | Sonr.ID") {
@layout.Container() {
@hero.TitleDesc("Uh oh!", "Something went wrong.")
<div class="pt-3 flex flex-col items-center justify-center h-full">
<p class="text-red-500">
{ err }
</p>
</div>
}
}
}
+98
View File
@@ -0,0 +1,98 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package views
//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/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/layout"
)
func ErrorView(err string) 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_Var3 := 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 = hero.TitleDesc("Uh oh!", "Something went wrong.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"pt-3 flex flex-col items-center justify-center h-full\"><p class=\"text-red-500\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var4 string
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(err)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `pkg/gateway/views/error.templ`, Line: 14, Col: 10}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</p></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.View("Error | 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
+31
View File
@@ -0,0 +1,31 @@
package views
import (
"github.com/onsonr/sonr/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/layout"
)
templ InitialView() {
@layout.View("Sonr.ID") {
@layout.Container() {
@hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.")
@hero.StartButton()
@hero.SocialButtonsRow()
}
}
}
templ ReturningView() {
@layout.View("Login | Sonr.ID") {
@layout.Container() {
@hero.TitleDesc("Welcome Back!", "Continue with your existing Sonr.ID.")
<div class="pt-3 flex flex-col items-center justify-center h-full">
<sl-button hx-target="#container" hx-get="/register" type="button">
<sl-icon slot="prefix" library="sonr" name="sonr"></sl-icon>
Log back in
<sl-icon slot="suffix" library="sonr" name="arrow-right"></sl-icon>
</sl-button>
</div>
}
}
}
+166
View File
@@ -0,0 +1,166 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package views
//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/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/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_Var3 := 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 = hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = hero.StartButton().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = hero.SocialButtonsRow().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.View("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_Var4 := templ.GetChildren(ctx)
if templ_7745c5c3_Var4 == nil {
templ_7745c5c3_Var4 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var5 := 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_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 = hero.TitleDesc("Welcome Back!", "Continue with your existing Sonr.ID.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" <div class=\"pt-3 flex flex-col items-center justify-center h-full\"><sl-button hx-target=\"#container\" hx-get=\"/register\" type=\"button\"><sl-icon slot=\"prefix\" library=\"sonr\" name=\"sonr\"></sl-icon> Log back in <sl-icon slot=\"suffix\" library=\"sonr\" name=\"arrow-right\"></sl-icon></sl-button></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.View("Login | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
}
var _ = templruntime.GeneratedTemplate
+14
View File
@@ -0,0 +1,14 @@
package views
import (
"github.com/onsonr/sonr/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/layout"
)
templ LoadingView() {
@layout.View("Loading... | Sonr.ID") {
@layout.Container() {
@hero.TitleDesc("Loading Vault", "This will be used to login to your vault.")
}
}
}
+81
View File
@@ -0,0 +1,81 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package views
//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/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/layout"
)
func LoadingView() 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_Var3 := 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 = hero.TitleDesc("Loading Vault", "This will be used to login to your vault.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.View("Loading... | 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
+56
View File
@@ -0,0 +1,56 @@
package views
import (
"github.com/onsonr/sonr/pkg/gateway/types"
"github.com/onsonr/sonr/internal/nebula/card"
"github.com/onsonr/sonr/internal/nebula/form"
"github.com/onsonr/sonr/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/input"
"github.com/onsonr/sonr/internal/nebula/layout"
)
templ RegisterProfileView(data types.CreateProfileParams) {
@layout.View("New Profile | Sonr.ID") {
@layout.Container() {
@hero.TitleDesc("Basic Info", "Tell us a little about yourself.")
@form.Root("/register/passkey", "create-profile") {
@form.Body() {
@form.Header() {
<div class="w-full py-2">
<sl-icon name="at-sign" library="sonr"></sl-icon>
<sl-avatar shape="circle" size="large" src="https://avatars.githubusercontent.com/u/101929?v=4"></sl-avatar>
</div>
}
@input.Handle()
@input.Name()
@input.HumanSlider(data.FirstNumber, data.LastNumber)
@form.Footer() {
@form.CancelButton()
@form.SubmitButton("Next")
}
}
}
}
}
}
templ RegisterPasskeyView(data types.CreatePasskeyParams) {
@layout.View("Register | Sonr.ID") {
@layout.Container() {
@hero.TitleDesc("Link a PassKey", "This will be used to login to your vault.")
@form.Root("/register/finish", "passkey-form") {
<input type="hidden" name="credential" id="credential-data" required/>
@form.Body() {
@form.Header() {
@card.SonrProfile(data.Address, data.Name, data.Handle, data.CreationBlock)
}
@input.CoinSelect()
@form.Footer() {
@input.Passkey(data.Address, data.Handle, data.Challenge)
@form.CancelButton()
}
}
}
}
}
}
+378
View File
@@ -0,0 +1,378 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package views
//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/internal/nebula/card"
"github.com/onsonr/sonr/internal/nebula/form"
"github.com/onsonr/sonr/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/input"
"github.com/onsonr/sonr/internal/nebula/layout"
"github.com/onsonr/sonr/pkg/gateway/types"
)
func RegisterProfileView(data types.CreateProfileParams) 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_Var3 := 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 = hero.TitleDesc("Basic Info", "Tell us a little about yourself.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
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_Var5 := 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_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=\"w-full py-2\"><sl-icon name=\"at-sign\" library=\"sonr\"></sl-icon> <sl-avatar shape=\"circle\" size=\"large\" src=\"https://avatars.githubusercontent.com/u/101929?v=4\"></sl-avatar></div>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Header().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = input.Handle().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = input.Name().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = input.HumanSlider(data.FirstNumber, data.LastNumber).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Var7 := 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 = form.CancelButton().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = form.SubmitButton("Next").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Footer().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Root("/register/passkey", "create-profile").Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.View("New Profile | 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 RegisterPasskeyView(data types.CreatePasskeyParams) 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_Var8 := templ.GetChildren(ctx)
if templ_7745c5c3_Var8 == nil {
templ_7745c5c3_Var8 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var9 := 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_Var10 := 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 = hero.TitleDesc("Link a PassKey", "This will be used to login to your vault.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Var11 := 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("<input type=\"hidden\" name=\"credential\" id=\"credential-data\" required>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Var12 := 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_Var13 := 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 = card.SonrProfile(data.Address, data.Name, data.Handle, data.CreationBlock).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Header().Render(templ.WithChildren(ctx, templ_7745c5c3_Var13), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = input.CoinSelect().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Var14 := 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 = input.Passkey(data.Address, data.Handle, data.Challenge).Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = form.CancelButton().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Footer().Render(templ.WithChildren(ctx, templ_7745c5c3_Var14), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var12), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = form.Root("/register/finish", "passkey-form").Render(templ.WithChildren(ctx, templ_7745c5c3_Var11), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var10), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.View("Register | Sonr.ID").Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
}
var _ = templruntime.GeneratedTemplate
-29
View File
@@ -1,29 +0,0 @@
package ipfsapi
import "github.com/ipfs/boxo/files"
type Client interface {
Add(data []byte) (string, error)
AddFile(file File) (string, error)
AddFolder(folder Folder) (string, error)
Get(cid string) ([]byte, error)
IsPublished(ipns string) (bool, error)
Exists(cid string) (bool, error)
Pin(cid string) error
Unpin(cid string) error
Publish(cid string, name string) (string, error)
Ls(cid string) ([]string, error)
}
type File interface {
files.File
Name() string
}
func convertFilesToMap(vs []File) map[string]files.Node {
m := make(map[string]files.Node)
for _, f := range vs {
m[f.Name()] = f
}
return m
}
+23
View File
@@ -0,0 +1,23 @@
package handlers
import (
"github.com/labstack/echo/v4"
)
func GrantAuthorization(e echo.Context) error {
// Implement authorization endpoint using passkey authentication
// Store session data in cache
return nil
}
func GetJWKS(e echo.Context) error {
// Implement token endpoint
// Use cached session data for validation
return nil
}
func GetToken(e echo.Context) error {
// Implement token endpoint
// Use cached session data for validation
return nil
}
+7
View File
@@ -0,0 +1,7 @@
package handlers
import "github.com/labstack/echo/v4"
func HandleConnect(c echo.Context) error {
return nil
}
+11
View File
@@ -0,0 +1,11 @@
package handlers
import (
"net/http"
"github.com/labstack/echo/v4"
)
func RenderIndex(c echo.Context) error {
return c.Render(http.StatusOK, "index.templ", nil)
}
+93
View File
@@ -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)
// }
+1
View File
@@ -0,0 +1 @@
package handlers
+1
View File
@@ -0,0 +1 @@
package handlers
+1
View File
@@ -0,0 +1 @@
package handlers
+15
View File
@@ -0,0 +1,15 @@
//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/internal/config/motr"
)
// RegisterRoutes registers the Decentralized Web Node API routes.
func RegisterRoutes(e *echo.Echo, config *motr.Config) {
}
+1
View File
@@ -0,0 +1 @@
package vault
+16
View File
@@ -0,0 +1,16 @@
package views
import (
"github.com/onsonr/sonr/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/layout"
)
templ InitialView() {
@layout.View("Sonr.ID") {
@layout.Container() {
@hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.")
@hero.StartButton()
@hero.SocialButtonsRow()
}
}
}
+97
View File
@@ -0,0 +1,97 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package views
//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/internal/nebula/hero"
"github.com/onsonr/sonr/internal/nebula/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_Var3 := 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 = hero.TitleDesc("Sonr.ID", "The decentralized identity layer for the web.").Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = hero.StartButton().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(" ")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = hero.SocialButtonsRow().Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = layout.View("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