mirror of
https://github.com/cf-sonr/motr.git
synced 2026-01-12 02:59:13 +00:00
Refactor/orm (#7)
* feat/refactor-motr * feat/refactor-motr * feat: introduce Cloudflare Workers gateway application * chore: migrate build system from Makefile to Taskfile for improved automation * feat: streamline task management with Taskfile consolidation * feat: consolidate build and install tasks for simplified workflows * <no value> * feat: enable publishing for core packages * feat/refactor-motr * feat: integrate updated crypto library for enhanced security * ci: Configure CI/CD to build and test WASM signer * refactor: streamline build process using npm scripts * fix: Correct template file paths for accurate error reporting * refactor: standardize templ file paths for improved maintainability * chore: remove package documentation * build: exclude documentation artifacts from version control * feat: serve static assets from cloudflare worker * feat: introduce Motr controller service * refactor: move UI components to separate ui module * refactor: move resolver middleware to top-level middleware directory * feat: introduce modular middleware architecture * refactor: improve separation of concerns by relocating endpoint definitions * build: simplify codebase by deleting unused info types * refactor: decouple middleware configurations * feat: integrate request middleware for enhanced processing * feat: implement register and login pages * feat: integrate WASM signer for enhanced security * refactor: move type definitions to models package * refactor: rename ipfs middleware to vault middleware * feat: Add Dockerfile for controller service * feat: Add Dockerfile for controller with multi-stage build * chore: Update Golang version to 1.24.2 in Dockerfile * feat: introduce Docker support for application deployment * feat: Implement WASM-based signing service * feat: migrate build system to Taskfile for improved automation * feat: enable docker-based development for controller and resolver * feat: Add docker-compose services for resolver and controller workers * refactor: streamline build and deployment processes with Devbox * chore: standardize development environment with Devbox * chore: standardize container entrypoint for improved consistency * feat: introduce docker-compose setup for local development * feat: remove initial placeholder code * refactor: restructure project modules for improved organization * feat: integrate motr UI library for enhanced components * chore: upgrade motr dependency to v0.0.3 * refactor: restructure project layout for improved modularity * refactor: consolidate data models and options into directory * feat: integrate sqlc for database interaction * feat: integrate D1 database for improved data management * refactor: improve naming consistency across project * feat: enhance context with HTTP header utilities * refactor: restructure project layout for improved maintainability * refactor: centralize rendering logic into middleware * chore: update motr dependency to v0.0.5 to address data consistency issues * feat: consolidate handler logic into root * refactor: relocate handlers and middleware to internal packages * chore: update dependency to v0.9.0 * refactor: Improve code structure and add comprehensive documentation for WebAssembly signer module * feat: implement WASM-based signing functionality * chore: remove build system configuration * feat: integrate D1 database for persistent data storage * feat: enable D1 database integration for Cloudflare Workers * feat: enhance task execution with docker-compose integration * refactor: centralize database queries and models * refactor: improve sqlc code generation and project structure * docs: Update README with Docker support and new project architecture * refactor: centralize Sonr configuration via middleware * chore: improve build task definitions in Taskfile * chore: remove docker deployment configuration * feat: upgrade crypto module to v0.11.0 * refactor: migrate to a configuration-driven architecture * refactor: inject database common queries into index handler * feat: streamline worker initialization * refactor: standardize package versioning process * build: prepare vault package for public release * feat: enable WASM-based vault signing with durable objects * feat: introduce Vault service for enhanced security * feat: upgrade crypto library to v0.12.1 for enhanced security features * build: update middleware build constraints * feat: introduce struct-based handlers for improved organization * feat: centralize database configuration * build: update database seeding to target remote instance * feat: enhance asset handling with shared coin type * feat: decouple build process from database initialization * refactor: move base UI components to a dedicated directory * refactor: improve component structure for enhanced maintainability * refactor: rename binding for clarity and consistency * feat: introduce development task and environment configurations * feat: introduce mprocs for simplified local development * <no value> * refactor: rename Vault DB to Controller DB for clarity * refactor: simplify configuration loading and database connections * feat: introduce MotrMode configuration to differentiate service roles * refactor: restructure base components and consolidate metadata handling * feat: introduce session context middleware for request handling * feat: enhance task management with database migration support * feat: Add database controller middleware and context retrieval methods * refactor: Improve session context handling and add full database controller middleware * feat: integrate Helia and Extism for Vault durable object * refactor: rename resolver to frontend * feat: streamline infrastructure and data management * refactor: improve task management and dependency loading * fix: remove legacy fetch handler from vault worker * feat: integrate WebAuthn for secure authentication * build: add hx-trigger for enhanced interaction * refactor: centralize session ID handling in middleware * refactor: simplify session context initialization * feat/split workers (#6) * refactor: rename claim route to register for clarity * refactor: rename demo view to dashboard view * feat: automate build and publish process * refactor: unify database queries and models for vault operations * feat: implement WASM compatible server and routing * feat: introduce controller-based routing * feat: implement passkey-based authentication * feat: implement Cloudflare cache middleware for improved performance * refactor: move ui components to ui package * feat: add handler functions for login and registration * refactor: centralize route registration logic * feat: implement user registration and login with passkey support * refactor: restructure view components for improved organization * feat: enable handle-based authentication and session management * refactor: improve config access and remove unused dependencies * refactor: restructure middleware and configuration for clarity * refactor: Remove external libraries * docs: update architecture to reflect removal of WASM build * refactor: centralize metadata and coin info types * refactor: move auth types to auth package * refactor: remove session management from vault service * refactor: reorganize UI components and middleware for clarity * refactor: move UI components to internal directory * feat: add session expiry configuration * refactor: streamline Taskfile and remove deprecated options * feat: introduce account entities and UI components * refactor: streamline asset representation with entity interfaces * feat: introduce asset pricing and market data * feat: enhance radar with session and cache middleware * fix: update dependencies and resolve peer dependency conflicts * feat: add blockchain entity and data model * feat: introduce entity-specific query interfaces * feat: Implement transaction creation, signing, and broadcasting methods * feat: implement durable object vault with RPC and IPFS support * refactor: align protobuf imports with updated cosm-orc package * feat: simplify auth components by removing options * feat: enhance data models for comprehensive crypto analysis * feat: implement account lookup by handle * refactor: simplify account card rendering * feat: enhance UI rendering with middleware * feat: remove helia file operations * build: scaffold navigation component with templ * feat: introduce UI layout components and dependency management * feat: remove unused assets for templated html * feat: implement authentication flow with WebAuthn and handle registration * feat: remove radar cmd * feat: enhance application architecture with module-based structure * refactor: relocate config and middleware to internal packages * feat: integrate session management into landing page * feat: improve landing page handler setup and session handling * feat: streamline initial setup and configuration process * chore: reorganize project layout for clarity and maintainability * chore: reorganize project structure by moving workers to 'cmd' * refactor/orm * feat: enhance task automation with root directory task * refactor: relocate chart components to dedicated directory
This commit is contained in:
5
.github/deploy/bootstrap.sh
vendored
5
.github/deploy/bootstrap.sh
vendored
@@ -1,5 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
|
||||
17
.github/deploy/devbox.json
vendored
17
.github/deploy/devbox.json
vendored
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"$schema": "https://raw.githubusercontent.com/jetify-com/devbox/0.13.7/.schema/devbox.schema.json",
|
||||
"packages": ["go@latest", "cargo@latest", "uv@latest", "bun@latest"],
|
||||
"env": {
|
||||
"PATH": "$HOME/.cargo/bin:$HOME/go/bin:$HOME/.local/bin:$HOME/.bun/bin:$PATH",
|
||||
"GITHUB_TOKEN": "$GITHUB_TOKEN",
|
||||
"GOPATH": "$HOME/go",
|
||||
"GOBIN": "$GOPATH/bin",
|
||||
"GHQ_ROOT": "$CLONEDIR"
|
||||
},
|
||||
"shell": {
|
||||
"init_hook": [],
|
||||
"scripts": {
|
||||
"test": ["echo \"Error: no test specified\" && exit 1"]
|
||||
}
|
||||
}
|
||||
}
|
||||
23
.github/deploy/process-compose.yaml
vendored
23
.github/deploy/process-compose.yaml
vendored
@@ -1,23 +0,0 @@
|
||||
version: "0.5"
|
||||
|
||||
processes:
|
||||
IPFS:
|
||||
namespace: testnet
|
||||
command: "ipfs daemon --mount"
|
||||
ready_log_line: "Daemon is ready"
|
||||
|
||||
Sonr:
|
||||
namespace: testnet
|
||||
command: "task sonrd:start"
|
||||
depends_on:
|
||||
IPFS:
|
||||
condition: process_log_ready
|
||||
|
||||
Hway:
|
||||
namespace: testnet
|
||||
command: "hway"
|
||||
depends_on:
|
||||
IPFS:
|
||||
condition: process_log_ready
|
||||
Sonr:
|
||||
condition: process_started
|
||||
14
.gitignore
vendored
14
.gitignore
vendored
@@ -1,10 +1,19 @@
|
||||
.DS_Store
|
||||
.tmp*
|
||||
go.work
|
||||
.aider*
|
||||
.vscode
|
||||
.idea
|
||||
bin
|
||||
tmp
|
||||
dist
|
||||
node_modules
|
||||
deploy/conf
|
||||
configs/logs.json
|
||||
go.work
|
||||
go.work.sum
|
||||
!.taskfile.yml
|
||||
!.taskfile.dist.yml
|
||||
|
||||
# Aider related generated files
|
||||
.aider-context
|
||||
@@ -99,19 +108,18 @@ cmd/gateway/node_modules
|
||||
pkg/nebula/node_modules
|
||||
configs/logs.json
|
||||
|
||||
mprocs.yaml
|
||||
|
||||
!devbox.lock
|
||||
!buf.lock
|
||||
|
||||
.air.toml
|
||||
mprocs.yaml
|
||||
mprocs.log
|
||||
tools-stamp
|
||||
deploy/conf
|
||||
*.aiderscript
|
||||
*.wasm
|
||||
|
||||
interchaintest-downloader
|
||||
.haptic
|
||||
|
||||
packages/vault/.parcel-cache
|
||||
packages/vault/.parcel-cache
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
# yaml-language-server: $schema=https://goreleaser.com/static/schema-pro.json
|
||||
version: 2
|
||||
project_name: motr
|
||||
builds:
|
||||
- id: motr
|
||||
binary: app
|
||||
goos:
|
||||
- js
|
||||
goarch:
|
||||
- wasm
|
||||
|
||||
release:
|
||||
github:
|
||||
owner: sonr-io
|
||||
name: motr
|
||||
name_template: "{{ .Tag }} | {{ .Env.RELEASE_DATE }}"
|
||||
draft: false
|
||||
replace_existing_draft: true
|
||||
replace_existing_artifacts: true
|
||||
extra_files:
|
||||
- glob: ./README*
|
||||
|
||||
announce:
|
||||
telegram:
|
||||
enabled: true
|
||||
chat_id: -1002222617755
|
||||
115
README.md
115
README.md
@@ -11,66 +11,95 @@ Motr is Sonr's decentralized vault and identity management system. It provides s
|
||||
- **Progressive Web App**: Works online and offline with service worker integration
|
||||
- **WASM Architecture**: Core functionality compiled to WebAssembly for cross-platform compatibility
|
||||
- **Local-First Design**: Data stored locally with sync capabilities to the Sonr blockchain
|
||||
- **Containerized Deployment**: Docker-based deployment for all components
|
||||
|
||||
## Installation
|
||||
|
||||
### Standard Installation
|
||||
|
||||
```bash
|
||||
git clone https://github.com/sonr-io/motr.git
|
||||
cd motr
|
||||
go mod tidy
|
||||
```
|
||||
|
||||
### Docker Installation
|
||||
|
||||
```bash
|
||||
git clone https://github.com/sonr-io/motr.git
|
||||
cd motr
|
||||
docker-compose up -d
|
||||
```
|
||||
|
||||
## Usage
|
||||
|
||||
### Run Using Docker
|
||||
|
||||
The simplest way to run the full Motr system is with Docker Compose:
|
||||
|
||||
```bash
|
||||
# Start all services
|
||||
docker-compose up -d
|
||||
|
||||
# View logs
|
||||
docker-compose logs -f
|
||||
|
||||
# Stop services
|
||||
docker-compose down
|
||||
```
|
||||
|
||||
### Run as a Local Server
|
||||
|
||||
```go
|
||||
package main
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"github.com/sonr-io/motr/app"
|
||||
"github.com/sonr-io/motr/pkg/models"
|
||||
"github.com/sonr-io/motr/pkg/types"
|
||||
"database/sql"
|
||||
"log"
|
||||
|
||||
"github.com/sonr-io/motr/app"
|
||||
"github.com/sonr-io/motr/pkg/models"
|
||||
"github.com/sonr-io/motr/pkg/types"
|
||||
)
|
||||
|
||||
func main() {
|
||||
dbq, err := setupDatabase()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
config := &types.Config{
|
||||
MotrToken: "your-token",
|
||||
SonrChainID: "sonr-testnet-1",
|
||||
// Other configuration options
|
||||
}
|
||||
|
||||
vault, err := app.New(config, dbq)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Start the server
|
||||
vault.Start(":8080")
|
||||
dbq, err := setupDatabase()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
config := &types.Config{
|
||||
MotrToken: "your-token",
|
||||
SonrChainID: "sonr-testnet-1",
|
||||
// Other configuration options
|
||||
}
|
||||
|
||||
vault, err := app.New(config, dbq)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
// Start the server
|
||||
vault.Start(":8080")
|
||||
}
|
||||
|
||||
func setupDatabase() (*models.Queries, error) {
|
||||
// Initialize your database connection
|
||||
// ...
|
||||
// Initialize your database connection
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
### Compile to WebAssembly
|
||||
|
||||
```sh
|
||||
# Build the vault application as WASM
|
||||
GOOS=js GOARCH=wasm go build -o public/app.wasm ./cmd/vault/main.go
|
||||
# Build the signer as WASM
|
||||
GOOS=js GOARCH=wasm go build -o build/signer.wasm ./cmd/signer/main.go
|
||||
|
||||
# Build the proxy application for Cloudflare Workers
|
||||
GOOS=js GOARCH=wasm go build -o workers/proxy.wasm ./cmd/proxy/main.go
|
||||
# Build the controller application as WASM
|
||||
GOOS=js GOARCH=wasm go build -o build/controller.wasm ./controller/main.go
|
||||
|
||||
# Build the resolver application for Cloudflare Workers
|
||||
GOOS=js GOARCH=wasm go build -o build/resolver.wasm ./resolver/main.go
|
||||
```
|
||||
|
||||
### Progressive Web App Integration
|
||||
@@ -86,18 +115,38 @@ Motr can be integrated into progressive web applications, providing:
|
||||
|
||||
Motr consists of several components:
|
||||
|
||||
- **Echo Server**: REST API for authentication and account management
|
||||
- **WASM Runtime**: Core logic compiled to WebAssembly
|
||||
- **Controller**: Manages WebAuthn credential creation and verification
|
||||
- **Resolver**: Handles name resolution and identity lookups
|
||||
- **Signer**: WebAssembly-based cryptographic operations for secure signing
|
||||
- **Service Worker**: Handles offline capabilities and request caching
|
||||
- **IndexedDB Storage**: Local data persistence
|
||||
- **Sonr Blockchain Integration**: Identity verification and data synchronization
|
||||
|
||||
### Component Details
|
||||
|
||||
1. **Controller**
|
||||
|
||||
- Manages user credentials and authentication
|
||||
- Integrates with WebAuthn for credential storage
|
||||
- Containerized for easy deployment
|
||||
|
||||
2. **Resolver**
|
||||
|
||||
- Resolves Sonr names to addresses and profiles
|
||||
- Serves as a gateway to the Sonr network
|
||||
- Implemented as a Cloudflare Worker
|
||||
|
||||
3. **Signer**
|
||||
- Secure cryptographic operations
|
||||
- WebAssembly-based for cross-platform compatibility
|
||||
- Handles key management and signatures
|
||||
|
||||
## Contributing
|
||||
|
||||
Contributions are welcome! Please feel free to submit a Pull Request.
|
||||
|
||||
## License
|
||||
|
||||
[MIT](LICENSE)
|
||||
[MIT](LICENSE)
|
||||
|
||||
Copyright (c) 2024, Sonr Labs, Inc.
|
||||
|
||||
156
Taskfile.yml
156
Taskfile.yml
@@ -1,66 +1,120 @@
|
||||
# yaml-language-server: $schema=https://json.schemastore.org/taskfile
|
||||
#yaml-language-server: $schema=https://json.schemastore.org/taskfile
|
||||
version: "3"
|
||||
silent: true
|
||||
|
||||
# vars:
|
||||
# VERSION:
|
||||
# sh: git describe --tags
|
||||
# COMMIT:
|
||||
# sh: git log -1 --format='%H'
|
||||
#
|
||||
vars:
|
||||
ROOT_DIR:
|
||||
sh: git rev-parse --show-toplevel
|
||||
|
||||
tasks:
|
||||
default:
|
||||
clean:
|
||||
desc: Remove build artifacts
|
||||
cmds:
|
||||
- task: gen:templ
|
||||
- task: gen:sqlc
|
||||
- task: build
|
||||
- task: tidy:vault
|
||||
- task: tidy:front
|
||||
- task: tidy:root
|
||||
|
||||
gen:templ:
|
||||
desc: Generate code
|
||||
sources:
|
||||
- "**/*.templ"
|
||||
generates:
|
||||
- "**/*_templ.go"
|
||||
deploy:
|
||||
desc: Deploy all
|
||||
cmds:
|
||||
- templ generate
|
||||
|
||||
gen:sqlc:
|
||||
desc: Generate code
|
||||
sources:
|
||||
- x/**/model/*.sql
|
||||
generates:
|
||||
- x/**/model/*.go
|
||||
cmds:
|
||||
- sqlc generate -f "x/identity/model/sqlc.yaml"
|
||||
- sqlc generate -f "x/portfolio/model/sqlc.yaml"
|
||||
- sqlc generate -f "x/user/model/sqlc.yaml"
|
||||
- task: deploy:vault
|
||||
- task: deploy:front
|
||||
|
||||
build:
|
||||
desc: Build
|
||||
watch: true
|
||||
desc: Build all
|
||||
cmds:
|
||||
- task: build:vault
|
||||
- task: build:front
|
||||
|
||||
start:vault:
|
||||
desc: Start the vault
|
||||
dir: "{{.ROOT_DIR}}/cmd/vault"
|
||||
cmd: bun run start
|
||||
|
||||
start:front:
|
||||
desc: Start the frontend
|
||||
dir: "{{.ROOT_DIR}}/cmd/front"
|
||||
cmd: bun run start
|
||||
|
||||
build:vault:
|
||||
desc: Build the vault
|
||||
dir: "{{.ROOT_DIR}}/cmd/vault"
|
||||
cmd: bun run build
|
||||
sources:
|
||||
- "**/*.go"
|
||||
- main.go
|
||||
generates:
|
||||
- web/app.wasm
|
||||
deps:
|
||||
- task: gen:templ
|
||||
- build/app.wasm
|
||||
|
||||
build:front:
|
||||
desc: Build the frontend
|
||||
dir: "{{.ROOT_DIR}}/cmd/front"
|
||||
cmd: bun run build
|
||||
sources:
|
||||
- main.go
|
||||
generates:
|
||||
- build/app.wasm
|
||||
|
||||
deploy:vault:
|
||||
desc: Deploy the vault
|
||||
dir: "{{.ROOT_DIR}}/cmd/vault"
|
||||
cmds:
|
||||
- bun run deploy
|
||||
|
||||
deploy:front:
|
||||
desc: Deploy the frontend
|
||||
dir: "{{.ROOT_DIR}}/cmd/front"
|
||||
cmd: bun run deploy
|
||||
|
||||
gen:templ:
|
||||
desc: Generate templ
|
||||
cmds:
|
||||
- templ generate
|
||||
- rm -rf .task
|
||||
|
||||
gen:sqlc:
|
||||
desc: Generate sqlc
|
||||
cmd: sqlc generate
|
||||
|
||||
db:migrate:
|
||||
desc: Migrate the database
|
||||
prompt:
|
||||
- Are you sure you want to run this command? This will delete all data in the database.
|
||||
cmds:
|
||||
- task: migrate:d1
|
||||
- task: gen:sqlc
|
||||
vars:
|
||||
TIME:
|
||||
sh: date
|
||||
cmds:
|
||||
- rm -rf web/vault.wasm
|
||||
- GOOS=js GOARCH=wasm go build -o web/vault.wasm .
|
||||
- gum log --time rfc822 --level info "[BUILD] WASM Complete"
|
||||
|
||||
serve:
|
||||
desc: Serve
|
||||
dir: web
|
||||
cmds:
|
||||
- bunx live-server
|
||||
migrate:d1:
|
||||
internal: true
|
||||
desc: Migrate the common database
|
||||
dir: "{{.ROOT_DIR}}/cmd/vault"
|
||||
cmd: npm run migrate
|
||||
sources:
|
||||
- schema.sql
|
||||
generates:
|
||||
- schema.sql
|
||||
|
||||
test:
|
||||
desc: Test
|
||||
|
||||
tidy:vault:
|
||||
desc: Go mod tidy the vault
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}/cmd/vault"
|
||||
cmds:
|
||||
- go test -v ./...
|
||||
- bun run clean
|
||||
- rm -rf ./build
|
||||
- rm -rf ./dist
|
||||
|
||||
tidy:front:
|
||||
desc: Go mod tidy the frontend
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}/cmd/front"
|
||||
cmds:
|
||||
- bun run clean
|
||||
- rm -rf ./build
|
||||
- rm -rf ./dist
|
||||
|
||||
tidy:root:
|
||||
desc: Go mod tidy the root
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
cmds:
|
||||
- go mod tidy
|
||||
- rm -rf .task
|
||||
|
||||
50
app/app.go
50
app/app.go
@@ -1,50 +0,0 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
|
||||
"github.com/labstack/echo/v4"
|
||||
)
|
||||
|
||||
// New returns a new App instance
|
||||
func New(opts ...Option) (*App, error) {
|
||||
o := baseOptions()
|
||||
for _, opt := range opts {
|
||||
opt(o)
|
||||
}
|
||||
e := o.applyDefaults()
|
||||
//
|
||||
// identity.RegisterRoutes(e, o.conn.Identity)
|
||||
// portfolio.RegisterRoutes(e, o.conn.Portfolio)
|
||||
// user.RegisterRoutes(e, o.conn.User)
|
||||
|
||||
return &App{
|
||||
Config: o.cfg,
|
||||
Database: o.conn,
|
||||
Echo: e,
|
||||
}, nil
|
||||
}
|
||||
|
||||
// handleIndex returns a simple JSON response
|
||||
func handleIndex(c echo.Context) error {
|
||||
params := make(map[string]string)
|
||||
if err := json.NewDecoder(c.Request().Body).Decode(¶ms); err != nil {
|
||||
return c.JSON(400, map[string]string{"message": err.Error()})
|
||||
}
|
||||
|
||||
c.Response().Header().Set("Content-Type", "application/json")
|
||||
return c.JSON(200, map[string]string{"message": "Hello, World!"})
|
||||
}
|
||||
|
||||
// handleError returns a simple JSON response
|
||||
func handleError() 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)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package app
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
echomiddleware "github.com/labstack/echo/v4/middleware"
|
||||
"github.com/onsonr/motr/pkg/config"
|
||||
)
|
||||
|
||||
type App struct {
|
||||
Config *config.MotrConfig
|
||||
Database *config.DBConnection
|
||||
Echo *echo.Echo
|
||||
}
|
||||
|
||||
type Options struct {
|
||||
conn *config.DBConnection
|
||||
cfg *config.MotrConfig
|
||||
mdws []echo.MiddlewareFunc
|
||||
}
|
||||
|
||||
func (o *Options) applyDefaults() *echo.Echo {
|
||||
e := echo.New()
|
||||
e.IPExtractor = echo.ExtractIPDirect()
|
||||
e.HTTPErrorHandler = handleError()
|
||||
for _, mdw := range o.mdws {
|
||||
e.Use(mdw)
|
||||
}
|
||||
e.POST("/", handleIndex)
|
||||
return e
|
||||
}
|
||||
|
||||
func baseOptions() *Options {
|
||||
return &Options{
|
||||
mdws: []echo.MiddlewareFunc{
|
||||
echomiddleware.Logger(),
|
||||
echomiddleware.Recover(),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
type Option func(*Options)
|
||||
|
||||
// WithConfig sets the configuration for the application
|
||||
func WithConfig(cfg *config.MotrConfig) func(*Options) {
|
||||
return func(o *Options) {
|
||||
o.cfg = cfg
|
||||
}
|
||||
}
|
||||
|
||||
// WithDatabase sets the database connection for the application
|
||||
func WithDatabase(conn *config.DBConnection) func(*Options) {
|
||||
return func(o *Options) {
|
||||
o.conn = conn
|
||||
}
|
||||
}
|
||||
|
||||
// WithMiddleware sets the middleware for the application
|
||||
func WithMiddleware(mdws ...echo.MiddlewareFunc) func(*Options) {
|
||||
return func(o *Options) {
|
||||
o.mdws = append(o.mdws, mdws...)
|
||||
}
|
||||
}
|
||||
5
cmd/front/.gitignore
vendored
Normal file
5
cmd/front/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
build
|
||||
node_modules
|
||||
.wrangler
|
||||
|
||||
.dev.vars*
|
||||
27
cmd/front/main.go
Normal file
27
cmd/front/main.go
Normal file
@@ -0,0 +1,27 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sonr-io/motr/handlers/auth"
|
||||
"github.com/sonr-io/motr/handlers/landing"
|
||||
"github.com/sonr-io/motr/internal/config"
|
||||
"github.com/sonr-io/motr/internal/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Setup config
|
||||
e, c := config.New()
|
||||
e.Use(middleware.UseSession(c), middleware.UseCloudflareCache(c))
|
||||
|
||||
// Register controllers
|
||||
if err := landing.Register(c, e); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
if err := auth.Register(c, e); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
// Start server
|
||||
e.Serve()
|
||||
}
|
||||
1540
cmd/front/package-lock.json
generated
Normal file
1540
cmd/front/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
16
cmd/front/package.json
Normal file
16
cmd/front/package.json
Normal file
@@ -0,0 +1,16 @@
|
||||
{
|
||||
"name": "@sonr-io/motr-front",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "npm run clean && npm run assets && npm run wasm",
|
||||
"assets": "go run github.com/syumai/workers/cmd/workers-assets-gen -mode=go",
|
||||
"wasm": "GOOS=js GOARCH=wasm go build -o ./build/app.wasm .",
|
||||
"deploy": "wrangler deploy",
|
||||
"start": "wrangler dev",
|
||||
"clean": "rm -rf ./build && rm -rf .wrangler && rm -rf ./dist && rm -rf ./node_modules && npm install"
|
||||
},
|
||||
"devDependencies": {
|
||||
"wrangler": "^4.10.0"
|
||||
}
|
||||
}
|
||||
47
cmd/front/wrangler.toml
Normal file
47
cmd/front/wrangler.toml
Normal file
@@ -0,0 +1,47 @@
|
||||
# Top-level configuration
|
||||
name = "motr-front"
|
||||
main = "build/worker.mjs"
|
||||
compatibility_date = "2025-04-14"
|
||||
|
||||
routes = [
|
||||
{ pattern = "sonr.id", custom_domain = true },
|
||||
]
|
||||
|
||||
[build]
|
||||
command = "npm run build"
|
||||
|
||||
[dev]
|
||||
port = 8787
|
||||
|
||||
[vars]
|
||||
SONR_CHAIN_ID = 'sonr-testnet-1'
|
||||
IPFS_GATEWAY = 'https://ipfs.sonr.land'
|
||||
SONR_API_URL = 'https://api.sonr.land'
|
||||
SONR_RPC_URL = 'https://rpc.sonr.land'
|
||||
SONR_GRPC_URL = 'https://grpc.sonr.id'
|
||||
MATRIX_SERVER = 'https://bm.chat'
|
||||
MOTR_GATEWAY = 'https://sonr.id'
|
||||
MOTR_VAULT = 'https://did.run'
|
||||
MOTR_MODE = 'resolver'
|
||||
|
||||
[observability]
|
||||
enabled = true
|
||||
logpush = true
|
||||
|
||||
[[r2_buckets]]
|
||||
binding = 'PROFILES'
|
||||
bucket_name = 'profiles'
|
||||
|
||||
[[d1_databases]]
|
||||
binding = "DB" # available in your Worker on env.DB
|
||||
database_name = "motr-db"
|
||||
database_id = "abc70ab3-32ce-4600-9b15-a452f92b7987"
|
||||
|
||||
[[kv_namespaces]]
|
||||
binding = "SESSIONS" # available in your Worker on env.KV
|
||||
id = "ea5de66fcfc14b5eba170395e29432ee"
|
||||
|
||||
[[kv_namespaces]]
|
||||
binding = "HANDLES" # available in your Worker on env.KV
|
||||
id = "271d47087a8842b2aac5ee79cf7bb203"
|
||||
|
||||
5
cmd/vault/.gitignore
vendored
Normal file
5
cmd/vault/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
||||
build
|
||||
node_modules
|
||||
.wrangler
|
||||
|
||||
.dev.vars*
|
||||
24
cmd/vault/main.go
Normal file
24
cmd/vault/main.go
Normal file
@@ -0,0 +1,24 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/sonr-io/motr/handlers/auth"
|
||||
"github.com/sonr-io/motr/internal/config"
|
||||
"github.com/sonr-io/motr/internal/middleware"
|
||||
)
|
||||
|
||||
func main() {
|
||||
// Setup config
|
||||
e, c := config.New()
|
||||
e.Use(middleware.UseSession(c), middleware.UseCloudflareCache(c))
|
||||
|
||||
// Register controllers
|
||||
if err := auth.Register(c, e); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
// Start server
|
||||
e.Serve()
|
||||
}
|
||||
6433
cmd/vault/package-lock.json
generated
Normal file
6433
cmd/vault/package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
27
cmd/vault/package.json
Normal file
27
cmd/vault/package.json
Normal file
@@ -0,0 +1,27 @@
|
||||
{
|
||||
"name": "@sonr-io/motr-vault",
|
||||
"version": "0.0.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "npm run clean && npm run assets && npm run wasm",
|
||||
"assets": "go run github.com/syumai/workers/cmd/workers-assets-gen -mode=go",
|
||||
"wasm": "GOOS=js GOARCH=wasm go build -o ./build/app.wasm .",
|
||||
"migrate": "npx wrangler d1 execute motr-db --remote --file=./schema.sql",
|
||||
"deploy": "npx wrangler deploy",
|
||||
"start": "npx wrangler dev",
|
||||
"clean": "rm -rf ./build && rm -rf .wrangler && rm -rf ./dist && rm -rf ./node_modules && npm install"
|
||||
},
|
||||
"dependencies": {
|
||||
"@extism/extism": "^2.0.0-rc11",
|
||||
"@helia/dag-cbor": "^1.0.1",
|
||||
"@helia/dag-json": "^1.0.1",
|
||||
"@helia/json": "^1.0.1",
|
||||
"@helia/strings": "^1.0.1",
|
||||
"@helia/unixfs": "^1.4.1",
|
||||
"helia": "^2.1.0",
|
||||
"sonr-cosmes": "^0.0.5"
|
||||
},
|
||||
"devDependencies": {
|
||||
"wrangler": "^4.10.0"
|
||||
}
|
||||
}
|
||||
1026
cmd/vault/query.sql
Normal file
1026
cmd/vault/query.sql
Normal file
File diff suppressed because it is too large
Load Diff
356
cmd/vault/schema.sql
Normal file
356
cmd/vault/schema.sql
Normal file
@@ -0,0 +1,356 @@
|
||||
-- Assets represent tokens and coins
|
||||
CREATE TABLE assets (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
name TEXT NOT NULL,
|
||||
symbol TEXT NOT NULL,
|
||||
decimals INTEGER NOT NULL CHECK(decimals >= 0),
|
||||
chain_id TEXT NOT NULL,
|
||||
channel TEXT NOT NULL,
|
||||
asset_type TEXT NOT NULL,
|
||||
coingecko_id TEXT,
|
||||
UNIQUE(chain_id, symbol)
|
||||
);
|
||||
|
||||
-- Credentials store WebAuthn credentials
|
||||
CREATE TABLE credentials (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
handle TEXT NOT NULL,
|
||||
credential_id TEXT NOT NULL UNIQUE,
|
||||
authenticator_attachment TEXT NOT NULL,
|
||||
origin TEXT NOT NULL,
|
||||
type TEXT NOT NULL,
|
||||
transports TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Accounts represent blockchain accounts
|
||||
CREATE TABLE accounts (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
number INTEGER NOT NULL,
|
||||
sequence INTEGER NOT NULL DEFAULT 0,
|
||||
address TEXT NOT NULL UNIQUE,
|
||||
public_key TEXT NOT NULL CHECK(json_valid(public_key)),
|
||||
chain_id TEXT NOT NULL,
|
||||
block_created INTEGER NOT NULL,
|
||||
controller TEXT NOT NULL,
|
||||
label TEXT NOT NULL,
|
||||
handle TEXT NOT NULL,
|
||||
is_subsidiary BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_subsidiary IN (0,1)),
|
||||
is_validator BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_validator IN (0,1)),
|
||||
is_delegator BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_delegator IN (0,1)),
|
||||
is_accountable BOOLEAN NOT NULL DEFAULT TRUE CHECK(is_accountable IN (0,1))
|
||||
);
|
||||
|
||||
-- Profiles represent user identities
|
||||
CREATE TABLE profiles (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
address TEXT NOT NULL,
|
||||
handle TEXT NOT NULL UNIQUE,
|
||||
origin TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
UNIQUE(address, origin)
|
||||
);
|
||||
|
||||
-- Vaults store encrypted data
|
||||
CREATE TABLE vaults (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
handle TEXT NOT NULL,
|
||||
origin TEXT NOT NULL,
|
||||
address TEXT NOT NULL,
|
||||
cid TEXT NOT NULL UNIQUE,
|
||||
config TEXT NOT NULL CHECK(json_valid(config)),
|
||||
session_id TEXT NOT NULL,
|
||||
redirect_uri TEXT NOT NULL
|
||||
);
|
||||
|
||||
-- Prices entity based on the Alternative.me API for crypto prices
|
||||
CREATE TABLE prices (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
asset_id TEXT NOT NULL,
|
||||
price_usd REAL,
|
||||
price_btc REAL,
|
||||
volume_24h_usd REAL,
|
||||
market_cap_usd REAL,
|
||||
available_supply REAL,
|
||||
total_supply REAL,
|
||||
max_supply REAL,
|
||||
percent_change_1h REAL,
|
||||
percent_change_24h REAL,
|
||||
percent_change_7d REAL,
|
||||
rank INTEGER,
|
||||
last_updated TIMESTAMP NOT NULL,
|
||||
FOREIGN KEY (asset_id) REFERENCES assets(id)
|
||||
);
|
||||
|
||||
-- Currency conversion rates for crypto prices
|
||||
CREATE TABLE price_conversions (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
price_id TEXT NOT NULL,
|
||||
currency_code TEXT NOT NULL,
|
||||
price REAL,
|
||||
volume_24h REAL,
|
||||
market_cap REAL,
|
||||
last_updated TIMESTAMP NOT NULL,
|
||||
FOREIGN KEY (price_id) REFERENCES prices(id),
|
||||
UNIQUE(price_id, currency_code)
|
||||
);
|
||||
|
||||
-- Global market data from Alternative.me API
|
||||
CREATE TABLE global_market (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
total_market_cap_usd REAL,
|
||||
total_24h_volume_usd REAL,
|
||||
bitcoin_percentage_of_market_cap REAL,
|
||||
active_currencies INTEGER,
|
||||
active_assets INTEGER,
|
||||
active_markets INTEGER,
|
||||
last_updated TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
-- Fear and Greed Index data from Alternative.me
|
||||
CREATE TABLE fear_greed_index (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
value INTEGER NOT NULL,
|
||||
value_classification TEXT NOT NULL,
|
||||
timestamp TIMESTAMP NOT NULL,
|
||||
time_until_update TEXT
|
||||
);
|
||||
|
||||
-- Listings data from Alternative.me API
|
||||
CREATE TABLE crypto_listings (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
api_id TEXT NOT NULL,
|
||||
name TEXT NOT NULL,
|
||||
symbol TEXT NOT NULL,
|
||||
website_slug TEXT NOT NULL,
|
||||
UNIQUE(api_id)
|
||||
);
|
||||
|
||||
-- Service for Service Records sourced on chain
|
||||
CREATE TABLE services (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
name TEXT NOT NULL,
|
||||
description TEXT,
|
||||
chain_id TEXT NOT NULL,
|
||||
address TEXT NOT NULL,
|
||||
owner_address TEXT NOT NULL,
|
||||
metadata TEXT CHECK(json_valid(metadata)),
|
||||
status TEXT NOT NULL,
|
||||
block_height INTEGER NOT NULL,
|
||||
FOREIGN KEY (chain_id) REFERENCES assets(chain_id),
|
||||
UNIQUE(chain_id, address)
|
||||
);
|
||||
|
||||
-- Activity table for basic transaction broadcast activity
|
||||
CREATE TABLE activities (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
account_id TEXT NOT NULL,
|
||||
tx_hash TEXT,
|
||||
tx_type TEXT NOT NULL,
|
||||
status TEXT NOT NULL,
|
||||
amount TEXT,
|
||||
fee TEXT,
|
||||
gas_used INTEGER,
|
||||
gas_wanted INTEGER,
|
||||
memo TEXT,
|
||||
block_height INTEGER,
|
||||
timestamp TIMESTAMP NOT NULL,
|
||||
raw_log TEXT,
|
||||
error TEXT,
|
||||
FOREIGN KEY (account_id) REFERENCES accounts(id)
|
||||
);
|
||||
|
||||
-- Health table for scheduled checks for API endpoints
|
||||
CREATE TABLE health (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
endpoint_url TEXT NOT NULL,
|
||||
endpoint_type TEXT NOT NULL,
|
||||
chain_id TEXT,
|
||||
status TEXT NOT NULL,
|
||||
response_time_ms INTEGER,
|
||||
last_checked TIMESTAMP NOT NULL,
|
||||
next_check TIMESTAMP,
|
||||
failure_count INTEGER NOT NULL DEFAULT 0,
|
||||
success_count INTEGER NOT NULL DEFAULT 0,
|
||||
response_data TEXT,
|
||||
error_message TEXT,
|
||||
FOREIGN KEY (chain_id) REFERENCES assets(chain_id)
|
||||
);
|
||||
|
||||
-- Blockchains table to store chain configuration parameters
|
||||
CREATE TABLE blockchains (
|
||||
id TEXT PRIMARY KEY,
|
||||
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
|
||||
deleted_at TIMESTAMP,
|
||||
|
||||
-- Basic chain information
|
||||
chain_name TEXT NOT NULL,
|
||||
chain_id_cosmos TEXT,
|
||||
chain_id_evm TEXT,
|
||||
api_name TEXT,
|
||||
bech_account_prefix TEXT,
|
||||
bech_validator_prefix TEXT,
|
||||
|
||||
-- Chain assets
|
||||
main_asset_symbol TEXT,
|
||||
main_asset_denom TEXT,
|
||||
staking_asset_symbol TEXT,
|
||||
staking_asset_denom TEXT,
|
||||
is_stake_enabled BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_stake_enabled IN (0,1)),
|
||||
|
||||
-- Chain images
|
||||
chain_image TEXT,
|
||||
main_asset_image TEXT,
|
||||
staking_asset_image TEXT,
|
||||
|
||||
-- Chain types and features
|
||||
chain_type TEXT NOT NULL CHECK(json_valid(chain_type)),
|
||||
is_support_mobile_wallet BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_support_mobile_wallet IN (0,1)),
|
||||
is_support_extension_wallet BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_support_extension_wallet IN (0,1)),
|
||||
is_support_erc20 BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_support_erc20 IN (0,1)),
|
||||
|
||||
-- Descriptions in multiple languages
|
||||
description_en TEXT,
|
||||
description_ko TEXT,
|
||||
description_ja TEXT,
|
||||
|
||||
-- Genesis information
|
||||
origin_genesis_time TIMESTAMP,
|
||||
|
||||
-- Account types configuration
|
||||
account_type TEXT NOT NULL CHECK(json_valid(account_type)),
|
||||
|
||||
-- BTC staking specific
|
||||
btc_staking TEXT CHECK(json_valid(btc_staking)),
|
||||
|
||||
-- Cosmos fee information
|
||||
cosmos_fee_info TEXT CHECK(json_valid(cosmos_fee_info)),
|
||||
|
||||
-- EVM fee information
|
||||
evm_fee_info TEXT CHECK(json_valid(evm_fee_info)),
|
||||
|
||||
-- Endpoints
|
||||
lcd_endpoint TEXT CHECK(json_valid(lcd_endpoint)),
|
||||
grpc_endpoint TEXT CHECK(json_valid(grpc_endpoint)),
|
||||
evm_rpc_endpoint TEXT CHECK(json_valid(evm_rpc_endpoint)),
|
||||
|
||||
-- Explorer information
|
||||
explorer TEXT CHECK(json_valid(explorer)),
|
||||
|
||||
-- Social and documentation links
|
||||
about TEXT CHECK(json_valid(about)),
|
||||
forum TEXT CHECK(json_valid(forum))
|
||||
);
|
||||
|
||||
-- Add all necessary indexes
|
||||
CREATE INDEX idx_assets_symbol ON assets(symbol);
|
||||
CREATE INDEX idx_assets_chain_id ON assets(chain_id);
|
||||
CREATE INDEX idx_assets_deleted_at ON assets(deleted_at);
|
||||
|
||||
CREATE INDEX idx_credentials_handle ON credentials(handle);
|
||||
CREATE INDEX idx_credentials_origin ON credentials(origin);
|
||||
CREATE INDEX idx_credentials_deleted_at ON credentials(deleted_at);
|
||||
|
||||
CREATE INDEX idx_accounts_address ON accounts(address);
|
||||
CREATE INDEX idx_accounts_chain_id ON accounts(chain_id);
|
||||
CREATE INDEX idx_accounts_block_created ON accounts(block_created);
|
||||
CREATE INDEX idx_accounts_label ON accounts(label);
|
||||
CREATE INDEX idx_accounts_controller ON accounts(controller);
|
||||
CREATE INDEX idx_accounts_deleted_at ON accounts(deleted_at);
|
||||
|
||||
CREATE INDEX idx_profiles_handle ON profiles(handle);
|
||||
CREATE INDEX idx_profiles_address ON profiles(address);
|
||||
CREATE INDEX idx_profiles_deleted_at ON profiles(deleted_at);
|
||||
|
||||
CREATE INDEX idx_vaults_handle ON vaults(handle);
|
||||
CREATE INDEX idx_vaults_session_id ON vaults(session_id);
|
||||
CREATE INDEX idx_vaults_deleted_at ON vaults(deleted_at);
|
||||
|
||||
CREATE INDEX idx_prices_asset_id ON prices(asset_id);
|
||||
CREATE INDEX idx_prices_rank ON prices(rank);
|
||||
CREATE INDEX idx_prices_last_updated ON prices(last_updated);
|
||||
CREATE INDEX idx_prices_deleted_at ON prices(deleted_at);
|
||||
|
||||
CREATE INDEX idx_price_conversions_price_id ON price_conversions(price_id);
|
||||
CREATE INDEX idx_price_conversions_currency_code ON price_conversions(currency_code);
|
||||
CREATE INDEX idx_price_conversions_deleted_at ON price_conversions(deleted_at);
|
||||
|
||||
CREATE INDEX idx_global_market_last_updated ON global_market(last_updated);
|
||||
CREATE INDEX idx_global_market_deleted_at ON global_market(deleted_at);
|
||||
|
||||
CREATE INDEX idx_fear_greed_index_timestamp ON fear_greed_index(timestamp);
|
||||
CREATE INDEX idx_fear_greed_index_value ON fear_greed_index(value);
|
||||
CREATE INDEX idx_fear_greed_index_deleted_at ON fear_greed_index(deleted_at);
|
||||
|
||||
CREATE INDEX idx_crypto_listings_api_id ON crypto_listings(api_id);
|
||||
CREATE INDEX idx_crypto_listings_symbol ON crypto_listings(symbol);
|
||||
CREATE INDEX idx_crypto_listings_website_slug ON crypto_listings(website_slug);
|
||||
CREATE INDEX idx_crypto_listings_deleted_at ON crypto_listings(deleted_at);
|
||||
|
||||
CREATE INDEX idx_services_name ON services(name);
|
||||
CREATE INDEX idx_services_chain_id ON services(chain_id);
|
||||
CREATE INDEX idx_services_address ON services(address);
|
||||
CREATE INDEX idx_services_owner_address ON services(owner_address);
|
||||
CREATE INDEX idx_services_status ON services(status);
|
||||
CREATE INDEX idx_services_deleted_at ON services(deleted_at);
|
||||
|
||||
CREATE INDEX idx_activities_account_id ON activities(account_id);
|
||||
CREATE INDEX idx_activities_tx_hash ON activities(tx_hash);
|
||||
CREATE INDEX idx_activities_tx_type ON activities(tx_type);
|
||||
CREATE INDEX idx_activities_status ON activities(status);
|
||||
CREATE INDEX idx_activities_timestamp ON activities(timestamp);
|
||||
CREATE INDEX idx_activities_block_height ON activities(block_height);
|
||||
CREATE INDEX idx_activities_deleted_at ON activities(deleted_at);
|
||||
|
||||
CREATE INDEX idx_health_endpoint_url ON health(endpoint_url);
|
||||
CREATE INDEX idx_health_endpoint_type ON health(endpoint_type);
|
||||
CREATE INDEX idx_health_chain_id ON health(chain_id);
|
||||
CREATE INDEX idx_health_status ON health(status);
|
||||
CREATE INDEX idx_health_last_checked ON health(last_checked);
|
||||
CREATE INDEX idx_health_next_check ON health(next_check);
|
||||
CREATE INDEX idx_health_deleted_at ON health(deleted_at);
|
||||
|
||||
CREATE INDEX idx_blockchains_chain_name ON blockchains(chain_name);
|
||||
CREATE INDEX idx_blockchains_chain_id_cosmos ON blockchains(chain_id_cosmos);
|
||||
CREATE INDEX idx_blockchains_chain_id_evm ON blockchains(chain_id_evm);
|
||||
CREATE INDEX idx_blockchains_main_asset_symbol ON blockchains(main_asset_symbol);
|
||||
CREATE INDEX idx_blockchains_deleted_at ON blockchains(deleted_at);
|
||||
686
cmd/vault/worker.mjs
Normal file
686
cmd/vault/worker.mjs
Normal file
@@ -0,0 +1,686 @@
|
||||
export { default } from "./build/worker.mjs";
|
||||
import { DurableObject } from "cloudflare:workers";
|
||||
import createPlugin from "@extism/extism";
|
||||
import { createHelia } from "helia";
|
||||
import { strings } from "@helia/strings";
|
||||
import { json } from "@helia/json";
|
||||
import { dagJson } from "@helia/dag-json";
|
||||
import { dagCbor } from "@helia/dag-cbor";
|
||||
import { unixfs } from "@helia/unixfs";
|
||||
import { serialiseSignDoc } from "sonr-cosmes/codec";
|
||||
import { broadcastTx, RpcClient } from "sonr-cosmes/client";
|
||||
import {
|
||||
DidV1MsgRegisterController,
|
||||
DwnV1QuerySpawnRequest,
|
||||
} from "sonr-cosmes/protobufs";
|
||||
|
||||
export class Vault extends DurableObject {
|
||||
constructor(ctx, env) {
|
||||
super(ctx, env);
|
||||
this.state = ctx;
|
||||
this.env = env;
|
||||
|
||||
// Initialize node state
|
||||
this.nodeState = {
|
||||
status: "offline",
|
||||
nodeId: null,
|
||||
discoveredPeers: new Map(),
|
||||
connectedPeers: new Map(),
|
||||
logs: [],
|
||||
};
|
||||
|
||||
// Initialize Helia node and related components when the DO is created
|
||||
this.initializeHelia();
|
||||
this.initializePlugins();
|
||||
}
|
||||
|
||||
// Helper method to add a log entry
|
||||
addLog(message) {
|
||||
const timestamp = new Date().toISOString();
|
||||
const logEntry = { timestamp, message };
|
||||
this.nodeState.logs.push(logEntry);
|
||||
|
||||
// Keep only the last 100 log entries
|
||||
if (this.nodeState.logs.length > 100) {
|
||||
this.nodeState.logs.shift();
|
||||
}
|
||||
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
async initializeHelia() {
|
||||
try {
|
||||
this.addLog("Initializing Helia node...");
|
||||
|
||||
// Create a Helia node with memory blockstore and datastore
|
||||
this.helia = await createHelia({
|
||||
blockstore: { type: "memory" },
|
||||
datastore: { type: "memory" },
|
||||
// Configure libp2p for Cloudflare Workers environment
|
||||
libp2p: {
|
||||
start: true,
|
||||
addresses: { listen: [] },
|
||||
connectionManager: {
|
||||
minConnections: 0,
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
// Initialize various data handlers
|
||||
this.stringHandler = strings(this.helia);
|
||||
this.jsonHandler = json(this.helia);
|
||||
this.dagJsonHandler = dagJson(this.helia);
|
||||
this.dagCborHandler = dagCbor(this.helia);
|
||||
this.fsHandler = unixfs(this.helia);
|
||||
|
||||
// Update node state
|
||||
this.nodeState.status = this.helia.libp2p.status;
|
||||
this.nodeState.nodeId = this.helia.libp2p.peerId.toString();
|
||||
|
||||
// Set up event listeners
|
||||
this.helia.libp2p.addEventListener("peer:discovery", (evt) => {
|
||||
const peerId = evt.detail.id.toString();
|
||||
this.nodeState.discoveredPeers.set(peerId, {
|
||||
id: peerId,
|
||||
multiaddrs: evt.detail.multiaddrs
|
||||
? evt.detail.multiaddrs.map((ma) => ma.toString())
|
||||
: [],
|
||||
discoveredAt: new Date().toISOString(),
|
||||
});
|
||||
this.addLog(`Discovered peer ${peerId}`);
|
||||
});
|
||||
|
||||
this.helia.libp2p.addEventListener("peer:connect", (evt) => {
|
||||
const peerId = evt.detail.toString();
|
||||
this.nodeState.connectedPeers.set(peerId, {
|
||||
id: peerId,
|
||||
connectedAt: new Date().toISOString(),
|
||||
});
|
||||
this.addLog(`Connected to ${peerId}`);
|
||||
});
|
||||
|
||||
this.helia.libp2p.addEventListener("peer:disconnect", (evt) => {
|
||||
const peerId = evt.detail.toString();
|
||||
this.nodeState.connectedPeers.delete(peerId);
|
||||
this.addLog(`Disconnected from ${peerId}`);
|
||||
});
|
||||
|
||||
this.addLog("Helia node initialized successfully");
|
||||
return true;
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to initialize Helia node: ${error.message}`);
|
||||
console.error("Failed to initialize Helia node:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// initializePlugins initializes the signer plugin
|
||||
async initializePlugins() {
|
||||
try {
|
||||
// 1. Initialize the enclave plugin
|
||||
this.addLog("Initializing enclave plugin...");
|
||||
this.enclavePlugin = await createPlugin(
|
||||
"https://cdn.sonr.io/bin/enclave.wasm",
|
||||
{
|
||||
useWasi: true,
|
||||
},
|
||||
);
|
||||
this.addLog("Enclave plugin initialized successfully");
|
||||
|
||||
// 2. Initialize the signer plugin
|
||||
this.addLog("Initializing signer plugin...");
|
||||
this.signerPlugin = await createPlugin(
|
||||
"https://cdn.sonr.io/bin/signer.wasm",
|
||||
{
|
||||
useWasi: true,
|
||||
},
|
||||
);
|
||||
this.addLog("Signer plugin initialized successfully");
|
||||
|
||||
// 3. Initialize the verifier plugin
|
||||
this.addLog("Initializing verifier plugin...");
|
||||
this.verifierPlugin = await createPlugin(
|
||||
"https://cdn.sonr.io/bin/verifier.wasm",
|
||||
{
|
||||
useWasi: true,
|
||||
},
|
||||
);
|
||||
this.addLog("Verifier plugin initialized successfully");
|
||||
return true;
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to initialize plugin: ${error.message}`);
|
||||
console.error("Failed to initialize plugin:", error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// RPC method to get node status
|
||||
async getNodeStatus() {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
return {
|
||||
status: this.nodeState.status,
|
||||
nodeId: this.nodeState.nodeId,
|
||||
discoveredPeersCount: this.nodeState.discoveredPeers.size,
|
||||
connectedPeersCount: this.nodeState.connectedPeers.size,
|
||||
};
|
||||
}
|
||||
|
||||
// RPC method to get node ID
|
||||
async getNodeId() {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
return {
|
||||
nodeId: this.nodeState.nodeId,
|
||||
};
|
||||
}
|
||||
|
||||
// RPC method to get discovered peers
|
||||
async getDiscoveredPeers() {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
return {
|
||||
count: this.nodeState.discoveredPeers.size,
|
||||
peers: Array.from(this.nodeState.discoveredPeers.values()),
|
||||
};
|
||||
}
|
||||
|
||||
// RPC method to get connected peers
|
||||
async getConnectedPeers() {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
return {
|
||||
count: this.nodeState.connectedPeers.size,
|
||||
peers: Array.from(this.nodeState.connectedPeers.values()),
|
||||
};
|
||||
}
|
||||
|
||||
// RPC method to get logs
|
||||
async getLogs(limit = 50) {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
const logs = [...this.nodeState.logs];
|
||||
return {
|
||||
count: logs.length,
|
||||
logs: logs.slice(-limit), // Return the most recent logs up to the limit
|
||||
};
|
||||
}
|
||||
|
||||
// RPC method to sign data
|
||||
async sign(data) {
|
||||
if (!this.plugin) {
|
||||
await this.initializePlugin();
|
||||
}
|
||||
try {
|
||||
let out = await this.plugin.call("sign", JSON.stringify(data));
|
||||
return JSON.parse(out.text());
|
||||
} catch (error) {
|
||||
throw new Error(`Signing failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Creates and signs a transaction
|
||||
async createAndSignTx(msg, signer, options = {}) {
|
||||
this.addLog(`Creating transaction with message type: ${msg.typeUrl}`);
|
||||
|
||||
try {
|
||||
// Default options
|
||||
const defaultOptions = {
|
||||
memo: "",
|
||||
fee: {
|
||||
amount: [{ denom: "usnr", amount: "1000" }],
|
||||
gas_limit: "200000",
|
||||
},
|
||||
chainId: this.env.SONR_CHAIN_ID || "sonr-testnet-1",
|
||||
};
|
||||
|
||||
const txOptions = { ...defaultOptions, ...options };
|
||||
|
||||
// Create the sign doc
|
||||
const signDoc = {
|
||||
chainId: txOptions.chainId,
|
||||
accountNumber: options.accountNumber || "0",
|
||||
sequence: options.sequence || "0",
|
||||
fee: txOptions.fee,
|
||||
msgs: [msg],
|
||||
memo: txOptions.memo,
|
||||
};
|
||||
|
||||
// Serialize the sign doc
|
||||
const signBytes = serialiseSignDoc(signDoc);
|
||||
|
||||
// Sign the transaction
|
||||
this.addLog(`Signing transaction for ${signer}`);
|
||||
const signature = await this.sign({
|
||||
bytes: Buffer.from(signBytes).toString("base64"),
|
||||
publicKey: options.publicKey,
|
||||
});
|
||||
|
||||
// Create the signed transaction
|
||||
const signedTx = {
|
||||
signDoc,
|
||||
signature: {
|
||||
signature: signature.signature,
|
||||
pub_key: {
|
||||
type: "tendermint/PubKeySecp256k1",
|
||||
value: signature.publicKey,
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
this.addLog("Transaction created and signed successfully");
|
||||
return signedTx;
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to create and sign transaction: ${error.message}`);
|
||||
throw new Error(`Transaction creation failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Broadcasts a signed transaction to the network
|
||||
async broadcastTransaction(signedTx, broadcastMode = "BROADCAST_MODE_SYNC") {
|
||||
this.addLog("Broadcasting transaction to network");
|
||||
|
||||
try {
|
||||
const rpcUrl = this.env.SONR_RPC_URL || "https://rpc.sonr.io";
|
||||
this.addLog(`Using RPC URL: ${rpcUrl}`);
|
||||
|
||||
const response = await broadcastTx(rpcUrl, signedTx, broadcastMode);
|
||||
|
||||
if (response.tx_response && response.tx_response.code === 0) {
|
||||
this.addLog(
|
||||
`Transaction broadcast successful. Hash: ${response.tx_response.txhash}`,
|
||||
);
|
||||
} else {
|
||||
this.addLog(
|
||||
`Transaction broadcast failed: ${JSON.stringify(response.tx_response)}`,
|
||||
);
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to broadcast transaction: ${error.message}`);
|
||||
throw new Error(`Transaction broadcast failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// RPC method to add string content to IPFS
|
||||
async addString(content) {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
if (!this.helia) {
|
||||
throw new Error("Helia node not available");
|
||||
}
|
||||
|
||||
try {
|
||||
const cid = await this.stringHandler.add(content);
|
||||
this.addLog(`Added string content with CID: ${cid.toString()}`);
|
||||
return { cid: cid.toString() };
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to add string: ${error.message}`);
|
||||
throw new Error(`Failed to add string: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// RPC method to add JSON content to IPFS
|
||||
async addJson(content) {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
if (!this.helia) {
|
||||
throw new Error("Helia node not available");
|
||||
}
|
||||
|
||||
try {
|
||||
const cid = await this.jsonHandler.add(content);
|
||||
this.addLog(`Added JSON content with CID: ${cid.toString()}`);
|
||||
return { cid: cid.toString() };
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to add JSON: ${error.message}`);
|
||||
throw new Error(`Failed to add JSON: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// RPC method to get content from IPFS by CID
|
||||
async getContent(cid) {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
if (!this.helia) {
|
||||
throw new Error("Helia node not available");
|
||||
}
|
||||
|
||||
try {
|
||||
this.addLog(`Retrieving content for CID: ${cid}`);
|
||||
// Try to get as JSON first
|
||||
try {
|
||||
const jsonData = await this.jsonHandler.get(cid);
|
||||
return { type: "json", content: jsonData };
|
||||
} catch (e) {
|
||||
// Fall back to string if JSON fails
|
||||
try {
|
||||
const stringData = await this.stringHandler.get(cid);
|
||||
return { type: "string", content: stringData };
|
||||
} catch (e2) {
|
||||
this.addLog(`Failed to retrieve content for CID: ${cid}`);
|
||||
throw new Error("Failed to retrieve content");
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
this.addLog(`Error getting content: ${error.message}`);
|
||||
throw new Error(`Failed to get content: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// RPC method to add DAG-JSON content to IPFS
|
||||
async addDagJson(content) {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
if (!this.helia) {
|
||||
throw new Error("Helia node not available");
|
||||
}
|
||||
|
||||
try {
|
||||
const cid = await this.dagJsonHandler.add(content);
|
||||
this.addLog(`Added DAG-JSON content with CID: ${cid.toString()}`);
|
||||
return { cid: cid.toString() };
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to add DAG-JSON: ${error.message}`);
|
||||
throw new Error(`Failed to add DAG-JSON: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// RPC method to add DAG-CBOR content to IPFS
|
||||
async addDagCbor(content) {
|
||||
if (!this.helia) {
|
||||
await this.initializeHelia();
|
||||
}
|
||||
|
||||
if (!this.helia) {
|
||||
throw new Error("Helia node not available");
|
||||
}
|
||||
|
||||
try {
|
||||
const cid = await this.dagCborHandler.add(content);
|
||||
this.addLog(`Added DAG-CBOR content with CID: ${cid.toString()}`);
|
||||
return { cid: cid.toString() };
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to add DAG-CBOR: ${error.message}`);
|
||||
throw new Error(`Failed to add DAG-CBOR: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async registerDidController(did, controller, signer, options = {}) {
|
||||
this.addLog(`Registering DID controller: ${controller} for DID: ${did}`);
|
||||
|
||||
try {
|
||||
// Create the message
|
||||
const msg = DidV1MsgRegisterController.create({
|
||||
did: did,
|
||||
controller: controller,
|
||||
});
|
||||
|
||||
// Create and sign transaction
|
||||
const signedTx = await this.createAndSignTx(msg, signer, options);
|
||||
|
||||
// Broadcast transaction
|
||||
const response = await this.broadcastTransaction(signedTx);
|
||||
|
||||
this.addLog(
|
||||
`DID controller registration response: ${JSON.stringify(response)}`,
|
||||
);
|
||||
return response;
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to register DID controller: ${error.message}`);
|
||||
throw new Error(`DID controller registration failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
async spawnDwnVault(address, redirect, options = {}) {
|
||||
this.addLog(
|
||||
`Spawning DWN vault for address: ${address}, redirect: ${redirect}`,
|
||||
);
|
||||
|
||||
try {
|
||||
// Use RPC client to make the query
|
||||
const rpcUrl =
|
||||
options.rpcUrl || this.env.SONR_RPC_URL || "https://rpc.sonr.io";
|
||||
this.addLog(`Using RPC URL: ${rpcUrl}`);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
RpcClient.newBatchQuery(rpcUrl)
|
||||
.add(
|
||||
DwnV1QuerySpawnRequest,
|
||||
{
|
||||
cid: address,
|
||||
redirect: redirect,
|
||||
},
|
||||
(err, res) => {
|
||||
if (err) {
|
||||
this.addLog(`Spawn DWN vault failed: ${err.message}`);
|
||||
reject(err);
|
||||
} else {
|
||||
this.addLog(`Spawn DWN vault response: ${JSON.stringify(res)}`);
|
||||
resolve(res);
|
||||
}
|
||||
},
|
||||
)
|
||||
.send();
|
||||
});
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to spawn DWN vault: ${error.message}`);
|
||||
throw new Error(`DWN vault spawn failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieves account information needed for transaction signing
|
||||
async getAccountInfo(address) {
|
||||
this.addLog(`Getting account info for address: ${address}`);
|
||||
|
||||
try {
|
||||
const rpcUrl = this.env.SONR_RPC_URL || "https://rpc.sonr.io";
|
||||
|
||||
const client = new RpcClient(rpcUrl);
|
||||
const accountInfo = await client.getAccount(address);
|
||||
|
||||
this.addLog(`Account info retrieved successfully`);
|
||||
return {
|
||||
accountNumber: accountInfo.account_number,
|
||||
sequence: accountInfo.sequence,
|
||||
};
|
||||
} catch (error) {
|
||||
this.addLog(`Failed to get account info: ${error.message}`);
|
||||
throw new Error(`Account info retrieval failed: ${error.message}`);
|
||||
}
|
||||
}
|
||||
|
||||
// Fetch handler for backward compatibility and Go WASM server interaction
|
||||
async fetch(request) {
|
||||
const url = new URL(request.url);
|
||||
const path = url.pathname;
|
||||
const method = request.method;
|
||||
|
||||
try {
|
||||
// Handle different API endpoints based on the path
|
||||
|
||||
// Helia node status endpoints
|
||||
if (path === "/helia/status") {
|
||||
return new Response(JSON.stringify(await this.getNodeStatus()), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
if (path === "/helia/node-id") {
|
||||
return new Response(JSON.stringify(await this.getNodeId()), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
if (path === "/helia/discovered-peers") {
|
||||
return new Response(JSON.stringify(await this.getDiscoveredPeers()), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
if (path === "/helia/connected-peers") {
|
||||
return new Response(JSON.stringify(await this.getConnectedPeers()), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
if (path === "/helia/logs") {
|
||||
const limitParam = url.searchParams.get("limit");
|
||||
const limit = limitParam ? parseInt(limitParam, 10) : 50;
|
||||
return new Response(JSON.stringify(await this.getLogs(limit)), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
// IPFS content endpoints
|
||||
if (path === "/ipfs/add/string" && method === "POST") {
|
||||
const content = await request.text();
|
||||
return new Response(JSON.stringify(await this.addString(content)), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
if (path === "/ipfs/add/json" && method === "POST") {
|
||||
const content = await request.json();
|
||||
return new Response(JSON.stringify(await this.addJson(content)), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
if (path.startsWith("/ipfs/get/") && method === "GET") {
|
||||
const cid = path.replace("/ipfs/get/", "");
|
||||
const result = await this.getContent(cid);
|
||||
|
||||
if (result.type === "json") {
|
||||
return new Response(JSON.stringify(result.content), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} else {
|
||||
return new Response(result.content, {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "text/plain" },
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (path === "/ipfs/dag/json" && method === "POST") {
|
||||
const content = await request.json();
|
||||
return new Response(JSON.stringify(await this.addDagJson(content)), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
if (path === "/ipfs/dag/cbor" && method === "POST") {
|
||||
const content = await request.json();
|
||||
return new Response(JSON.stringify(await this.addDagCbor(content)), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
// Signing endpoint
|
||||
if (path === "/vault/sign" && method === "POST") {
|
||||
const data = await request.json();
|
||||
return new Response(JSON.stringify(await this.sign(data)), {
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
|
||||
// DID controller registration endpoint
|
||||
if (path === "/did/register-controller" && method === "POST") {
|
||||
const data = await request.json();
|
||||
const { did, controller, signer, options } = data;
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(
|
||||
await this.registerDidController(did, controller, signer, options),
|
||||
),
|
||||
{
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// DWN vault spawning endpoint
|
||||
if (path === "/dwn/spawn" && method === "POST") {
|
||||
const data = await request.json();
|
||||
const { address, redirect, options } = data;
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(await this.spawnDwnVault(address, redirect, options)),
|
||||
{
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Account info endpoint
|
||||
if (path === "/account/info" && method === "GET") {
|
||||
const address = url.searchParams.get("address");
|
||||
if (!address) {
|
||||
return new Response(
|
||||
JSON.stringify({ error: "Address parameter is required" }),
|
||||
{
|
||||
status: 400,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return new Response(
|
||||
JSON.stringify(await this.getAccountInfo(address)),
|
||||
{
|
||||
status: 200,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
// Default response for unhandled paths
|
||||
return new Response(JSON.stringify({ error: "Not found" }), {
|
||||
status: 404,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
} catch (error) {
|
||||
// Log the error
|
||||
this.addLog(`Error handling request to ${path}: ${error.message}`);
|
||||
|
||||
// Return error response
|
||||
return new Response(JSON.stringify({ error: error.message }), {
|
||||
status: 500,
|
||||
headers: { "Content-Type": "application/json" },
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
53
cmd/vault/wrangler.toml
Normal file
53
cmd/vault/wrangler.toml
Normal file
@@ -0,0 +1,53 @@
|
||||
# Top-level configuration
|
||||
name = "motr-vault"
|
||||
main = "./worker.mjs"
|
||||
compatibility_date = "2025-04-14"
|
||||
|
||||
routes = [
|
||||
{ pattern = "did.run", custom_domain = true },
|
||||
]
|
||||
|
||||
[build]
|
||||
command = "npm run build"
|
||||
|
||||
[dev]
|
||||
port = 6969
|
||||
|
||||
[observability]
|
||||
enabled = true
|
||||
logpush = true
|
||||
|
||||
[[d1_databases]]
|
||||
binding = "DB" # available in your Worker on env.DB
|
||||
database_name = "motr-controller-db"
|
||||
database_id = "872a4b08-7e07-4978-b227-5b60940238ed"
|
||||
|
||||
[[kv_namespaces]]
|
||||
binding = "SESSIONS" # available in your Worker on env.KV
|
||||
id = "ea5de66fcfc14b5eba170395e29432ee"
|
||||
|
||||
[[kv_namespaces]]
|
||||
binding = "HANDLES" # available in your Worker on env.KV
|
||||
id = "271d47087a8842b2aac5ee79cf7bb203"
|
||||
|
||||
[[r2_buckets]]
|
||||
binding = 'PROFILES'
|
||||
bucket_name = 'profiles'
|
||||
|
||||
[vars]
|
||||
SONR_CHAIN_ID = 'sonr-testnet-1'
|
||||
IPFS_GATEWAY = 'https://ipfs.sonr.land'
|
||||
SONR_API_URL = 'https://api.sonr.land'
|
||||
SONR_RPC_URL = 'https://rpc.sonr.land'
|
||||
SONR_GRPC_URL = 'https://grpc.sonr.land'
|
||||
MATRIX_SERVER = 'https://bm.chat'
|
||||
MOTR_GATEWAY = 'https://sonr.id'
|
||||
MOTR_VAULT = 'https://did.run'
|
||||
MOTR_MODE = 'controller'
|
||||
|
||||
[durable_objects]
|
||||
bindings = [{name = "VAULT", class_name = "Vault"}]
|
||||
|
||||
[[migrations]]
|
||||
tag = "v1" # Should be unique for each entry
|
||||
new_classes = ["Vault"] # List the classes that should be created
|
||||
20
components/charts/area_chart.templ
Normal file
20
components/charts/area_chart.templ
Normal file
@@ -0,0 +1,20 @@
|
||||
package charts
|
||||
|
||||
import "fmt"
|
||||
|
||||
type DateValue struct {
|
||||
Date string
|
||||
Value int
|
||||
}
|
||||
|
||||
templ AreaChart(data []DateValue) {
|
||||
for _, d := range data {
|
||||
<div class="flex flex-col">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-900">${ d.Date }</span>
|
||||
<span class="text-sm font-medium text-gray-900">${ fmt.Sprintf("%d", d.Value) }</span>
|
||||
</div>
|
||||
<div class="h-1 bg-gray-200 rounded-full"></div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
75
components/charts/area_chart_templ.go
Normal file
75
components/charts/area_chart_templ.go
Normal file
@@ -0,0 +1,75 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package charts
|
||||
|
||||
//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 "fmt"
|
||||
|
||||
type DateValue struct {
|
||||
Date string
|
||||
Value int
|
||||
}
|
||||
|
||||
func AreaChart(data []DateValue) 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)
|
||||
for _, d := range data {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col\"><div class=\"flex justify-between\"><span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(d.Date)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/area_chart.templ`, Line: 14, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", d.Value))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/area_chart.templ`, Line: 15, Col: 81}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"h-1 bg-gray-200 rounded-full\"></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
21
components/charts/bar_chart.templ
Normal file
21
components/charts/bar_chart.templ
Normal file
@@ -0,0 +1,21 @@
|
||||
package charts
|
||||
|
||||
import "fmt"
|
||||
|
||||
type KeyValue struct {
|
||||
Key string
|
||||
Value int
|
||||
Color string
|
||||
}
|
||||
|
||||
templ BarChart(data []KeyValue) {
|
||||
for _, d := range data {
|
||||
<div class="flex flex-col">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-900">${ d.Key }</span>
|
||||
<span class="text-sm font-medium text-gray-900">${ fmt.Sprintf("%d", d.Value) }</span>
|
||||
</div>
|
||||
<div class="h-1 bg-gray-200 rounded-full"></div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
76
components/charts/bar_chart_templ.go
Normal file
76
components/charts/bar_chart_templ.go
Normal file
@@ -0,0 +1,76 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package charts
|
||||
|
||||
//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 "fmt"
|
||||
|
||||
type KeyValue struct {
|
||||
Key string
|
||||
Value int
|
||||
Color string
|
||||
}
|
||||
|
||||
func BarChart(data []KeyValue) 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)
|
||||
for _, d := range data {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col\"><div class=\"flex justify-between\"><span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(d.Key)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/bar_chart.templ`, Line: 15, Col: 60}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", d.Value))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/bar_chart.templ`, Line: 16, Col: 81}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"h-1 bg-gray-200 rounded-full\"></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
106
components/charts/candle_chart.templ
Normal file
106
components/charts/candle_chart.templ
Normal file
@@ -0,0 +1,106 @@
|
||||
package charts
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CandleData struct {
|
||||
Open float64
|
||||
Close float64
|
||||
High float64
|
||||
Low float64
|
||||
Date time.Time
|
||||
}
|
||||
|
||||
// D3 script handle for deduplication
|
||||
var d3Handle = templ.NewOnceHandle()
|
||||
|
||||
// D3 component for loading D3.js
|
||||
templ D3() {
|
||||
@d3Handle.Once() {
|
||||
<script type="module">
|
||||
|
||||
window.d3 = d3;
|
||||
</script>
|
||||
}
|
||||
}
|
||||
|
||||
// CandleChart component
|
||||
templ CandleChart(data []CandleData) {
|
||||
@D3()
|
||||
<div id="candleChart" class="@container relative">
|
||||
<div
|
||||
class="relative h-72 w-full"
|
||||
style="--marginTop: 10px; --marginRight: 60px; --marginBottom: 56px; --marginLeft: 30px;"
|
||||
></div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import * as d3 from "https://cdn.jsdelivr.net/npm/d3@7/+esm";
|
||||
// Convert Go data to JavaScript
|
||||
|
||||
// Declare the chart dimensions and margins.
|
||||
const width = 640;
|
||||
const height = 400;
|
||||
const marginTop = 20;
|
||||
const marginRight = 20;
|
||||
const marginBottom = 30;
|
||||
const marginLeft = 40;
|
||||
|
||||
// Declare the x (horizontal position) scale.
|
||||
const x = d3.scaleUtc()
|
||||
.domain([new Date("2023-01-01"), new Date("2024-01-01")])
|
||||
.range([marginLeft, width - marginRight]);
|
||||
|
||||
// Declare the y (vertical position) scale.
|
||||
const y = d3.scaleLinear()
|
||||
.domain([0, 100])
|
||||
.range([height - marginBottom, marginTop]);
|
||||
|
||||
// Create the SVG container.
|
||||
const svg = d3.create("svg")
|
||||
.attr("width", width)
|
||||
.attr("height", height);
|
||||
|
||||
// Add the x-axis.
|
||||
svg.append("g")
|
||||
.attr("transform", `translate(0,${height - marginBottom})`)
|
||||
.call(d3.axisBottom(x));
|
||||
|
||||
// Add the y-axis.
|
||||
svg.append("g")
|
||||
.attr("transform", `translate(${marginLeft},0)`)
|
||||
.call(d3.axisLeft(y));
|
||||
|
||||
// Append the SVG element.
|
||||
container.append(svg.node());
|
||||
</script>
|
||||
}
|
||||
|
||||
// formatDataForJS converts the Go data structure to a JavaScript-compatible JSON string
|
||||
func formatDataForJS(data []CandleData) string {
|
||||
type jsData struct {
|
||||
Date string `json:"date"`
|
||||
Open float64 `json:"open"`
|
||||
Close float64 `json:"close"`
|
||||
High float64 `json:"high"`
|
||||
Low float64 `json:"low"`
|
||||
}
|
||||
|
||||
jsDataArray := make([]jsData, len(data))
|
||||
for i, d := range data {
|
||||
jsDataArray[i] = jsData{
|
||||
Date: d.Date.Format(time.RFC3339),
|
||||
Open: d.Open,
|
||||
Close: d.Close,
|
||||
High: d.High,
|
||||
Low: d.Low,
|
||||
}
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(jsDataArray)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(jsonBytes)
|
||||
}
|
||||
137
components/charts/candle_chart_templ.go
Normal file
137
components/charts/candle_chart_templ.go
Normal file
@@ -0,0 +1,137 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package charts
|
||||
|
||||
//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 (
|
||||
"encoding/json"
|
||||
"time"
|
||||
)
|
||||
|
||||
type CandleData struct {
|
||||
Open float64
|
||||
Close float64
|
||||
High float64
|
||||
Low float64
|
||||
Date time.Time
|
||||
}
|
||||
|
||||
// D3 script handle for deduplication
|
||||
var d3Handle = templ.NewOnceHandle()
|
||||
|
||||
// D3 component for loading D3.js
|
||||
func D3() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<script type=\"module\">\n \n window.d3 = d3;\n </script>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = d3Handle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// CandleChart component
|
||||
func CandleChart(data []CandleData) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = D3().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div id=\"candleChart\" class=\"@container relative\"><div class=\"relative h-72 w-full\" style=\"--marginTop: 10px; --marginRight: 60px; --marginBottom: 56px; --marginLeft: 30px;\"></div></div><script type=\"module\">\n\t import * as d3 from \"https://cdn.jsdelivr.net/npm/d3@7/+esm\";\n // Convert Go data to JavaScript\n \n // Declare the chart dimensions and margins.\n const width = 640;\n const height = 400;\n const marginTop = 20;\n const marginRight = 20;\n const marginBottom = 30;\n const marginLeft = 40;\n\n // Declare the x (horizontal position) scale.\n const x = d3.scaleUtc()\n .domain([new Date(\"2023-01-01\"), new Date(\"2024-01-01\")])\n .range([marginLeft, width - marginRight]);\n\n // Declare the y (vertical position) scale.\n const y = d3.scaleLinear()\n .domain([0, 100])\n .range([height - marginBottom, marginTop]);\n\n // Create the SVG container.\n const svg = d3.create(\"svg\")\n .attr(\"width\", width)\n .attr(\"height\", height);\n\n // Add the x-axis.\n svg.append(\"g\")\n .attr(\"transform\", `translate(0,${height - marginBottom})`)\n .call(d3.axisBottom(x));\n\n // Add the y-axis.\n svg.append(\"g\")\n .attr(\"transform\", `translate(${marginLeft},0)`)\n .call(d3.axisLeft(y));\n\n // Append the SVG element.\n container.append(svg.node()); \n </script>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// formatDataForJS converts the Go data structure to a JavaScript-compatible JSON string
|
||||
func formatDataForJS(data []CandleData) string {
|
||||
type jsData struct {
|
||||
Date string `json:"date"`
|
||||
Open float64 `json:"open"`
|
||||
Close float64 `json:"close"`
|
||||
High float64 `json:"high"`
|
||||
Low float64 `json:"low"`
|
||||
}
|
||||
|
||||
jsDataArray := make([]jsData, len(data))
|
||||
for i, d := range data {
|
||||
jsDataArray[i] = jsData{
|
||||
Date: d.Date.Format(time.RFC3339),
|
||||
Open: d.Open,
|
||||
Close: d.Close,
|
||||
High: d.High,
|
||||
Low: d.Low,
|
||||
}
|
||||
}
|
||||
|
||||
jsonBytes, err := json.Marshal(jsDataArray)
|
||||
if err != nil {
|
||||
return "[]"
|
||||
}
|
||||
return string(jsonBytes)
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
15
components/charts/line_chart.templ
Normal file
15
components/charts/line_chart.templ
Normal file
@@ -0,0 +1,15 @@
|
||||
package charts
|
||||
|
||||
import "fmt"
|
||||
|
||||
templ LineChart(data []DateValue) {
|
||||
for _, d := range data {
|
||||
<div class="flex flex-col">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-900">${ d.Date }</span>
|
||||
<span class="text-sm font-medium text-gray-900">${ fmt.Sprintf("%d", d.Value) }</span>
|
||||
</div>
|
||||
<div class="h-1 bg-gray-200 rounded-full"></div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
70
components/charts/line_chart_templ.go
Normal file
70
components/charts/line_chart_templ.go
Normal file
@@ -0,0 +1,70 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package charts
|
||||
|
||||
//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 "fmt"
|
||||
|
||||
func LineChart(data []DateValue) 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)
|
||||
for _, d := range data {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col\"><div class=\"flex justify-between\"><span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(d.Date)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/line_chart.templ`, Line: 9, Col: 61}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", d.Value))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/line_chart.templ`, Line: 10, Col: 81}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"h-1 bg-gray-200 rounded-full\"></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
22
components/charts/pie_chart.templ
Normal file
22
components/charts/pie_chart.templ
Normal file
@@ -0,0 +1,22 @@
|
||||
package charts
|
||||
|
||||
import "fmt"
|
||||
|
||||
type CategoryValue struct {
|
||||
Category string
|
||||
Value int
|
||||
ColorFrom string
|
||||
ColorTo string
|
||||
}
|
||||
|
||||
templ PieChart(data []CategoryValue) {
|
||||
for _, d := range data {
|
||||
<div class="flex flex-col">
|
||||
<div class="flex justify-between">
|
||||
<span class="text-sm font-medium text-gray-900">${ d.Category }</span>
|
||||
<span class="text-sm font-medium text-gray-900">${ fmt.Sprintf("%d", d.Value) }</span>
|
||||
</div>
|
||||
<div class="h-1 bg-gray-200 rounded-full"></div>
|
||||
</div>
|
||||
}
|
||||
}
|
||||
77
components/charts/pie_chart_templ.go
Normal file
77
components/charts/pie_chart_templ.go
Normal file
@@ -0,0 +1,77 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package charts
|
||||
|
||||
//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 "fmt"
|
||||
|
||||
type CategoryValue struct {
|
||||
Category string
|
||||
Value int
|
||||
ColorFrom string
|
||||
ColorTo string
|
||||
}
|
||||
|
||||
func PieChart(data []CategoryValue) 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)
|
||||
for _, d := range data {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col\"><div class=\"flex justify-between\"><span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(d.Category)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/pie_chart.templ`, Line: 16, Col: 65}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</span> <span class=\"text-sm font-medium text-gray-900\">$")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(fmt.Sprintf("%d", d.Value))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/charts/pie_chart.templ`, Line: 17, Col: 81}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"h-1 bg-gray-200 rounded-full\"></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
83
components/dashboard/helia_console.templ
Normal file
83
components/dashboard/helia_console.templ
Normal file
@@ -0,0 +1,83 @@
|
||||
package dashboard
|
||||
|
||||
// StatusCard component for displaying Helia node status
|
||||
templ HeliaStatusCard() {
|
||||
<div class="p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex justify-between items-center mb-1">
|
||||
<h2 class="text-4xl font-semibold text-gray-800 dark:text-neutral-200">
|
||||
<span id="statusValue">Offline</span>
|
||||
</h2>
|
||||
<div class="flex items-center -space-x-2">
|
||||
<img class="shrink-0 size-7 rounded-full" src="https://images.unsplash.com/photo-1659482633369-9fe69af50bfb?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=3&w=320&h=320&q=80" alt="Avatar"/>
|
||||
</div>
|
||||
</div>
|
||||
<h3 class="text-gray-500 dark:text-neutral-500">
|
||||
Status
|
||||
</h3>
|
||||
</div>
|
||||
}
|
||||
|
||||
// NodeIDCard component for displaying Helia node ID
|
||||
templ HeliaNodeIDCard() {
|
||||
<div>
|
||||
<div class="p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex justify-between items-center mb-1">
|
||||
<h2 class="text-4xl font-semibold text-gray-800 dark:text-neutral-200">
|
||||
Node ID
|
||||
</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="inline-flex items-center gap-x-2">
|
||||
<h3 class="text-gray-500 dark:text-neutral-500">
|
||||
<span id="nodeId">-</span>
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
// DiscoveredPeersCard component for displaying discovered peers count
|
||||
templ HeliaDiscoveredPeersCard() {
|
||||
<div class="p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex justify-between items-center mb-1">
|
||||
<h2 class="text-4xl font-semibold text-gray-800 dark:text-neutral-200">
|
||||
<span id="discoveredPeerCount">0</span>
|
||||
</h2>
|
||||
</div>
|
||||
<div class="inline-flex items-center gap-x-2">
|
||||
<h3 class="text-gray-500 dark:text-neutral-500">
|
||||
Discovered Peers
|
||||
</h3>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
// ConnectedPeersCard component for displaying connected peers count
|
||||
templ HeliaConnectedPeersCard() {
|
||||
<div class="p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<div class="flex justify-between items-center mb-1">
|
||||
<h2 class="text-4xl font-semibold text-gray-800 dark:text-neutral-200">
|
||||
<span id="connectedPeerCount">0</span>
|
||||
</h2>
|
||||
<div class="flex items-center -space-x-2"></div>
|
||||
</div>
|
||||
<h3 class="text-gray-500 dark:text-neutral-500">
|
||||
Connected Peers
|
||||
</h3>
|
||||
</div>
|
||||
}
|
||||
|
||||
// Optional: Create a component for a connected peers list if needed
|
||||
templ HeliaConnectedPeersList() {
|
||||
<div class="p-4 bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<h3 class="text-lg font-medium text-gray-800 dark:text-neutral-200 mb-2">Connected Peers List</h3>
|
||||
<ul id="connectedPeersList" class="text-sm text-gray-600 dark:text-neutral-400"></ul>
|
||||
</div>
|
||||
}
|
||||
|
||||
// Optional: Create a component for the running log
|
||||
templ HeliaRunningLog() {
|
||||
<div class="p-4 bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700">
|
||||
<h3 class="text-lg font-medium text-gray-800 dark:text-neutral-200 mb-2">Running Log</h3>
|
||||
<div id="runningLog" class="text-sm text-gray-600 dark:text-neutral-400 h-40 overflow-y-auto font-mono"></div>
|
||||
</div>
|
||||
}
|
||||
191
components/dashboard/helia_console_templ.go
Normal file
191
components/dashboard/helia_console_templ.go
Normal file
@@ -0,0 +1,191 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package dashboard
|
||||
|
||||
//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"
|
||||
|
||||
// StatusCard component for displaying Helia node status
|
||||
func HeliaStatusCard() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700\"><div class=\"flex justify-between items-center mb-1\"><h2 class=\"text-4xl font-semibold text-gray-800 dark:text-neutral-200\"><span id=\"statusValue\">Offline</span></h2><div class=\"flex items-center -space-x-2\"><img class=\"shrink-0 size-7 rounded-full\" src=\"https://images.unsplash.com/photo-1659482633369-9fe69af50bfb?ixlib=rb-4.0.3&ixid=MnwxMjA3fDB8MHxwaG90by1wYWdlfHx8fGVufDB8fHx8&auto=format&fit=facearea&facepad=3&w=320&h=320&q=80\" alt=\"Avatar\"></div></div><h3 class=\"text-gray-500 dark:text-neutral-500\">Status</h3></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// NodeIDCard component for displaying Helia node ID
|
||||
func HeliaNodeIDCard() 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_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div><div class=\"p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700\"><div class=\"flex justify-between items-center mb-1\"><h2 class=\"text-4xl font-semibold text-gray-800 dark:text-neutral-200\">Node ID</h2></div></div><div class=\"inline-flex items-center gap-x-2\"><h3 class=\"text-gray-500 dark:text-neutral-500\"><span id=\"nodeId\">-</span></h3></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// DiscoveredPeersCard component for displaying discovered peers count
|
||||
func HeliaDiscoveredPeersCard() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<div class=\"p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700\"><div class=\"flex justify-between items-center mb-1\"><h2 class=\"text-4xl font-semibold text-gray-800 dark:text-neutral-200\"><span id=\"discoveredPeerCount\">0</span></h2></div><div class=\"inline-flex items-center gap-x-2\"><h3 class=\"text-gray-500 dark:text-neutral-500\">Discovered Peers</h3></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// ConnectedPeersCard component for displaying connected peers count
|
||||
func HeliaConnectedPeersCard() 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_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<div class=\"p-4 flex flex-col bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700\"><div class=\"flex justify-between items-center mb-1\"><h2 class=\"text-4xl font-semibold text-gray-800 dark:text-neutral-200\"><span id=\"connectedPeerCount\">0</span></h2><div class=\"flex items-center -space-x-2\"></div></div><h3 class=\"text-gray-500 dark:text-neutral-500\">Connected Peers</h3></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Optional: Create a component for a connected peers list if needed
|
||||
func HeliaConnectedPeersList() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"p-4 bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700\"><h3 class=\"text-lg font-medium text-gray-800 dark:text-neutral-200 mb-2\">Connected Peers List</h3><ul id=\"connectedPeersList\" class=\"text-sm text-gray-600 dark:text-neutral-400\"></ul></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// Optional: Create a component for the running log
|
||||
func HeliaRunningLog() 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_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"p-4 bg-white border border-gray-200 rounded-xl dark:bg-neutral-800 dark:border-neutral-700\"><h3 class=\"text-lg font-medium text-gray-800 dark:text-neutral-200 mb-2\">Running Log</h3><div id=\"runningLog\" class=\"text-sm text-gray-600 dark:text-neutral-400 h-40 overflow-y-auto font-mono\"></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
8
components/inputs/input_avatar.templ
Normal file
8
components/inputs/input_avatar.templ
Normal file
@@ -0,0 +1,8 @@
|
||||
package inputs
|
||||
|
||||
templ InputAvatar(value string, helpText string) {
|
||||
<input type="file" name="avatar" id="avatar" name="avatar" accept="image/*"/>
|
||||
<sl-button variant="neutral" slot="suffix" type="button">
|
||||
<sl-icon name="upload-2-fill" slot="prefix"></sl-icon>
|
||||
</sl-button>
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package view
|
||||
package inputs
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func allocationView(data any) templ.Component {
|
||||
func InputAvatar(value string, helpText 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 {
|
||||
@@ -29,7 +29,7 @@ func allocationView(data any) templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div><h1>Allocation</h1></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<input type=\"file\" name=\"avatar\" id=\"avatar\" name=\"avatar\" accept=\"image/*\"> <sl-button variant=\"neutral\" slot=\"suffix\" type=\"button\"><sl-icon name=\"upload-2-fill\" slot=\"prefix\"></sl-icon></sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
9
components/inputs/input_bio.templ
Normal file
9
components/inputs/input_bio.templ
Normal file
@@ -0,0 +1,9 @@
|
||||
package inputs
|
||||
|
||||
templ InputBio(value string, helpText string) {
|
||||
<sl-textarea name="bio" placeholder="Bio" type="text" label="Bio" minlength="4" maxlength="12" required class="border-red-500" value={ value } help-text={ helpText }>
|
||||
<div slot="prefix">
|
||||
<sl-icon name="at-sign" library="sonr"></sl-icon>
|
||||
</div>
|
||||
</sl-textarea>
|
||||
}
|
||||
66
components/inputs/input_bio_templ.go
Normal file
66
components/inputs/input_bio_templ.go
Normal file
@@ -0,0 +1,66 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package inputs
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func InputBio(value string, helpText 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_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<sl-textarea name=\"bio\" placeholder=\"Bio\" type=\"text\" label=\"Bio\" minlength=\"4\" maxlength=\"12\" required class=\"border-red-500\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(value)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/inputs/input_bio.templ`, Line: 4, Col: 141}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\" help-text=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(helpText)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/inputs/input_bio.templ`, Line: 4, Col: 164}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\"><div slot=\"prefix\"><sl-icon name=\"at-sign\" library=\"sonr\"></sl-icon></div></sl-textarea>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
33
components/inputs/input_handle.templ
Normal file
33
components/inputs/input_handle.templ
Normal file
@@ -0,0 +1,33 @@
|
||||
package inputs
|
||||
|
||||
templ HandleInitial() {
|
||||
<div hx-target="this" hx-swap="outerHTML">
|
||||
<sl-input name="handle" placeholder="digitalgold" type="text" label="Handle" minlength="4" maxlength="12" required hx-post="/register/profile" hx-indicator="#handle-indicator" autofocus>
|
||||
<div slot="prefix">
|
||||
<sl-icon name="at-sign" library="sonr"></sl-icon>
|
||||
</div>
|
||||
</sl-input>
|
||||
</div>
|
||||
<br/>
|
||||
}
|
||||
|
||||
templ HandleError(value string, helpText string) {
|
||||
<sl-input name="handle" placeholder="digitalgold" type="text" label="Handle" minlength="4" maxlength="12" required class="border-red-500" value={ value } help-text={ helpText }>
|
||||
<div slot="prefix">
|
||||
<sl-icon name="at-sign" library="sonr"></sl-icon>
|
||||
</div>
|
||||
<div slot="suffix" style="color: #B54549;">
|
||||
<sl-icon name="x"></sl-icon>
|
||||
</div>
|
||||
</sl-input>
|
||||
<br/>
|
||||
}
|
||||
|
||||
templ HandleSuccess(value string) {
|
||||
<sl-input name="handle" placeholder="digitalgold" type="text" label="Handle" minlength="4" maxlength="12" required class="border-green-500" value={ value } disabled>
|
||||
<div slot="prefix" style="color: #46A758;">
|
||||
<sl-icon name="at-sign" library="sonr"></sl-icon>
|
||||
</div>
|
||||
</sl-input>
|
||||
<br/>
|
||||
}
|
||||
137
components/inputs/input_handle_templ.go
Normal file
137
components/inputs/input_handle_templ.go
Normal file
@@ -0,0 +1,137 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package inputs
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func HandleInitial() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div hx-target=\"this\" hx-swap=\"outerHTML\"><sl-input name=\"handle\" placeholder=\"digitalgold\" type=\"text\" label=\"Handle\" minlength=\"4\" maxlength=\"12\" required hx-post=\"/register/profile\" hx-indicator=\"#handle-indicator\" autofocus><div slot=\"prefix\"><sl-icon name=\"at-sign\" library=\"sonr\"></sl-icon></div></sl-input></div><br>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func HandleError(value string, helpText 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_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<sl-input name=\"handle\" placeholder=\"digitalgold\" type=\"text\" label=\"Handle\" minlength=\"4\" maxlength=\"12\" required class=\"border-red-500\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(value)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/inputs/input_handle.templ`, Line: 15, Col: 152}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "\" help-text=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(helpText)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/inputs/input_handle.templ`, Line: 15, Col: 175}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"><div slot=\"prefix\"><sl-icon name=\"at-sign\" library=\"sonr\"></sl-icon></div><div slot=\"suffix\" style=\"color: #B54549;\"><sl-icon name=\"x\"></sl-icon></div></sl-input><br>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func HandleSuccess(value 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_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<sl-input name=\"handle\" placeholder=\"digitalgold\" type=\"text\" label=\"Handle\" minlength=\"4\" maxlength=\"12\" required class=\"border-green-500\" value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(value)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/inputs/input_handle.templ`, Line: 27, Col: 154}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\" disabled><div slot=\"prefix\" style=\"color: #46A758;\"><sl-icon name=\"at-sign\" library=\"sonr\"></sl-icon></div></sl-input><br>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
111
components/inputs/input_passkey.templ
Normal file
111
components/inputs/input_passkey.templ
Normal file
@@ -0,0 +1,111 @@
|
||||
package inputs
|
||||
|
||||
templ PasskeyInitial(clickHandler templ.ComponentScript) {
|
||||
<sl-button style="width: 100%;" onclick={ clickHandler }>
|
||||
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-neutral-500"></sl-icon>
|
||||
Register Passkey
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
templ PasskeyError(clickHandler templ.ComponentScript) {
|
||||
<sl-button style="width: 100%;" onclick={ clickHandler }>
|
||||
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-red-500"></sl-icon>
|
||||
Register Passkey
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
templ PasskeySuccess(clickHandler templ.ComponentScript) {
|
||||
<sl-button style="width: 100%;" onclick={ clickHandler }>
|
||||
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-green-500"></sl-icon>
|
||||
Register Passkey
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
script NavigatorCredentialsCreate(userId string, userHandle string, challenge string) {
|
||||
const publicKey = {
|
||||
challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
|
||||
rp: {
|
||||
name: "Sonr.ID",
|
||||
},
|
||||
user: {
|
||||
// Assuming that userId is ASCII-only
|
||||
id: Uint8Array.from(userId, (c) => c.charCodeAt(0)),
|
||||
name: userId,
|
||||
displayName: userHandle,
|
||||
},
|
||||
pubKeyCredParams: [
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -7, // "ES256"
|
||||
},
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -257, // "RS256"
|
||||
},
|
||||
],
|
||||
authenticatorSelection: {
|
||||
userVerification: "required",
|
||||
residentKey: "required",
|
||||
authenticatorAttachment: "platform",
|
||||
},
|
||||
timeout: 60000, // 1 minute
|
||||
extensions: {
|
||||
payment: {
|
||||
isPayment: true,
|
||||
},
|
||||
largeBlob: {
|
||||
supported: "preferred",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Helper function to convert ArrayBuffer to Base64URL string
|
||||
function arrayBufferToBase64URL(buffer) {
|
||||
const bytes = new Uint8Array(buffer);
|
||||
let str = '';
|
||||
bytes.forEach(byte => { str += String.fromCharCode(byte) });
|
||||
return btoa(str)
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=/g, '');
|
||||
}
|
||||
|
||||
navigator.credentials
|
||||
.create({ publicKey })
|
||||
.then((newCredentialInfo) => {
|
||||
if (!(newCredentialInfo instanceof PublicKeyCredential)) {
|
||||
throw new Error('Received credential is not a PublicKeyCredential');
|
||||
}
|
||||
|
||||
const response = newCredentialInfo.response;
|
||||
if (!(response instanceof AuthenticatorAttestationResponse)) {
|
||||
throw new Error('Response is not an AuthenticatorAttestationResponse');
|
||||
}
|
||||
|
||||
// Convert the credential data to a cross-platform compatible format
|
||||
const credentialJSON = {
|
||||
id: newCredentialInfo.id,
|
||||
rawId: arrayBufferToBase64URL(newCredentialInfo.rawId),
|
||||
type: newCredentialInfo.type,
|
||||
authenticatorAttachment: newCredentialInfo.authenticatorAttachment || null,
|
||||
transports: Array.isArray(response.getTransports) ? response.getTransports() : [],
|
||||
clientExtensionResults: newCredentialInfo.getClientExtensionResults(),
|
||||
response: {
|
||||
attestationObject: arrayBufferToBase64URL(response.attestationObject),
|
||||
clientDataJSON: arrayBufferToBase64URL(response.clientDataJSON)
|
||||
}
|
||||
};
|
||||
|
||||
// Set the form value with the stringified credential data
|
||||
const credential = document.getElementById('credential-data');
|
||||
credential.value = JSON.stringify(credentialJSON);
|
||||
|
||||
// Submit the form
|
||||
const form = document.getElementById('passkey-form');
|
||||
form.submit();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Passkey creation failed:', err);
|
||||
alert(`Failed to create passkey: ${err.message || 'Unknown error'}`);
|
||||
});
|
||||
}
|
||||
232
components/inputs/input_passkey_templ.go
Normal file
232
components/inputs/input_passkey_templ.go
Normal file
@@ -0,0 +1,232 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package inputs
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func PasskeyInitial(clickHandler templ.ComponentScript) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, clickHandler)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<sl-button style=\"width: 100%;\" onclick=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 templ.ComponentScript = clickHandler
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"><sl-icon slot=\"prefix\" name=\"passkey\" library=\"sonr\" style=\"font-size: 24px;\" class=\"text-neutral-500\"></sl-icon> Register Passkey</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func PasskeyError(clickHandler templ.ComponentScript) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, clickHandler)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<sl-button style=\"width: 100%;\" onclick=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 templ.ComponentScript = clickHandler
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"><sl-icon slot=\"prefix\" name=\"passkey\" library=\"sonr\" style=\"font-size: 24px;\" class=\"text-red-500\"></sl-icon> Register Passkey</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func PasskeySuccess(clickHandler templ.ComponentScript) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, clickHandler)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<sl-button style=\"width: 100%;\" onclick=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 templ.ComponentScript = clickHandler
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\"><sl-icon slot=\"prefix\" name=\"passkey\" library=\"sonr\" style=\"font-size: 24px;\" class=\"text-green-500\"></sl-icon> Register Passkey</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func NavigatorCredentialsCreate(userId string, userHandle string, challenge string) templ.ComponentScript {
|
||||
return templ.ComponentScript{
|
||||
Name: `__templ_NavigatorCredentialsCreate_8f96`,
|
||||
Function: `function __templ_NavigatorCredentialsCreate_8f96(userId, userHandle, challenge){const publicKey = {
|
||||
challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
|
||||
rp: {
|
||||
name: "Sonr.ID",
|
||||
},
|
||||
user: {
|
||||
// Assuming that userId is ASCII-only
|
||||
id: Uint8Array.from(userId, (c) => c.charCodeAt(0)),
|
||||
name: userId,
|
||||
displayName: userHandle,
|
||||
},
|
||||
pubKeyCredParams: [
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -7, // "ES256"
|
||||
},
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -257, // "RS256"
|
||||
},
|
||||
],
|
||||
authenticatorSelection: {
|
||||
userVerification: "required",
|
||||
residentKey: "required",
|
||||
authenticatorAttachment: "platform",
|
||||
},
|
||||
timeout: 60000, // 1 minute
|
||||
extensions: {
|
||||
payment: {
|
||||
isPayment: true,
|
||||
},
|
||||
largeBlob: {
|
||||
supported: "preferred",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Helper function to convert ArrayBuffer to Base64URL string
|
||||
function arrayBufferToBase64URL(buffer) {
|
||||
const bytes = new Uint8Array(buffer);
|
||||
let str = '';
|
||||
bytes.forEach(byte => { str += String.fromCharCode(byte) });
|
||||
return btoa(str)
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=/g, '');
|
||||
}
|
||||
|
||||
navigator.credentials
|
||||
.create({ publicKey })
|
||||
.then((newCredentialInfo) => {
|
||||
if (!(newCredentialInfo instanceof PublicKeyCredential)) {
|
||||
throw new Error('Received credential is not a PublicKeyCredential');
|
||||
}
|
||||
|
||||
const response = newCredentialInfo.response;
|
||||
if (!(response instanceof AuthenticatorAttestationResponse)) {
|
||||
throw new Error('Response is not an AuthenticatorAttestationResponse');
|
||||
}
|
||||
|
||||
// Convert the credential data to a cross-platform compatible format
|
||||
const credentialJSON = {
|
||||
id: newCredentialInfo.id,
|
||||
rawId: arrayBufferToBase64URL(newCredentialInfo.rawId),
|
||||
type: newCredentialInfo.type,
|
||||
authenticatorAttachment: newCredentialInfo.authenticatorAttachment || null,
|
||||
transports: Array.isArray(response.getTransports) ? response.getTransports() : [],
|
||||
clientExtensionResults: newCredentialInfo.getClientExtensionResults(),
|
||||
response: {
|
||||
attestationObject: arrayBufferToBase64URL(response.attestationObject),
|
||||
clientDataJSON: arrayBufferToBase64URL(response.clientDataJSON)
|
||||
}
|
||||
};
|
||||
|
||||
// Set the form value with the stringified credential data
|
||||
const credential = document.getElementById('credential-data');
|
||||
credential.value = JSON.stringify(credentialJSON);
|
||||
|
||||
// Submit the form
|
||||
const form = document.getElementById('passkey-form');
|
||||
form.submit();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Passkey creation failed:', err);
|
||||
alert(` + "`" + `Failed to create passkey: ${err.message || 'Unknown error'}` + "`" + `);
|
||||
});
|
||||
}`,
|
||||
Call: templ.SafeScript(`__templ_NavigatorCredentialsCreate_8f96`, userId, userHandle, challenge),
|
||||
CallInline: templ.SafeScriptInline(`__templ_NavigatorCredentialsCreate_8f96`, userId, userHandle, challenge),
|
||||
}
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
37
components/menus/assets_dropdown.templ
Normal file
37
components/menus/assets_dropdown.templ
Normal file
@@ -0,0 +1,37 @@
|
||||
package wallet
|
||||
|
||||
templ AssetsDropdown() {
|
||||
<sl-select
|
||||
label="Accounts"
|
||||
name="select-assets"
|
||||
value="SNR BTC ETH"
|
||||
help-text="Select Blockchains to connect with your Vault"
|
||||
multiple
|
||||
class="custom-tag py-2"
|
||||
>
|
||||
<sl-option value="SNR">
|
||||
<sl-icon slot="prefix" name="SNR" library="crypto"></sl-icon>
|
||||
Sonr
|
||||
</sl-option>
|
||||
<sl-option value="BTC">
|
||||
<sl-icon slot="prefix" name="BTC" library="crypto"></sl-icon>
|
||||
Bitcoin
|
||||
</sl-option>
|
||||
<sl-option value="ETH">
|
||||
<sl-icon slot="prefix" name="ETH" library="crypto"></sl-icon>
|
||||
Ethereum
|
||||
</sl-option>
|
||||
<sl-option value="SOL">
|
||||
<sl-icon slot="prefix" name="SOL" library="crypto"></sl-icon>
|
||||
Solana
|
||||
</sl-option>
|
||||
<sl-option value="LTC">
|
||||
<sl-icon slot="prefix" name="LTC" library="crypto"></sl-icon>
|
||||
Litecoin
|
||||
</sl-option>
|
||||
<sl-option value="DOGE">
|
||||
<sl-icon slot="prefix" name="DOGE" library="crypto"></sl-icon>
|
||||
Dogecoin
|
||||
</sl-option>
|
||||
</sl-select>
|
||||
}
|
||||
40
components/menus/assets_dropdown_templ.go
Normal file
40
components/menus/assets_dropdown_templ.go
Normal file
@@ -0,0 +1,40 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package wallet
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func AssetsDropdown() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<sl-select label=\"Accounts\" name=\"select-assets\" value=\"SNR BTC ETH\" help-text=\"Select Blockchains to connect with your Vault\" multiple class=\"custom-tag py-2\"><sl-option value=\"SNR\"><sl-icon slot=\"prefix\" name=\"SNR\" library=\"crypto\"></sl-icon> Sonr</sl-option> <sl-option value=\"BTC\"><sl-icon slot=\"prefix\" name=\"BTC\" library=\"crypto\"></sl-icon> Bitcoin</sl-option> <sl-option value=\"ETH\"><sl-icon slot=\"prefix\" name=\"ETH\" library=\"crypto\"></sl-icon> Ethereum</sl-option> <sl-option value=\"SOL\"><sl-icon slot=\"prefix\" name=\"SOL\" library=\"crypto\"></sl-icon> Solana</sl-option> <sl-option value=\"LTC\"><sl-icon slot=\"prefix\" name=\"LTC\" library=\"crypto\"></sl-icon> Litecoin</sl-option> <sl-option value=\"DOGE\"><sl-icon slot=\"prefix\" name=\"DOGE\" library=\"crypto\"></sl-icon> Dogecoin</sl-option></sl-select>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
67
components/menus/coins_dropdown.templ
Normal file
67
components/menus/coins_dropdown.templ
Normal file
@@ -0,0 +1,67 @@
|
||||
package wallet
|
||||
|
||||
type CoinInfo struct {
|
||||
Ticker string
|
||||
Name string
|
||||
IsDefault bool
|
||||
}
|
||||
|
||||
var defaultCoins = []CoinInfo{
|
||||
{Ticker: "SNR", Name: "Sonr", IsDefault: true},
|
||||
{Ticker: "BTC", Name: "Bitcoin", IsDefault: true},
|
||||
{Ticker: "ETH", Name: "Ethereum", IsDefault: true},
|
||||
{Ticker: "SOL", Name: "Solana", IsDefault: false},
|
||||
{Ticker: "LTC", Name: "Litecoin", IsDefault: false},
|
||||
{Ticker: "DOGE", Name: "Dogecoin", IsDefault: false},
|
||||
{Ticker: "XRP", Name: "Ripple", IsDefault: false},
|
||||
{Ticker: "OSMO", Name: "Osmosis", IsDefault: false},
|
||||
{Ticker: "ATOM", Name: "Cosmos", IsDefault: false},
|
||||
{Ticker: "STARZ", Name: "Stargaze", IsDefault: false},
|
||||
{Ticker: "AKT", Name: "Akash", IsDefault: false},
|
||||
{Ticker: "EVMOS", Name: "Evmos", IsDefault: false},
|
||||
{Ticker: "FIL", Name: "Filecoin", IsDefault: false},
|
||||
{Ticker: "AXL", Name: "Axelar", IsDefault: false},
|
||||
}
|
||||
|
||||
templ CoinsDropdown() {
|
||||
<sl-select
|
||||
label="Accounts"
|
||||
name="selected_assets"
|
||||
value="SNR BTC ETH"
|
||||
help-text="Select Blockchains to connect with your Vault"
|
||||
multiple
|
||||
class="custom-tag py-2"
|
||||
>
|
||||
for _, a := range defaultCoins {
|
||||
@CoinOption(a)
|
||||
}
|
||||
</sl-select>
|
||||
<script>
|
||||
const select = document.querySelector('.custom-tag');
|
||||
select.getTag = (option, index) => {
|
||||
const name = option.querySelector('sl-icon[slot="prefix"]').name;
|
||||
return `
|
||||
<sl-tag removable>
|
||||
<sl-icon name="${name}" library="crypto" style="padding-inline-end: .5rem;"></sl-icon>
|
||||
${option.getTextLabel()}
|
||||
</sl-tag>
|
||||
`;
|
||||
};
|
||||
</script>
|
||||
}
|
||||
|
||||
templ CoinOption(a CoinInfo) {
|
||||
if a.IsDefault {
|
||||
<sl-option value={ a.Ticker } selected disabled>
|
||||
<sl-icon slot="prefix" name={ a.Ticker } library="crypto"></sl-icon>
|
||||
{ a.Name }
|
||||
</sl-option>
|
||||
<sl-divider></sl-divider>
|
||||
} else {
|
||||
<sl-option value={ a.Ticker }>
|
||||
<sl-icon slot="prefix" name={ a.Ticker } library="crypto"></sl-icon>
|
||||
{ a.Name }
|
||||
</sl-option>
|
||||
<sl-divider></sl-divider>
|
||||
}
|
||||
}
|
||||
187
components/menus/coins_dropdown_templ.go
Normal file
187
components/menus/coins_dropdown_templ.go
Normal file
@@ -0,0 +1,187 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package wallet
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
type CoinInfo struct {
|
||||
Ticker string
|
||||
Name string
|
||||
IsDefault bool
|
||||
}
|
||||
|
||||
var defaultCoins = []CoinInfo{
|
||||
{Ticker: "SNR", Name: "Sonr", IsDefault: true},
|
||||
{Ticker: "BTC", Name: "Bitcoin", IsDefault: true},
|
||||
{Ticker: "ETH", Name: "Ethereum", IsDefault: true},
|
||||
{Ticker: "SOL", Name: "Solana", IsDefault: false},
|
||||
{Ticker: "LTC", Name: "Litecoin", IsDefault: false},
|
||||
{Ticker: "DOGE", Name: "Dogecoin", IsDefault: false},
|
||||
{Ticker: "XRP", Name: "Ripple", IsDefault: false},
|
||||
{Ticker: "OSMO", Name: "Osmosis", IsDefault: false},
|
||||
{Ticker: "ATOM", Name: "Cosmos", IsDefault: false},
|
||||
{Ticker: "STARZ", Name: "Stargaze", IsDefault: false},
|
||||
{Ticker: "AKT", Name: "Akash", IsDefault: false},
|
||||
{Ticker: "EVMOS", Name: "Evmos", IsDefault: false},
|
||||
{Ticker: "FIL", Name: "Filecoin", IsDefault: false},
|
||||
{Ticker: "AXL", Name: "Axelar", IsDefault: false},
|
||||
}
|
||||
|
||||
func CoinsDropdown() templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<sl-select label=\"Accounts\" name=\"selected_assets\" value=\"SNR BTC ETH\" help-text=\"Select Blockchains to connect with your Vault\" multiple class=\"custom-tag py-2\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, a := range defaultCoins {
|
||||
templ_7745c5c3_Err = CoinOption(a).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</sl-select><script>\n\t const select = document.querySelector('.custom-tag');\n select.getTag = (option, index) => {\n const name = option.querySelector('sl-icon[slot=\"prefix\"]').name;\n return `\n <sl-tag removable>\n <sl-icon name=\"${name}\" library=\"crypto\" style=\"padding-inline-end: .5rem;\"></sl-icon>\n ${option.getTextLabel()}\n </sl-tag>\n `;\n };\n\t</script>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func CoinOption(a CoinInfo) 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_Var2 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var2 == nil {
|
||||
templ_7745c5c3_Var2 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
if a.IsDefault {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<sl-option value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(a.Ticker)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/menus/coins_dropdown.templ`, Line: 55, Col: 29}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\" selected disabled><sl-icon slot=\"prefix\" name=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(a.Ticker)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/menus/coins_dropdown.templ`, Line: 56, Col: 41}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "\" library=\"crypto\"></sl-icon> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(a.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/menus/coins_dropdown.templ`, Line: 57, Col: 11}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</sl-option> <sl-divider></sl-divider>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
} else {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "<sl-option value=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 string
|
||||
templ_7745c5c3_Var6, templ_7745c5c3_Err = templ.JoinStringErrs(a.Ticker)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/menus/coins_dropdown.templ`, Line: 61, Col: 29}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var6))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "\"><sl-icon slot=\"prefix\" name=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(a.Ticker)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/menus/coins_dropdown.templ`, Line: 62, Col: 41}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "\" library=\"crypto\"></sl-icon> ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var8 string
|
||||
templ_7745c5c3_Var8, templ_7745c5c3_Err = templ.JoinStringErrs(a.Name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `components/menus/coins_dropdown.templ`, Line: 63, Col: 11}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var8))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</sl-option> <sl-divider></sl-divider>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
91
components/views/console.templ
Normal file
91
components/views/console.templ
Normal file
@@ -0,0 +1,91 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/sonr-io/motr/internal/ui"
|
||||
"github.com/sonr-io/motr/components/dashboard"
|
||||
"time"
|
||||
)
|
||||
|
||||
var heliaCardScriptHandle = templ.NewOnceHandle()
|
||||
|
||||
func DemoView(d time.Time) templ.Component {
|
||||
return demoComponent(d)
|
||||
}
|
||||
|
||||
templ demoComponent(d time.Time) {
|
||||
@ui.HTML() {
|
||||
@ui.Head() {
|
||||
}
|
||||
<sl-tab-group>
|
||||
@ui.Nav() {
|
||||
@ui.NavLeft() {
|
||||
@ui.NavLogo("Motr")
|
||||
}
|
||||
@ui.NavRight() {
|
||||
<sl-tab slot="nav" panel="tab-1">Time</sl-tab>
|
||||
}
|
||||
}
|
||||
@ui.Body() {
|
||||
<sl-tab-panel name="tab-1" active>
|
||||
@ui.Container() {
|
||||
<div class="space-y-6">
|
||||
<div class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4">
|
||||
@dashboard.HeliaStatusCard()
|
||||
@dashboard.HeliaNodeIDCard()
|
||||
@dashboard.HeliaDiscoveredPeersCard()
|
||||
@dashboard.HeliaConnectedPeersCard()
|
||||
</div>
|
||||
<div class="grid grid-cols-1 lg:grid-cols-2 gap-4">
|
||||
@dashboard.HeliaConnectedPeersList()
|
||||
@dashboard.HeliaRunningLog()
|
||||
</div>
|
||||
@heliaCardScriptHandle.Once() {
|
||||
<script>
|
||||
document.addEventListener('DOMContentLoaded', async () => {
|
||||
try {
|
||||
// Use the globally available instantiateHeliaNode function
|
||||
const helia = window.helia = await window.instantiateHeliaNode()
|
||||
window.heliaFs = await HeliaUnixfs.unixfs(helia)
|
||||
|
||||
helia.libp2p.addEventListener('peer:discovery', (evt) => {
|
||||
window.discoveredPeers.set(evt.detail.id.toString(), evt.detail)
|
||||
addToLog(`Discovered peer ${evt.detail.id.toString()}`)
|
||||
})
|
||||
|
||||
helia.libp2p.addEventListener('peer:connect', (evt) => {
|
||||
addToLog(`Connected to ${evt.detail.toString()}`)
|
||||
})
|
||||
|
||||
helia.libp2p.addEventListener('peer:disconnect', (evt) => {
|
||||
addToLog(`Disconnected from ${evt.detail.toString()}`)
|
||||
})
|
||||
|
||||
setInterval(() => {
|
||||
const statusValueEl = document.getElementById('statusValue')
|
||||
if (statusValueEl) {
|
||||
statusValueEl.innerHTML = helia.libp2p.status === 'started' ? 'Online' : 'Offline'
|
||||
}
|
||||
updateConnectedPeers()
|
||||
updateDiscoveredPeers()
|
||||
}, 500)
|
||||
|
||||
const id = await helia.libp2p.peerId.toString()
|
||||
const nodeIdEl = document.getElementById('nodeId')
|
||||
if (nodeIdEl) {
|
||||
nodeIdEl.innerHTML = id
|
||||
}
|
||||
addToLog('Helia node initialized successfully')
|
||||
} catch (err) {
|
||||
addToLog(`Error initializing Helia: ${err.message}`)
|
||||
console.error('Error initializing Helia:', err)
|
||||
}
|
||||
})
|
||||
</script>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
</sl-tab-panel>
|
||||
}
|
||||
</sl-tab-group>
|
||||
}
|
||||
}
|
||||
264
components/views/console_templ.go
Normal file
264
components/views/console_templ.go
Normal file
@@ -0,0 +1,264 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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/sonr-io/motr/components/dashboard"
|
||||
"github.com/sonr-io/motr/internal/ui"
|
||||
"time"
|
||||
)
|
||||
|
||||
var heliaCardScriptHandle = templ.NewOnceHandle()
|
||||
|
||||
func DemoView(d time.Time) templ.Component {
|
||||
return demoComponent(d)
|
||||
}
|
||||
|
||||
func demoComponent(d time.Time) 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)
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Head().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <sl-tab-group>")
|
||||
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_Err = ui.NavLogo("Motr").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavLeft().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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 = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<sl-tab slot=\"nav\" panel=\"tab-1\">Time</sl-tab>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavRight().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Nav().Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
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 = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "<sl-tab-panel name=\"tab-1\" active>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<div class=\"space-y-6\"><div class=\"grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-4 gap-4\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = dashboard.HeliaStatusCard().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = dashboard.HeliaNodeIDCard().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = dashboard.HeliaDiscoveredPeersCard().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = dashboard.HeliaConnectedPeersCard().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "</div><div class=\"grid grid-cols-1 lg:grid-cols-2 gap-4\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = dashboard.HeliaConnectedPeersList().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = dashboard.HeliaRunningLog().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<script>\n document.addEventListener('DOMContentLoaded', async () => {\n try {\n // Use the globally available instantiateHeliaNode function\n const helia = window.helia = await window.instantiateHeliaNode()\n window.heliaFs = await HeliaUnixfs.unixfs(helia)\n\n helia.libp2p.addEventListener('peer:discovery', (evt) => {\n window.discoveredPeers.set(evt.detail.id.toString(), evt.detail)\n addToLog(`Discovered peer ${evt.detail.id.toString()}`)\n })\n\n helia.libp2p.addEventListener('peer:connect', (evt) => {\n addToLog(`Connected to ${evt.detail.toString()}`)\n })\n \n helia.libp2p.addEventListener('peer:disconnect', (evt) => {\n addToLog(`Disconnected from ${evt.detail.toString()}`)\n })\n\n setInterval(() => {\n const statusValueEl = document.getElementById('statusValue')\n if (statusValueEl) {\n statusValueEl.innerHTML = helia.libp2p.status === 'started' ? 'Online' : 'Offline'\n }\n updateConnectedPeers()\n updateDiscoveredPeers()\n }, 500)\n\n const id = await helia.libp2p.peerId.toString()\n const nodeIdEl = document.getElementById('nodeId')\n if (nodeIdEl) {\n nodeIdEl.innerHTML = id\n }\n addToLog('Helia node initialized successfully')\n } catch (err) {\n addToLog(`Error initializing Helia: ${err.message}`)\n console.error('Error initializing Helia:', err)\n }\n })\n </script>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = heliaCardScriptHandle.Once().Render(templ.WithChildren(ctx, templ_7745c5c3_Var9), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 10, "</sl-tab-panel>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 11, "</sl-tab-group>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.HTML().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
48
components/views/home.templ
Normal file
48
components/views/home.templ
Normal file
@@ -0,0 +1,48 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/sonr-io/motr/internal/sink"
|
||||
"github.com/sonr-io/motr/internal/ui"
|
||||
)
|
||||
|
||||
var meta = sink.DefaultMetadata()
|
||||
|
||||
func HomeView() templ.Component {
|
||||
return homeComponent()
|
||||
}
|
||||
|
||||
templ homeComponent() {
|
||||
@ui.HTML() {
|
||||
@ui.Head() {
|
||||
@ui.MetaComponent(meta)
|
||||
}
|
||||
<sl-tab-group>
|
||||
@ui.Nav() {
|
||||
@ui.NavLeft() {
|
||||
@ui.NavLogo("Motr")
|
||||
}
|
||||
@ui.NavRight() {
|
||||
}
|
||||
}
|
||||
@ui.Body() {
|
||||
@ui.Container() {
|
||||
<sl-card>
|
||||
<div slot="header">
|
||||
<h3 class="card-title">Welcome to Motr</h3>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<p>This is a demo of the Motr web app.</p>
|
||||
<p>You can use this app to manage your Motr account.</p>
|
||||
</div>
|
||||
<div class="card-footer">
|
||||
<sl-button type="primary" size="large" href="/register">
|
||||
<sl-icon slot="prefix" library="sonr" name="passkey"></sl-icon>
|
||||
Register
|
||||
</sl-button>
|
||||
</div>
|
||||
</sl-card>
|
||||
}
|
||||
}
|
||||
</sl-tab-group>
|
||||
}
|
||||
}
|
||||
197
components/views/home_templ.go
Normal file
197
components/views/home_templ.go
Normal file
@@ -0,0 +1,197 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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/sonr-io/motr/internal/sink"
|
||||
"github.com/sonr-io/motr/internal/ui"
|
||||
)
|
||||
|
||||
var meta = sink.DefaultMetadata()
|
||||
|
||||
func HomeView() templ.Component {
|
||||
return homeComponent()
|
||||
}
|
||||
|
||||
func homeComponent() 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 = ui.MetaComponent(meta).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Head().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <sl-tab-group>")
|
||||
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_Err = ui.NavLogo("Motr").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavLeft().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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)
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavRight().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Nav().Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
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_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<sl-card><div slot=\"header\"><h3 class=\"card-title\">Welcome to Motr</h3></div><div class=\"card-body\"><p>This is a demo of the Motr web app.</p><p>You can use this app to manage your Motr account.</p></div><div class=\"card-footer\"><sl-button type=\"primary\" size=\"large\" href=\"/register\"><sl-icon slot=\"prefix\" library=\"sonr\" name=\"passkey\"></sl-icon> Register</sl-button></div></sl-card>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</sl-tab-group>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.HTML().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
25
components/views/login.templ
Normal file
25
components/views/login.templ
Normal file
@@ -0,0 +1,25 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/sonr-io/motr/internal/ui"
|
||||
)
|
||||
|
||||
templ LoginView() {
|
||||
@ui.HTML() {
|
||||
@ui.Head() {
|
||||
@ui.MetaComponent(meta)
|
||||
}
|
||||
<sl-tab-group>
|
||||
@ui.Nav() {
|
||||
@ui.NavLeft() {
|
||||
@ui.NavLogo("Motr")
|
||||
}
|
||||
@ui.NavRight() {
|
||||
}
|
||||
}
|
||||
@ui.Body() {
|
||||
}
|
||||
</sl-tab-group>
|
||||
}
|
||||
}
|
||||
|
||||
168
components/views/login_templ.go
Normal file
168
components/views/login_templ.go
Normal file
@@ -0,0 +1,168 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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/sonr-io/motr/internal/ui"
|
||||
)
|
||||
|
||||
func LoginView() 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 = ui.MetaComponent(meta).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Head().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <sl-tab-group>")
|
||||
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_Err = ui.NavLogo("Motr").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavLeft().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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)
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavRight().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Nav().Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
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)
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</sl-tab-group>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.HTML().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
28
components/views/register.templ
Normal file
28
components/views/register.templ
Normal file
@@ -0,0 +1,28 @@
|
||||
package views
|
||||
|
||||
import (
|
||||
"github.com/sonr-io/motr/internal/ui"
|
||||
"github.com/sonr-io/motr/components/inputs"
|
||||
)
|
||||
|
||||
templ RegisterView() {
|
||||
@ui.HTML() {
|
||||
@ui.Head() {
|
||||
@ui.MetaComponent(meta)
|
||||
}
|
||||
<sl-tab-group>
|
||||
@ui.Nav() {
|
||||
@ui.NavLeft() {
|
||||
@ui.NavLogo("Motr")
|
||||
}
|
||||
@ui.NavRight() {
|
||||
}
|
||||
}
|
||||
@ui.Body() {
|
||||
@ui.Container() {
|
||||
@inputs.HandleInitial()
|
||||
}
|
||||
}
|
||||
</sl-tab-group>
|
||||
}
|
||||
}
|
||||
191
components/views/register_templ.go
Normal file
191
components/views/register_templ.go
Normal file
@@ -0,0 +1,191 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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/sonr-io/motr/components/inputs"
|
||||
"github.com/sonr-io/motr/internal/ui"
|
||||
)
|
||||
|
||||
func RegisterView() 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 = ui.MetaComponent(meta).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Head().Render(templ.WithChildren(ctx, templ_7745c5c3_Var3), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, " <sl-tab-group>")
|
||||
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_Err = ui.NavLogo("Motr").Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavLeft().Render(templ.WithChildren(ctx, templ_7745c5c3_Var5), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, " ")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
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)
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.NavRight().Render(templ.WithChildren(ctx, templ_7745c5c3_Var6), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Nav().Render(templ.WithChildren(ctx, templ_7745c5c3_Var4), templ_7745c5c3_Buffer)
|
||||
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_Var8 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Err = inputs.HandleInitial().Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Container().Render(templ.WithChildren(ctx, templ_7745c5c3_Var8), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.Body().Render(templ.WithChildren(ctx, templ_7745c5c3_Var7), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</sl-tab-group>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
templ_7745c5c3_Err = ui.HTML().Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
48
controllers/account/card.templ
Normal file
48
controllers/account/card.templ
Normal file
@@ -0,0 +1,48 @@
|
||||
package account
|
||||
|
||||
import "github.com/sonr-io/motr/internal/sink/models"
|
||||
|
||||
templ cardComponent(handle, addr, block, name string) {
|
||||
<div class="profile-card min-w-[320px]">
|
||||
<div class="text-white max-w-xs my-auto mx-auto bg-gradient-to-r from-cyan-600 to-cyan-300 p-4 py-5 px-5 rounded-xl">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<h2>sonr-testnet-1</h2>
|
||||
<p class="text-2xl font-bold">{ handle }</p>
|
||||
</div>
|
||||
<div class="flex items-center opacity-60">
|
||||
<sl-icon style="font-size: 52px;" library="sonr" name="sonr-fill"></sl-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 flex justify-between items-center w-52">
|
||||
<span class="text-lg font-mono">{ addr }</span>
|
||||
</div>
|
||||
<div class="flex justify-between mt-5 w-48 ">
|
||||
<div>
|
||||
<h3 class="text-xs">Block Created </h3>
|
||||
<p class="font-bold"><span>#</span>{ block }</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xs">Issued to</h3>
|
||||
<p class="font-bold">{ name }</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
// option is a single option in the dropdown
|
||||
templ optionComponent(account models.Account) {
|
||||
<div class="flex justify-between items-center">
|
||||
{ account.Address }
|
||||
<sl-icon style="font-size: 24px;" library="sonr" name="chevron-right"></sl-icon>
|
||||
</div>
|
||||
}
|
||||
|
||||
// row is a single row in the list with a basic card
|
||||
templ rowComponent(account models.Account) {
|
||||
<div class="flex justify-between items-center">
|
||||
{ account.Address }
|
||||
<sl-icon style="font-size: 24px;" library="sonr" name="chevron-right"></sl-icon>
|
||||
</div>
|
||||
}
|
||||
180
controllers/account/card_templ.go
Normal file
180
controllers/account/card_templ.go
Normal file
@@ -0,0 +1,180 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package account
|
||||
|
||||
//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/sonr-io/motr/internal/sink/models"
|
||||
|
||||
func cardComponent(handle, addr, block, name 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_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"profile-card min-w-[320px]\"><div class=\"text-white max-w-xs my-auto mx-auto bg-gradient-to-r from-cyan-600 to-cyan-300 p-4 py-5 px-5 rounded-xl\"><div class=\"flex justify-between\"><div><h2>sonr-testnet-1</h2><p class=\"text-2xl font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(handle)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/account/card.templ`, Line: 11, Col: 43}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</p></div><div class=\"flex items-center opacity-60\"><sl-icon style=\"font-size: 52px;\" library=\"sonr\" name=\"sonr-fill\"></sl-icon></div></div><div class=\"mt-5 flex justify-between items-center w-52\"><span class=\"text-lg font-mono\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(addr)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/account/card.templ`, Line: 18, Col: 42}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"flex justify-between mt-5 w-48 \"><div><h3 class=\"text-xs\">Block Created </h3><p class=\"font-bold\"><span>#</span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(block)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/account/card.templ`, Line: 23, Col: 47}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div><div><h3 class=\"text-xs\">Issued to</h3><p class=\"font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/account/card.templ`, Line: 27, Col: 32}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</p></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// option is a single option in the dropdown
|
||||
func optionComponent(account models.Account) 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_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"flex justify-between items-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(account.Address)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/account/card.templ`, Line: 37, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " <sl-icon style=\"font-size: 24px;\" library=\"sonr\" name=\"chevron-right\"></sl-icon></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// row is a single row in the list with a basic card
|
||||
func rowComponent(account models.Account) 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_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"flex justify-between items-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(account.Address)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/account/card.templ`, Line: 45, Col: 19}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " <sl-icon style=\"font-size: 24px;\" library=\"sonr\" name=\"chevron-right\"></sl-icon></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
63
controllers/account/entity.go
Normal file
63
controllers/account/entity.go
Normal file
@@ -0,0 +1,63 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type AccountEntity interface {
|
||||
GetModel() models.Account
|
||||
GetCard() templ.Component
|
||||
shortAddr() string
|
||||
}
|
||||
|
||||
type AccountsEntity interface {
|
||||
GetModels() []models.Account
|
||||
GetList() templ.Component
|
||||
GetDropdown() templ.Component
|
||||
}
|
||||
|
||||
func NewAccountEntity(account models.Account) AccountEntity {
|
||||
return &accountEntity{Account: account}
|
||||
}
|
||||
|
||||
func NewAccountsEntity(accounts []models.Account) AccountsEntity {
|
||||
return &accountsEntity{Accounts: accounts}
|
||||
}
|
||||
|
||||
type accountEntity struct {
|
||||
models.Account
|
||||
}
|
||||
|
||||
func (a *accountEntity) shortAddr() string {
|
||||
if len(a.Address) <= 20 {
|
||||
return a.Address
|
||||
}
|
||||
return a.Address[:16] + "..." + a.Address[len(a.Address)-4:]
|
||||
}
|
||||
|
||||
func (a *accountEntity) GetModel() models.Account {
|
||||
return a.Account
|
||||
}
|
||||
|
||||
func (a *accountEntity) GetCard() templ.Component {
|
||||
return cardComponent(a.Handle, a.shortAddr(), strconv.FormatInt(a.BlockCreated, 10), a.Label)
|
||||
}
|
||||
|
||||
type accountsEntity struct {
|
||||
Accounts []models.Account
|
||||
}
|
||||
|
||||
func (a *accountsEntity) GetModels() []models.Account {
|
||||
return a.Accounts
|
||||
}
|
||||
|
||||
func (a *accountsEntity) GetList() templ.Component {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *accountsEntity) GetDropdown() templ.Component {
|
||||
return nil
|
||||
}
|
||||
11
controllers/account/list.templ
Normal file
11
controllers/account/list.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package account
|
||||
|
||||
templ listComponent(accounts AccountsEntity) {
|
||||
<div class="flex flex-col gap-4 mt-4">
|
||||
for _,account := range accounts.GetModels() {
|
||||
<div class="flex justify-between items-center">
|
||||
@rowComponent(account)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
58
controllers/account/list_templ.go
Normal file
58
controllers/account/list_templ.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package account
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func listComponent(accounts AccountsEntity) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col gap-4 mt-4\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, account := range accounts.GetModels() {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex justify-between items-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = rowComponent(account).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
32
controllers/account/queries.go
Normal file
32
controllers/account/queries.go
Normal file
@@ -0,0 +1,32 @@
|
||||
package account
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetAccountByID(ctx context.Context, id string) (models.Account, error)
|
||||
GetAccountByAddress(ctx context.Context, address string) (models.Account, error)
|
||||
GetAccountByController(ctx context.Context, controller string) (models.Account, error)
|
||||
GetAccountByPublicKey(ctx context.Context, publicKey string) (models.Account, error)
|
||||
GetAccountByNumber(ctx context.Context, number int64) (models.Account, error)
|
||||
GetAccountBySequence(ctx context.Context, sequence int64) (models.Account, error)
|
||||
GetAccountsByChainID(ctx context.Context, chainID string) ([]models.Account, error)
|
||||
GetAccountsByHandle(ctx context.Context, handle string) ([]models.Account, error)
|
||||
GetAccountsByLabel(ctx context.Context, name string) ([]models.Account, error)
|
||||
UpdateAccountLabel(ctx context.Context, arg models.UpdateAccountLabelParams) (models.Account, error)
|
||||
UpdateAccountSequence(ctx context.Context, arg models.UpdateAccountSequenceParams) (models.Account, error)
|
||||
SoftDeleteAccount(ctx context.Context, id string) error
|
||||
ListValidatorAccounts(ctx context.Context) ([]models.Account, error)
|
||||
ListDelegatorAccounts(ctx context.Context) ([]models.Account, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
11
controllers/account/select.templ
Normal file
11
controllers/account/select.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package account
|
||||
|
||||
templ selectComponent(accounts AccountsEntity) {
|
||||
<div class="flex flex-col gap-4 mt-4">
|
||||
for _,account := range accounts.GetModels() {
|
||||
<div class="flex justify-between items-center">
|
||||
@optionComponent(account)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
58
controllers/account/select_templ.go
Normal file
58
controllers/account/select_templ.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package account
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func selectComponent(accounts AccountsEntity) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col gap-4 mt-4\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, account := range accounts.GetModels() {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex justify-between items-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = optionComponent(account).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
48
controllers/activity/card.templ
Normal file
48
controllers/activity/card.templ
Normal file
@@ -0,0 +1,48 @@
|
||||
package activity
|
||||
|
||||
import "github.com/sonr-io/motr/internal/sink/models"
|
||||
|
||||
templ cardComponent(handle, addr, block, name string) {
|
||||
<div class="profile-card min-w-[320px]">
|
||||
<div class="text-white max-w-xs my-auto mx-auto bg-gradient-to-r from-cyan-600 to-cyan-300 p-4 py-5 px-5 rounded-xl">
|
||||
<div class="flex justify-between">
|
||||
<div>
|
||||
<h2>sonr-testnet-1</h2>
|
||||
<p class="text-2xl font-bold">{ handle }</p>
|
||||
</div>
|
||||
<div class="flex items-center opacity-60">
|
||||
<sl-icon style="font-size: 52px;" library="sonr" name="sonr-fill"></sl-icon>
|
||||
</div>
|
||||
</div>
|
||||
<div class="mt-5 flex justify-between items-center w-52">
|
||||
<span class="text-lg font-mono">{ addr }</span>
|
||||
</div>
|
||||
<div class="flex justify-between mt-5 w-48 ">
|
||||
<div>
|
||||
<h3 class="text-xs">Block Created </h3>
|
||||
<p class="font-bold"><span>#</span>{ block }</p>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-xs">Issued to</h3>
|
||||
<p class="font-bold">{ name }</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
}
|
||||
|
||||
// option is a single option in the dropdown
|
||||
templ optionComponent(account models.Activity) {
|
||||
<div class="flex justify-between items-center">
|
||||
{ account.Status }
|
||||
<sl-icon style="font-size: 24px;" library="sonr" name="chevron-right"></sl-icon>
|
||||
</div>
|
||||
}
|
||||
|
||||
// row is a single row in the list with a basic card
|
||||
templ rowComponent(account models.Activity) {
|
||||
<div class="flex justify-between items-center">
|
||||
{ account.Status }
|
||||
<sl-icon style="font-size: 24px;" library="sonr" name="chevron-right"></sl-icon>
|
||||
</div>
|
||||
}
|
||||
180
controllers/activity/card_templ.go
Normal file
180
controllers/activity/card_templ.go
Normal file
@@ -0,0 +1,180 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package activity
|
||||
|
||||
//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/sonr-io/motr/internal/sink/models"
|
||||
|
||||
func cardComponent(handle, addr, block, name 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_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"profile-card min-w-[320px]\"><div class=\"text-white max-w-xs my-auto mx-auto bg-gradient-to-r from-cyan-600 to-cyan-300 p-4 py-5 px-5 rounded-xl\"><div class=\"flex justify-between\"><div><h2>sonr-testnet-1</h2><p class=\"text-2xl font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 string
|
||||
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(handle)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/activity/card.templ`, Line: 11, Col: 43}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "</p></div><div class=\"flex items-center opacity-60\"><sl-icon style=\"font-size: 52px;\" library=\"sonr\" name=\"sonr-fill\"></sl-icon></div></div><div class=\"mt-5 flex justify-between items-center w-52\"><span class=\"text-lg font-mono\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var3 string
|
||||
templ_7745c5c3_Var3, templ_7745c5c3_Err = templ.JoinStringErrs(addr)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/activity/card.templ`, Line: 18, Col: 42}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var3))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</span></div><div class=\"flex justify-between mt-5 w-48 \"><div><h3 class=\"text-xs\">Block Created </h3><p class=\"font-bold\"><span>#</span>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 string
|
||||
templ_7745c5c3_Var4, templ_7745c5c3_Err = templ.JoinStringErrs(block)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/activity/card.templ`, Line: 23, Col: 47}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var4))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</p></div><div><h3 class=\"text-xs\">Issued to</h3><p class=\"font-bold\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var5 string
|
||||
templ_7745c5c3_Var5, templ_7745c5c3_Err = templ.JoinStringErrs(name)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/activity/card.templ`, Line: 27, Col: 32}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var5))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "</p></div></div></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// option is a single option in the dropdown
|
||||
func optionComponent(account models.Activity) 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_Var6 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var6 == nil {
|
||||
templ_7745c5c3_Var6 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "<div class=\"flex justify-between items-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var7 string
|
||||
templ_7745c5c3_Var7, templ_7745c5c3_Err = templ.JoinStringErrs(account.Status)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/activity/card.templ`, Line: 37, Col: 18}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var7))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 7, " <sl-icon style=\"font-size: 24px;\" library=\"sonr\" name=\"chevron-right\"></sl-icon></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
// row is a single row in the list with a basic card
|
||||
func rowComponent(account models.Activity) 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_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 8, "<div class=\"flex justify-between items-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var9 string
|
||||
templ_7745c5c3_Var9, templ_7745c5c3_Err = templ.JoinStringErrs(account.Status)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ.Error{Err: templ_7745c5c3_Err, FileName: `controllers/activity/card.templ`, Line: 45, Col: 18}
|
||||
}
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var9))
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 9, " <sl-icon style=\"font-size: 24px;\" library=\"sonr\" name=\"chevron-right\"></sl-icon></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
16
controllers/activity/entity.go
Normal file
16
controllers/activity/entity.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package activity
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type ActivityEntity interface {
|
||||
GetModel() models.Activity
|
||||
GetCard() templ.Component
|
||||
}
|
||||
|
||||
type ActivitiesEntity interface {
|
||||
GetModels() []models.Activity
|
||||
GetList() templ.Component
|
||||
}
|
||||
11
controllers/activity/list.templ
Normal file
11
controllers/activity/list.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package activity
|
||||
|
||||
templ listComponent(accounts ActivitiesEntity) {
|
||||
<div class="flex flex-col gap-4 mt-4">
|
||||
for _,account := range accounts.GetModels() {
|
||||
<div class="flex justify-between items-center">
|
||||
@rowComponent(account)
|
||||
</div>
|
||||
}
|
||||
</div>
|
||||
}
|
||||
58
controllers/activity/list_templ.go
Normal file
58
controllers/activity/list_templ.go
Normal file
@@ -0,0 +1,58 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package activity
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func listComponent(accounts ActivitiesEntity) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col gap-4 mt-4\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
for _, account := range accounts.GetModels() {
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "<div class=\"flex justify-between items-center\">")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = rowComponent(account).Render(ctx, templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "</div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
27
controllers/activity/queries.go
Normal file
27
controllers/activity/queries.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package activity
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetActivityByID(ctx context.Context, id string) (models.Activity, error)
|
||||
GetActivityByTxHash(ctx context.Context, txHash sql.NullString) (models.Activity, error)
|
||||
InsertActivity(ctx context.Context, arg models.InsertActivityParams) (models.Activity, error)
|
||||
ListActivitiesByAccount(ctx context.Context, arg models.ListActivitiesByAccountParams) ([]models.Activity, error)
|
||||
ListActivitiesByStatus(ctx context.Context, arg models.ListActivitiesByStatusParams) ([]models.Activity, error)
|
||||
ListActivitiesByType(ctx context.Context, arg models.ListActivitiesByTypeParams) ([]models.Activity, error)
|
||||
SoftDeleteActivity(ctx context.Context, id string) error
|
||||
UpdateActivityStatus(ctx context.Context, arg models.UpdateActivityStatusParams) (models.Activity, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
17
controllers/asset/entity.go
Normal file
17
controllers/asset/entity.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package asset
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type AssetEntity interface {
|
||||
GetModel() models.Asset
|
||||
GetCard(ticker, price string) templ.Component
|
||||
}
|
||||
|
||||
type AssetsEntity interface {
|
||||
GetModels() []models.Asset
|
||||
GetList() templ.Component
|
||||
GetDropdown() templ.Component
|
||||
}
|
||||
27
controllers/asset/queries.go
Normal file
27
controllers/asset/queries.go
Normal file
@@ -0,0 +1,27 @@
|
||||
package asset
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetAssetByChainAndSymbol(ctx context.Context, arg models.GetAssetByChainAndSymbolParams) (models.Asset, error)
|
||||
GetAssetByID(ctx context.Context, id string) (models.Asset, error)
|
||||
GetAssetBySymbol(ctx context.Context, symbol string) (models.Asset, error)
|
||||
GetAssetWithLatestPrice(ctx context.Context, id string) (models.GetAssetWithLatestPriceRow, error)
|
||||
InsertAsset(ctx context.Context, arg models.InsertAssetParams) (models.Asset, error)
|
||||
ListAssetsByChain(ctx context.Context, chainID string) ([]models.Asset, error)
|
||||
ListAssetsWithLatestPrices(ctx context.Context, arg models.ListAssetsWithLatestPricesParams) ([]models.ListAssetsWithLatestPricesRow, error)
|
||||
SoftDeleteAsset(ctx context.Context, id string) error
|
||||
UpdateAsset(ctx context.Context, arg models.UpdateAssetParams) (models.Asset, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
7
controllers/asset/select.templ
Normal file
7
controllers/asset/select.templ
Normal file
@@ -0,0 +1,7 @@
|
||||
package asset
|
||||
|
||||
templ selectComponent() {
|
||||
<div class="flex flex-col gap-4 mt-4">
|
||||
<div class="flex justify-between items-center"></div>
|
||||
</div>
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package view
|
||||
package asset
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func registerView(data any) templ.Component {
|
||||
func selectComponent() 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 {
|
||||
@@ -29,7 +29,7 @@ func registerView(data any) templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div><h1>Register</h1></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div class=\"flex flex-col gap-4 mt-4\"><div class=\"flex justify-between items-center\"></div></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
17
controllers/blockchain/entity.go
Normal file
17
controllers/blockchain/entity.go
Normal file
@@ -0,0 +1,17 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type BlockchainEntity interface {
|
||||
GetModel() models.Blockchain
|
||||
GetCard(ticker, price string) templ.Component
|
||||
}
|
||||
|
||||
type BlockchainsEntity interface {
|
||||
GetModels() []models.Blockchain
|
||||
GetList() templ.Component
|
||||
GetDropdown() templ.Component
|
||||
}
|
||||
41
controllers/blockchain/queries.go
Normal file
41
controllers/blockchain/queries.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetBlockchainByChainName(ctx context.Context, chainName string) (models.Blockchain, error)
|
||||
GetBlockchainByCosmosChainID(ctx context.Context, chainIDCosmos sql.NullString) (models.Blockchain, error)
|
||||
GetBlockchainByEvmChainID(ctx context.Context, chainIDEvm sql.NullString) (models.Blockchain, error)
|
||||
GetBlockchainByID(ctx context.Context, id string) (models.Blockchain, error)
|
||||
GetBlockchainEndpoints(ctx context.Context, id string) (models.GetBlockchainEndpointsRow, error)
|
||||
GetBlockchainExplorer(ctx context.Context, id string) (models.GetBlockchainExplorerRow, error)
|
||||
GetBlockchainWithAssetInfo(ctx context.Context, id string) (models.GetBlockchainWithAssetInfoRow, error)
|
||||
InsertBlockchain(ctx context.Context, arg models.InsertBlockchainParams) (models.Blockchain, error)
|
||||
ListBlockchainsWithAssetInfo(ctx context.Context, arg models.ListBlockchainsWithAssetInfoParams) ([]models.ListBlockchainsWithAssetInfoRow, error)
|
||||
ListBlockchainsWithERC20Support(ctx context.Context) ([]models.Blockchain, error)
|
||||
ListBlockchainsWithExtensionSupport(ctx context.Context) ([]models.Blockchain, error)
|
||||
ListBlockchainsWithMobileSupport(ctx context.Context) ([]models.Blockchain, error)
|
||||
ListBlockchainsWithStaking(ctx context.Context) ([]models.Blockchain, error)
|
||||
SearchBlockchains(ctx context.Context, arg models.SearchBlockchainsParams) ([]models.Blockchain, error)
|
||||
SoftDeleteBlockchain(ctx context.Context, id string) error
|
||||
UpdateBlockchain(ctx context.Context, arg models.UpdateBlockchainParams) (models.Blockchain, error)
|
||||
UpdateBlockchainDescriptions(ctx context.Context, arg models.UpdateBlockchainDescriptionsParams) (models.Blockchain, error)
|
||||
UpdateBlockchainEndpoints(ctx context.Context, arg models.UpdateBlockchainEndpointsParams) (models.Blockchain, error)
|
||||
UpdateBlockchainExplorer(ctx context.Context, arg models.UpdateBlockchainExplorerParams) (models.Blockchain, error)
|
||||
UpdateBlockchainFeeInfo(ctx context.Context, arg models.UpdateBlockchainFeeInfoParams) (models.Blockchain, error)
|
||||
UpdateBlockchainImages(ctx context.Context, arg models.UpdateBlockchainImagesParams) (models.Blockchain, error)
|
||||
UpdateBlockchainSocialLinks(ctx context.Context, arg models.UpdateBlockchainSocialLinksParams) (models.Blockchain, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
43
controllers/credential/descriptor.go
Normal file
43
controllers/credential/descriptor.go
Normal file
@@ -0,0 +1,43 @@
|
||||
package credential
|
||||
|
||||
import "github.com/sonr-io/motr/internal/sink/models"
|
||||
|
||||
// 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) *models.Credential {
|
||||
return &models.Credential{
|
||||
Handle: handle,
|
||||
Origin: origin,
|
||||
CredentialID: c.ID,
|
||||
Type: c.Type,
|
||||
Transports: c.Transports,
|
||||
AuthenticatorAttachment: c.AuthenticatorAttachment,
|
||||
}
|
||||
}
|
||||
|
||||
func CredentialArrayToDescriptors(credentials []models.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
|
||||
}
|
||||
18
controllers/credential/entity.go
Normal file
18
controllers/credential/entity.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package credential
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type CredentialEntity interface {
|
||||
GetModel() models.Credential
|
||||
GetDescriptor() *CredentialDescriptor
|
||||
GetInfoModal() templ.Component
|
||||
}
|
||||
|
||||
type CredentialsEntity interface {
|
||||
GetModels() []models.Credential
|
||||
GetDescriptors() []*CredentialDescriptor
|
||||
GetList() templ.Component
|
||||
}
|
||||
111
controllers/credential/inputs.templ
Normal file
111
controllers/credential/inputs.templ
Normal file
@@ -0,0 +1,111 @@
|
||||
package credential
|
||||
|
||||
templ PasskeyInitial(clickHandler templ.ComponentScript) {
|
||||
<sl-button style="width: 100%;" onclick={ clickHandler }>
|
||||
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-neutral-500"></sl-icon>
|
||||
Register Passkey
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
templ PasskeyError(clickHandler templ.ComponentScript) {
|
||||
<sl-button style="width: 100%;" onclick={ clickHandler }>
|
||||
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-red-500"></sl-icon>
|
||||
Register Passkey
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
templ PasskeySuccess(clickHandler templ.ComponentScript) {
|
||||
<sl-button style="width: 100%;" onclick={ clickHandler }>
|
||||
<sl-icon slot="prefix" name="passkey" library="sonr" style="font-size: 24px;" class="text-green-500"></sl-icon>
|
||||
Register Passkey
|
||||
</sl-button>
|
||||
}
|
||||
|
||||
script NavigatorCredentialsCreate(userId string, userHandle string, challenge string) {
|
||||
const publicKey = {
|
||||
challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
|
||||
rp: {
|
||||
name: "Sonr.ID",
|
||||
},
|
||||
user: {
|
||||
// Assuming that userId is ASCII-only
|
||||
id: Uint8Array.from(userId, (c) => c.charCodeAt(0)),
|
||||
name: userId,
|
||||
displayName: userHandle,
|
||||
},
|
||||
pubKeyCredParams: [
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -7, // "ES256"
|
||||
},
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -257, // "RS256"
|
||||
},
|
||||
],
|
||||
authenticatorSelection: {
|
||||
userVerification: "required",
|
||||
residentKey: "required",
|
||||
authenticatorAttachment: "platform",
|
||||
},
|
||||
timeout: 60000, // 1 minute
|
||||
extensions: {
|
||||
payment: {
|
||||
isPayment: true,
|
||||
},
|
||||
largeBlob: {
|
||||
supported: "preferred",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Helper function to convert ArrayBuffer to Base64URL string
|
||||
function arrayBufferToBase64URL(buffer) {
|
||||
const bytes = new Uint8Array(buffer);
|
||||
let str = '';
|
||||
bytes.forEach(byte => { str += String.fromCharCode(byte) });
|
||||
return btoa(str)
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=/g, '');
|
||||
}
|
||||
|
||||
navigator.credentials
|
||||
.create({ publicKey })
|
||||
.then((newCredentialInfo) => {
|
||||
if (!(newCredentialInfo instanceof PublicKeyCredential)) {
|
||||
throw new Error('Received credential is not a PublicKeyCredential');
|
||||
}
|
||||
|
||||
const response = newCredentialInfo.response;
|
||||
if (!(response instanceof AuthenticatorAttestationResponse)) {
|
||||
throw new Error('Response is not an AuthenticatorAttestationResponse');
|
||||
}
|
||||
|
||||
// Convert the credential data to a cross-platform compatible format
|
||||
const credentialJSON = {
|
||||
id: newCredentialInfo.id,
|
||||
rawId: arrayBufferToBase64URL(newCredentialInfo.rawId),
|
||||
type: newCredentialInfo.type,
|
||||
authenticatorAttachment: newCredentialInfo.authenticatorAttachment || null,
|
||||
transports: Array.isArray(response.getTransports) ? response.getTransports() : [],
|
||||
clientExtensionResults: newCredentialInfo.getClientExtensionResults(),
|
||||
response: {
|
||||
attestationObject: arrayBufferToBase64URL(response.attestationObject),
|
||||
clientDataJSON: arrayBufferToBase64URL(response.clientDataJSON)
|
||||
}
|
||||
};
|
||||
|
||||
// Set the form value with the stringified credential data
|
||||
const credential = document.getElementById('credential-data');
|
||||
credential.value = JSON.stringify(credentialJSON);
|
||||
|
||||
// Submit the form
|
||||
const form = document.getElementById('passkey-form');
|
||||
form.submit();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Passkey creation failed:', err);
|
||||
alert(`Failed to create passkey: ${err.message || 'Unknown error'}`);
|
||||
});
|
||||
}
|
||||
232
controllers/credential/inputs_templ.go
Normal file
232
controllers/credential/inputs_templ.go
Normal file
@@ -0,0 +1,232 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package credential
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func PasskeyInitial(clickHandler templ.ComponentScript) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var1 == nil {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, clickHandler)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<sl-button style=\"width: 100%;\" onclick=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var2 templ.ComponentScript = clickHandler
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var2.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 2, "\"><sl-icon slot=\"prefix\" name=\"passkey\" library=\"sonr\" style=\"font-size: 24px;\" class=\"text-neutral-500\"></sl-icon> Register Passkey</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func PasskeyError(clickHandler templ.ComponentScript) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var3 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var3 == nil {
|
||||
templ_7745c5c3_Var3 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, clickHandler)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 3, "<sl-button style=\"width: 100%;\" onclick=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var4 templ.ComponentScript = clickHandler
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var4.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 4, "\"><sl-icon slot=\"prefix\" name=\"passkey\" library=\"sonr\" style=\"font-size: 24px;\" class=\"text-red-500\"></sl-icon> Register Passkey</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func PasskeySuccess(clickHandler templ.ComponentScript) templ.Component {
|
||||
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
|
||||
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
|
||||
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
|
||||
return templ_7745c5c3_CtxErr
|
||||
}
|
||||
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
|
||||
if !templ_7745c5c3_IsBuffer {
|
||||
defer func() {
|
||||
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
|
||||
if templ_7745c5c3_Err == nil {
|
||||
templ_7745c5c3_Err = templ_7745c5c3_BufErr
|
||||
}
|
||||
}()
|
||||
}
|
||||
ctx = templ.InitializeContext(ctx)
|
||||
templ_7745c5c3_Var5 := templ.GetChildren(ctx)
|
||||
if templ_7745c5c3_Var5 == nil {
|
||||
templ_7745c5c3_Var5 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templ.RenderScriptItems(ctx, templ_7745c5c3_Buffer, clickHandler)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 5, "<sl-button style=\"width: 100%;\" onclick=\"")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
var templ_7745c5c3_Var6 templ.ComponentScript = clickHandler
|
||||
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ_7745c5c3_Var6.Call)
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 6, "\"><sl-icon slot=\"prefix\" name=\"passkey\" library=\"sonr\" style=\"font-size: 24px;\" class=\"text-green-500\"></sl-icon> Register Passkey</sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
func NavigatorCredentialsCreate(userId string, userHandle string, challenge string) templ.ComponentScript {
|
||||
return templ.ComponentScript{
|
||||
Name: `__templ_NavigatorCredentialsCreate_8f96`,
|
||||
Function: `function __templ_NavigatorCredentialsCreate_8f96(userId, userHandle, challenge){const publicKey = {
|
||||
challenge: Uint8Array.from(challenge, (c) => c.charCodeAt(0)),
|
||||
rp: {
|
||||
name: "Sonr.ID",
|
||||
},
|
||||
user: {
|
||||
// Assuming that userId is ASCII-only
|
||||
id: Uint8Array.from(userId, (c) => c.charCodeAt(0)),
|
||||
name: userId,
|
||||
displayName: userHandle,
|
||||
},
|
||||
pubKeyCredParams: [
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -7, // "ES256"
|
||||
},
|
||||
{
|
||||
type: "public-key",
|
||||
alg: -257, // "RS256"
|
||||
},
|
||||
],
|
||||
authenticatorSelection: {
|
||||
userVerification: "required",
|
||||
residentKey: "required",
|
||||
authenticatorAttachment: "platform",
|
||||
},
|
||||
timeout: 60000, // 1 minute
|
||||
extensions: {
|
||||
payment: {
|
||||
isPayment: true,
|
||||
},
|
||||
largeBlob: {
|
||||
supported: "preferred",
|
||||
},
|
||||
},
|
||||
};
|
||||
|
||||
// Helper function to convert ArrayBuffer to Base64URL string
|
||||
function arrayBufferToBase64URL(buffer) {
|
||||
const bytes = new Uint8Array(buffer);
|
||||
let str = '';
|
||||
bytes.forEach(byte => { str += String.fromCharCode(byte) });
|
||||
return btoa(str)
|
||||
.replace(/\+/g, '-')
|
||||
.replace(/\//g, '_')
|
||||
.replace(/=/g, '');
|
||||
}
|
||||
|
||||
navigator.credentials
|
||||
.create({ publicKey })
|
||||
.then((newCredentialInfo) => {
|
||||
if (!(newCredentialInfo instanceof PublicKeyCredential)) {
|
||||
throw new Error('Received credential is not a PublicKeyCredential');
|
||||
}
|
||||
|
||||
const response = newCredentialInfo.response;
|
||||
if (!(response instanceof AuthenticatorAttestationResponse)) {
|
||||
throw new Error('Response is not an AuthenticatorAttestationResponse');
|
||||
}
|
||||
|
||||
// Convert the credential data to a cross-platform compatible format
|
||||
const credentialJSON = {
|
||||
id: newCredentialInfo.id,
|
||||
rawId: arrayBufferToBase64URL(newCredentialInfo.rawId),
|
||||
type: newCredentialInfo.type,
|
||||
authenticatorAttachment: newCredentialInfo.authenticatorAttachment || null,
|
||||
transports: Array.isArray(response.getTransports) ? response.getTransports() : [],
|
||||
clientExtensionResults: newCredentialInfo.getClientExtensionResults(),
|
||||
response: {
|
||||
attestationObject: arrayBufferToBase64URL(response.attestationObject),
|
||||
clientDataJSON: arrayBufferToBase64URL(response.clientDataJSON)
|
||||
}
|
||||
};
|
||||
|
||||
// Set the form value with the stringified credential data
|
||||
const credential = document.getElementById('credential-data');
|
||||
credential.value = JSON.stringify(credentialJSON);
|
||||
|
||||
// Submit the form
|
||||
const form = document.getElementById('passkey-form');
|
||||
form.submit();
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error('Passkey creation failed:', err);
|
||||
alert(` + "`" + `Failed to create passkey: ${err.message || 'Unknown error'}` + "`" + `);
|
||||
});
|
||||
}`,
|
||||
Call: templ.SafeScript(`__templ_NavigatorCredentialsCreate_8f96`, userId, userHandle, challenge),
|
||||
CallInline: templ.SafeScriptInline(`__templ_NavigatorCredentialsCreate_8f96`, userId, userHandle, challenge),
|
||||
}
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
22
controllers/credential/queries.go
Normal file
22
controllers/credential/queries.go
Normal file
@@ -0,0 +1,22 @@
|
||||
package credential
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetCredentialByID(ctx context.Context, credentialID string) (models.Credential, error)
|
||||
GetCredentialsByHandle(ctx context.Context, handle string) ([]models.Credential, error)
|
||||
InsertCredential(ctx context.Context, arg models.InsertCredentialParams) (models.Credential, error)
|
||||
SoftDeleteCredential(ctx context.Context, credentialID string) error
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
16
controllers/health/entity.go
Normal file
16
controllers/health/entity.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package health
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type HealthEntity interface {
|
||||
GetModel() models.Health
|
||||
GetCard() templ.Component
|
||||
}
|
||||
|
||||
type HealthsEntity interface {
|
||||
GetModels() []models.Health
|
||||
GetList() templ.Component
|
||||
}
|
||||
26
controllers/health/queries.go
Normal file
26
controllers/health/queries.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package health
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetHealthByEndpoint(ctx context.Context, endpointUrl string) (models.Health, error)
|
||||
GetHealthByID(ctx context.Context, id string) (models.Health, error)
|
||||
InsertHealth(ctx context.Context, arg models.InsertHealthParams) (models.Health, error)
|
||||
ListHealthByChain(ctx context.Context, arg models.ListHealthByChainParams) ([]models.Health, error)
|
||||
ListHealthByStatus(ctx context.Context, arg models.ListHealthByStatusParams) ([]models.Health, error)
|
||||
ListHealthChecksNeedingUpdate(ctx context.Context, limit int64) ([]models.Health, error)
|
||||
SoftDeleteHealth(ctx context.Context, id string) error
|
||||
UpdateHealthCheck(ctx context.Context, arg models.UpdateHealthCheckParams) (models.Health, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
16
controllers/prices/entity.go
Normal file
16
controllers/prices/entity.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package prices
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type PriceEntity interface {
|
||||
GetModel() models.Price
|
||||
GetCard() templ.Component
|
||||
}
|
||||
|
||||
type PricesEntity interface {
|
||||
GetModels() []models.Price
|
||||
GetList() templ.Component
|
||||
}
|
||||
23
controllers/prices/queries.go
Normal file
23
controllers/prices/queries.go
Normal file
@@ -0,0 +1,23 @@
|
||||
package prices
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetPriceByAssetID(ctx context.Context, assetID string) (models.Price, error)
|
||||
GetPriceByID(ctx context.Context, id string) (models.Price, error)
|
||||
InsertPrice(ctx context.Context, arg models.InsertPriceParams) (models.Price, error)
|
||||
ListPriceHistoryByAssetID(ctx context.Context, arg models.ListPriceHistoryByAssetIDParams) ([]models.Price, error)
|
||||
UpdatePrice(ctx context.Context, arg models.UpdatePriceParams) (models.Price, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
16
controllers/profile/entity.go
Normal file
16
controllers/profile/entity.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type ProfileEntity interface {
|
||||
GetModel() models.Profile
|
||||
}
|
||||
|
||||
type ProfilesEntity interface {
|
||||
GetModels() []models.Profile
|
||||
GetList() templ.Component
|
||||
GetDropdown() templ.Component
|
||||
}
|
||||
8
controllers/profile/inputs.templ
Normal file
8
controllers/profile/inputs.templ
Normal file
@@ -0,0 +1,8 @@
|
||||
package profile
|
||||
|
||||
templ InputAvatar(value string, helpText string) {
|
||||
<input type="file" name="avatar" id="avatar" name="avatar" accept="image/*"/>
|
||||
<sl-button variant="neutral" slot="suffix" type="button">
|
||||
<sl-icon name="upload-2-fill" slot="prefix"></sl-icon>
|
||||
</sl-button>
|
||||
}
|
||||
@@ -1,14 +1,14 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
package view
|
||||
package profile
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func loginView(data any) templ.Component {
|
||||
func InputAvatar(value string, helpText 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 {
|
||||
@@ -29,7 +29,7 @@ func loginView(data any) templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div><h1>Login</h1></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<input type=\"file\" name=\"avatar\" id=\"avatar\" name=\"avatar\" accept=\"image/*\"> <sl-button variant=\"neutral\" slot=\"suffix\" type=\"button\"><sl-icon name=\"upload-2-fill\" slot=\"prefix\"></sl-icon></sl-button>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
26
controllers/profile/queries.go
Normal file
26
controllers/profile/queries.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package profile
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
CheckHandleExists(ctx context.Context, handle string) (bool, error)
|
||||
GetAccountsByHandle(ctx context.Context, handle string) ([]models.Account, error)
|
||||
GetCredentialsByHandle(ctx context.Context, handle string) ([]models.Credential, error)
|
||||
GetVaultsByHandle(ctx context.Context, handle string) ([]models.Vault, error)
|
||||
InsertProfile(ctx context.Context, arg models.InsertProfileParams) (models.Profile, error)
|
||||
ListProfiles(ctx context.Context, arg models.ListProfilesParams) ([]models.Profile, error)
|
||||
SoftDeleteProfile(ctx context.Context, address string) error
|
||||
UpdateProfile(ctx context.Context, arg models.UpdateProfileParams) (models.Profile, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
16
controllers/service/entity.go
Normal file
16
controllers/service/entity.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"github.com/a-h/templ"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type ServiceEntity interface {
|
||||
GetModel() models.Service
|
||||
GetCard() templ.Component
|
||||
}
|
||||
|
||||
type ServicesEntity interface {
|
||||
GetModels() []models.Service
|
||||
GetList() templ.Component
|
||||
}
|
||||
26
controllers/service/queries.go
Normal file
26
controllers/service/queries.go
Normal file
@@ -0,0 +1,26 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetServiceByAddress(ctx context.Context, address string) (models.Service, error)
|
||||
GetServiceByChainAndAddress(ctx context.Context, arg models.GetServiceByChainAndAddressParams) (models.Service, error)
|
||||
GetServiceByID(ctx context.Context, id string) (models.Service, error)
|
||||
InsertService(ctx context.Context, arg models.InsertServiceParams) (models.Service, error)
|
||||
ListServicesByChain(ctx context.Context, arg models.ListServicesByChainParams) ([]models.Service, error)
|
||||
ListServicesByOwner(ctx context.Context, arg models.ListServicesByOwnerParams) ([]models.Service, error)
|
||||
SoftDeleteService(ctx context.Context, id string) error
|
||||
UpdateService(ctx context.Context, arg models.UpdateServiceParams) (models.Service, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
9
controllers/vault/entity.go
Normal file
9
controllers/vault/entity.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type VaultEntity interface {
|
||||
GetModel() models.Vault
|
||||
}
|
||||
7
controllers/vault/forms.templ
Normal file
7
controllers/vault/forms.templ
Normal file
@@ -0,0 +1,7 @@
|
||||
package vault
|
||||
|
||||
templ LoginForm(opts LoginOptions) {
|
||||
<form method="post" action="/login">
|
||||
<sl-button type="submit" variant="primary">Login</sl-button>
|
||||
</form>
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
|
||||
package view
|
||||
package vault
|
||||
|
||||
//lint:file-ignore SA4006 This context is only used if a nested component is present.
|
||||
|
||||
import "github.com/a-h/templ"
|
||||
import templruntime "github.com/a-h/templ/runtime"
|
||||
|
||||
func authorizeView(data any) templ.Component {
|
||||
func LoginForm(opts LoginOptions) 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 {
|
||||
@@ -30,7 +29,7 @@ func authorizeView(data any) templ.Component {
|
||||
templ_7745c5c3_Var1 = templ.NopComponent
|
||||
}
|
||||
ctx = templ.ClearChildren(ctx)
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<div><h1>Authorize</h1></div>")
|
||||
templ_7745c5c3_Err = templruntime.WriteString(templ_7745c5c3_Buffer, 1, "<form method=\"post\" action=\"/login\"><sl-button type=\"submit\" variant=\"primary\">Login</sl-button></form>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
18
controllers/vault/options.go
Normal file
18
controllers/vault/options.go
Normal file
@@ -0,0 +1,18 @@
|
||||
package vault
|
||||
|
||||
import "github.com/sonr-io/motr/controllers/credential"
|
||||
|
||||
type LoginOptions struct {
|
||||
Account string
|
||||
Handle string
|
||||
HelpText string
|
||||
Label string
|
||||
Challenge string
|
||||
AllowedCredentials []*credential.CredentialDescriptor
|
||||
}
|
||||
|
||||
type RegisterOptions struct {
|
||||
Address string
|
||||
Handle string
|
||||
Challenge string
|
||||
}
|
||||
25
controllers/vault/queries.go
Normal file
25
controllers/vault/queries.go
Normal file
@@ -0,0 +1,25 @@
|
||||
package vault
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
)
|
||||
|
||||
type Queries interface {
|
||||
GetVaultByID(ctx context.Context, id string) (models.Vault, error)
|
||||
GetVaultConfigByCID(ctx context.Context, cid string) (models.Vault, error)
|
||||
GetVaultRedirectURIBySessionID(ctx context.Context, sessionID string) (string, error)
|
||||
GetVaultsByHandle(ctx context.Context, handle string) ([]models.Vault, error)
|
||||
InsertVault(ctx context.Context, arg models.InsertVaultParams) (models.Vault, error)
|
||||
SoftDeleteVault(ctx context.Context, id string) error
|
||||
UpdateVault(ctx context.Context, arg models.UpdateVaultParams) (models.Vault, error)
|
||||
}
|
||||
|
||||
func NewQueries(q models.Querier) Queries {
|
||||
return &queries{Querier: q}
|
||||
}
|
||||
|
||||
type queries struct {
|
||||
models.Querier
|
||||
}
|
||||
24
go.mod
24
go.mod
@@ -1,33 +1,33 @@
|
||||
module github.com/onsonr/motr
|
||||
module github.com/sonr-io/motr
|
||||
|
||||
go 1.23.1
|
||||
go 1.24.2
|
||||
|
||||
require (
|
||||
github.com/a-h/templ v0.3.857
|
||||
github.com/go-webauthn/webauthn v0.12.3
|
||||
github.com/labstack/echo/v4 v4.13.3
|
||||
github.com/ncruces/go-sqlite3 v0.21.3
|
||||
github.com/nlepage/go-wasm-http-server/v2 v2.2.1
|
||||
github.com/segmentio/ksuid v1.0.4
|
||||
github.com/syumai/workers v0.30.2
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/hack-pad/safejs v0.1.1 // indirect
|
||||
github.com/nlepage/go-js-promise v1.0.0 // indirect
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 // indirect
|
||||
github.com/go-webauthn/x v0.1.20 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
||||
github.com/google/go-tpm v0.9.3 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/x448/float16 v0.8.4 // indirect
|
||||
)
|
||||
|
||||
require (
|
||||
// github.com/a-h/templ v0.3.857 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/labstack/gommon v0.4.2 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/ncruces/julianday v1.0.0 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/tetratelabs/wazero v1.8.2 // indirect
|
||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||
golang.org/x/crypto v0.36.0 // indirect
|
||||
golang.org/x/net v0.37.0 // indirect
|
||||
golang.org/x/sys v0.31.0 // indirect
|
||||
golang.org/x/text v0.23.0 // indirect
|
||||
golang.org/x/time v0.8.0 // indirect
|
||||
)
|
||||
|
||||
42
go.sum
42
go.sum
@@ -1,11 +1,21 @@
|
||||
github.com/a-h/templ v0.3.857 h1:6EqcJuGZW4OL+2iZ3MD+NnIcG7nGkaQeF2Zq5kf9ZGg=
|
||||
github.com/a-h/templ v0.3.857/go.mod h1:qhrhAkRFubE7khxLZHsBFHfX+gWwVNKbzKeF9GlPV4M=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0 h1:fFtUGXUzXPHTIUdne5+zzMPTfffl3RD5qYnkY40vtxU=
|
||||
github.com/fxamacker/cbor/v2 v2.8.0/go.mod h1:vM4b+DJCtHn+zz7h3FFp/hDAI9WNWCsZj23V5ytsSxQ=
|
||||
github.com/go-webauthn/webauthn v0.12.3 h1:hHQl1xkUuabUU9uS+ISNCMLs9z50p9mDUZI/FmkayNE=
|
||||
github.com/go-webauthn/webauthn v0.12.3/go.mod h1:4JRe8Z3W7HIw8NGEWn2fnUwecoDzkkeach/NnvhkqGY=
|
||||
github.com/go-webauthn/x v0.1.20 h1:brEBDqfiPtNNCdS/peu8gARtq8fIPsHz0VzpPjGvgiw=
|
||||
github.com/go-webauthn/x v0.1.20/go.mod h1:n/gAc8ssZJGATM0qThE+W+vfgXiMedsWi3wf/C4lld0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/hack-pad/safejs v0.1.1 h1:d5qPO0iQ7h2oVtpzGnLExE+Wn9AtytxIfltcS2b9KD8=
|
||||
github.com/hack-pad/safejs v0.1.1/go.mod h1:HdS+bKF1NrE72VoXZeWzxFOVQVUSqZJAG0xNCnb+Tio=
|
||||
github.com/google/go-tpm v0.9.3 h1:+yx0/anQuGzi+ssRqeD6WpXjW2L/V0dItUayO0i9sRc=
|
||||
github.com/google/go-tpm v0.9.3/go.mod h1:h9jEsEECg7gtLis0upRBQU+GhYVH6jMjrFxI8u6bVUY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/labstack/echo/v4 v4.13.3 h1:pwhpCPrTl5qry5HRdM5FwdXnhXSLSY+WE+YQSeCaafY=
|
||||
github.com/labstack/echo/v4 v4.13.3/go.mod h1:o90YNEeQWjDozo584l7AwhJMHN0bOC4tAfg+Xox9q5g=
|
||||
github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
|
||||
@@ -15,24 +25,22 @@ github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovk
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/ncruces/go-sqlite3 v0.21.3 h1:hHkfNQLcbnxPJZhC/RGw9SwP3bfkv/Y0xUHWsr1CdMQ=
|
||||
github.com/ncruces/go-sqlite3 v0.21.3/go.mod h1:zxMOaSG5kFYVFK4xQa0pdwIszqxqJ0W0BxBgwdrNjuA=
|
||||
github.com/ncruces/julianday v1.0.0 h1:fH0OKwa7NWvniGQtxdJRxAgkBMolni2BjDHaWTxqt7M=
|
||||
github.com/ncruces/julianday v1.0.0/go.mod h1:Dusn2KvZrrovOMJuOt0TNXL6tB7U2E8kvza5fFc9G7g=
|
||||
github.com/nlepage/go-js-promise v1.0.0 h1:K7OmJ3+0BgWJ2LfXchg2sI6RDr7AW/KWR8182epFwGQ=
|
||||
github.com/nlepage/go-js-promise v1.0.0/go.mod h1:bdOP0wObXu34euibyK39K1hoBCtlgTKXGc56AGflaRo=
|
||||
github.com/nlepage/go-wasm-http-server/v2 v2.2.1 h1:4tzhSb3HKQ3Ykt2TPfqEnmcPfw8n1E8agv4OzAyckr8=
|
||||
github.com/nlepage/go-wasm-http-server/v2 v2.2.1/go.mod h1:r8j7cEOeUqNp+c+C52sNuWaFTvvT/cNqIwBuEtA36HA=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/segmentio/ksuid v1.0.4 h1:sBo2BdShXjmcugAMwjugoGUdUV0pcxY5mW4xKRn3v4c=
|
||||
github.com/segmentio/ksuid v1.0.4/go.mod h1:/XUiZBD3kVx5SmUOl55voK5yeAbBNNIed+2O73XgrPE=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/tetratelabs/wazero v1.8.2 h1:yIgLR/b2bN31bjxwXHD8a3d+BogigR952csSDdLYEv4=
|
||||
github.com/tetratelabs/wazero v1.8.2/go.mod h1:yAI0XTsMBhREkM/YDAK/zNou3GoiAce1P6+rp/wQhjs=
|
||||
github.com/syumai/workers v0.30.2 h1:ZefPdAoXBsw87Bxy1LTAR6Pm9Gbxw/iM7DNraPSput0=
|
||||
github.com/syumai/workers v0.30.2/go.mod h1:ZnqmdiHNBrbxOLrZ/HJ5jzHy6af9cmiNZk10R9NrIEA=
|
||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
|
||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||
github.com/x448/float16 v0.8.4 h1:qLwI1I70+NjRFUR3zs1JPUCgaCXSh3SW62uAKT1mSBM=
|
||||
github.com/x448/float16 v0.8.4/go.mod h1:14CWIYCyZA/cWjXOioeEpHeN/83MdbZDRQHoFcYsOfg=
|
||||
golang.org/x/crypto v0.36.0 h1:AnAEvhDddvBdpY+uR+MyHmuZzzNqXSe/GvuDeob5L34=
|
||||
golang.org/x/crypto v0.36.0/go.mod h1:Y4J0ReaxCR1IMaabaSMugxJES1EpwhBHhv2bDHklZvc=
|
||||
golang.org/x/net v0.37.0 h1:1zLorHbz+LYj7MQlSf1+2tPIIgibq2eL5xkrGk6f+2c=
|
||||
@@ -43,7 +51,5 @@ golang.org/x/sys v0.31.0 h1:ioabZlmFYtWhL+TRYpcnNlLwhyxaM9kWTDEmfnprqik=
|
||||
golang.org/x/sys v0.31.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/text v0.23.0 h1:D71I7dUrlY+VX0gQShAThNGHFxZ13dGLBHQLVl1mJlY=
|
||||
golang.org/x/text v0.23.0/go.mod h1:/BLNzu4aZCJ1+kcD0DNRotWKage4q2rGVAg4o22unh4=
|
||||
golang.org/x/time v0.8.0 h1:9i3RxcPv3PZnitoVGMPDKZSq1xW1gK1Xy3ArNOGZfEg=
|
||||
golang.org/x/time v0.8.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
|
||||
171
handlers/auth/controller.go
Normal file
171
handlers/auth/controller.go
Normal file
@@ -0,0 +1,171 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package auth
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/go-webauthn/webauthn/webauthn"
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/sonr-io/motr/components/views"
|
||||
"github.com/sonr-io/motr/internal/config"
|
||||
"github.com/sonr-io/motr/internal/middleware"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
"github.com/syumai/workers/cloudflare/kv"
|
||||
)
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Auth Handler │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
func Register(cfg config.Config, s *config.Server) error {
|
||||
q, err := cfg.DB.GetQuerier()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hkv, err := cfg.KV.GetHandles()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
skv, err := cfg.KV.GetSessions()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
h := NewAuthHandler(q, hkv, skv)
|
||||
h.SetupRoutes(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Auth Handler │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
// AuthHandler is the auth handler.
|
||||
type AuthHandler struct {
|
||||
DB models.Querier
|
||||
Handles *kv.Namespace
|
||||
Sessions *kv.Namespace
|
||||
}
|
||||
|
||||
func NewAuthHandler(q models.Querier, hkv *kv.Namespace, skv *kv.Namespace) *AuthHandler {
|
||||
return &AuthHandler{DB: q, Handles: hkv, Sessions: skv}
|
||||
}
|
||||
|
||||
// SetupRoutes sets up the routes for the auth handler.
|
||||
func (h *AuthHandler) SetupRoutes(s *config.Server) {
|
||||
s.GET("/login", h.HandleLoginInitial)
|
||||
s.GET("/login/:handle", h.HandleLoginStart)
|
||||
s.POST("/login/:handle/check", h.HandleLoginUsernameCheck)
|
||||
s.POST("/login/:handle/finish", h.HandleLoginFinish)
|
||||
|
||||
s.GET("/register", h.HandleRegisterInitial)
|
||||
s.GET("/register/:handle", h.HandleRegisterStart)
|
||||
s.POST("/register/:handle/check", h.HandleRegisterUsernameCheck)
|
||||
s.POST("/register/:handle/finish", h.HandleRegisterFinish)
|
||||
}
|
||||
|
||||
func (c *AuthHandler) VerifyHandle(handle string, target bool) bool {
|
||||
_, err := c.Handles.GetString(handle, nil)
|
||||
if err != nil {
|
||||
return !target
|
||||
}
|
||||
res, err := c.DB.CheckHandleExists(context.Background(), handle)
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
return res == target
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Login Handlers (/login) │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
// HandleLoginFinish handles the finish login request.
|
||||
func (h *AuthHandler) HandleLoginFinish(c echo.Context) error {
|
||||
return middleware.Render(c, views.LoginView())
|
||||
}
|
||||
|
||||
// HandleLoginStart handles the start login request.
|
||||
func (h *AuthHandler) HandleLoginStart(c echo.Context) error {
|
||||
return middleware.Render(c, views.LoginView())
|
||||
}
|
||||
|
||||
func (h *AuthHandler) HandleLoginInitial(c echo.Context) error {
|
||||
return middleware.Render(c, views.LoginView())
|
||||
}
|
||||
|
||||
// HandleSubmitCredentialLogin handles the submit credential login request.
|
||||
func (h *AuthHandler) HandleSubmitCredentialLogin(c echo.Context) error {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
// ╭───────────────────────────────────────────────────────────╮
|
||||
// │ Profile Handlers (/login) │
|
||||
// ╰───────────────────────────────────────────────────────────╯
|
||||
|
||||
// HandleRegisterUsernameCheck handles the username check request.
|
||||
func (h *AuthHandler) HandleRegisterUsernameCheck(c echo.Context) error {
|
||||
handle := c.FormValue("handle")
|
||||
ok := h.VerifyHandle(handle, false)
|
||||
if ok {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
// HandleLoginUsernameCheck handles the username check request.
|
||||
func (h *AuthHandler) HandleLoginUsernameCheck(c echo.Context) error {
|
||||
handle := c.FormValue("handle")
|
||||
ok := h.VerifyHandle(handle, true)
|
||||
if ok {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
func (h *AuthHandler) HandleSubmitUsernameClaim(c echo.Context) error {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
func (h *AuthHandler) HandleSubmitProfile(c echo.Context) error {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
// ╭────────────────────────────────────────────────────────╮
|
||||
// │ Register Init (/register) │
|
||||
// ╰────────────────────────────────────────────────────────╯
|
||||
|
||||
// HandleRegisterInitial handles the initial register request.
|
||||
func (h *AuthHandler) HandleRegisterInitial(c echo.Context) error {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
// HandleRegisterStart handles the start register request.
|
||||
func (h *AuthHandler) HandleRegisterStart(c echo.Context) error {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
// HandleRegisterFinish handles the finish register request.
|
||||
func (h *AuthHandler) HandleRegisterFinish(c echo.Context) error {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
|
||||
// HandleSubmitCredentialRegister handles the submit credential register request.
|
||||
func (h *AuthHandler) HandleSubmitCredentialRegister(c echo.Context) error {
|
||||
credJSON := c.FormValue("credentialJSON")
|
||||
if credJSON == "" {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
cred := webauthn.Credential{}
|
||||
err := json.Unmarshal([]byte(credJSON), &cred)
|
||||
if err != nil {
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
fmt.Println(cred)
|
||||
|
||||
return middleware.Render(c, views.RegisterView())
|
||||
}
|
||||
52
handlers/landing/controller.go
Normal file
52
handlers/landing/controller.go
Normal file
@@ -0,0 +1,52 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package landing
|
||||
|
||||
import (
|
||||
"github.com/labstack/echo/v4"
|
||||
"github.com/sonr-io/motr/components/views"
|
||||
"github.com/sonr-io/motr/internal/config"
|
||||
"github.com/sonr-io/motr/internal/middleware"
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
"github.com/syumai/workers/cloudflare/kv"
|
||||
)
|
||||
|
||||
func Register(cfg config.Config, s *config.Server) error {
|
||||
q, err := cfg.DB.GetQuerier()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
hkv, err := cfg.KV.GetHandles()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
skv, err := cfg.KV.GetSessions()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
h := New(q, hkv, skv)
|
||||
h.SetupRoutes(s)
|
||||
return nil
|
||||
}
|
||||
|
||||
type LandingHandler struct {
|
||||
DB models.Querier
|
||||
Handles *kv.Namespace
|
||||
Sessions *kv.Namespace
|
||||
}
|
||||
|
||||
func New(q models.Querier, hkv *kv.Namespace, skv *kv.Namespace) *LandingHandler {
|
||||
return &LandingHandler{DB: q, Handles: hkv, Sessions: skv}
|
||||
}
|
||||
|
||||
func (h *LandingHandler) SetupRoutes(s *config.Server) {
|
||||
s.GET("/", h.HandleIndex)
|
||||
}
|
||||
|
||||
func (h *LandingHandler) HandleIndex(c echo.Context) error {
|
||||
if err := middleware.GetSession(c).SaveStatus(h.Sessions); err != nil {
|
||||
return err
|
||||
}
|
||||
return middleware.Render(c, views.HomeView())
|
||||
}
|
||||
183
internal/config/config.go
Normal file
183
internal/config/config.go
Normal file
@@ -0,0 +1,183 @@
|
||||
//go:build js && wasm
|
||||
// +build js,wasm
|
||||
|
||||
package config
|
||||
|
||||
import (
|
||||
"database/sql"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/sonr-io/motr/internal/sink/models"
|
||||
"github.com/syumai/workers/cloudflare"
|
||||
_ "github.com/syumai/workers/cloudflare/d1"
|
||||
"github.com/syumai/workers/cloudflare/kv"
|
||||
)
|
||||
|
||||
type MotrMode string
|
||||
|
||||
const (
|
||||
ControllerMode MotrMode = "controller"
|
||||
ResolverMode MotrMode = "resolver"
|
||||
)
|
||||
|
||||
func (m MotrMode) String() string {
|
||||
return string(m)
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
Sonr SonrConfig `json:"sonr"`
|
||||
IPFS IPFSConfig `json:"ipfs"`
|
||||
Mode MotrMode `json:"mode"`
|
||||
DB DBConfig `json:"db"`
|
||||
Cache CacheConfig `json:"cache"` // Added Cache configuration
|
||||
KV KVConfig `json:"kv"` // Added KV configuration
|
||||
}
|
||||
|
||||
func Get() Config {
|
||||
c := Config{
|
||||
Sonr: getSonrConfig(),
|
||||
IPFS: getIPFSConfig(),
|
||||
Mode: getMotrMode(),
|
||||
DB: getDBConfig(),
|
||||
Cache: getCacheConfig(), // Added Cache configuration
|
||||
KV: getKVConfig(), // Added KV configuration
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
type SonrConfig struct {
|
||||
ChainID string `json:"chain_id"`
|
||||
APIURL string `json:"api_url"`
|
||||
RPCURL string `json:"rpc_url"`
|
||||
}
|
||||
|
||||
func getSonrConfig() SonrConfig {
|
||||
return SonrConfig{
|
||||
ChainID: cloudflare.Getenv("SONR_CHAIN_ID"),
|
||||
APIURL: cloudflare.Getenv("SONR_API_URL"),
|
||||
RPCURL: cloudflare.Getenv("SONR_RPC_URL"),
|
||||
}
|
||||
}
|
||||
|
||||
type IPFSConfig struct {
|
||||
GatewayURL string `json:"gateway_url"`
|
||||
}
|
||||
|
||||
func getIPFSConfig() IPFSConfig {
|
||||
return IPFSConfig{
|
||||
GatewayURL: cloudflare.Getenv("IPFS_GATEWAY"),
|
||||
}
|
||||
}
|
||||
|
||||
func getMotrMode() MotrMode {
|
||||
mode := cloudflare.Getenv("MOTR_MODE")
|
||||
if mode == "" {
|
||||
return ControllerMode
|
||||
}
|
||||
return MotrMode(mode)
|
||||
}
|
||||
|
||||
type DBConfig struct {
|
||||
DBName string `json:"common_db_name"`
|
||||
}
|
||||
|
||||
func getDBConfig() DBConfig {
|
||||
return DBConfig{
|
||||
DBName: "DB",
|
||||
}
|
||||
}
|
||||
|
||||
func (c DBConfig) GetCommon() (*sql.DB, error) {
|
||||
return sql.Open("d1", c.DBName)
|
||||
}
|
||||
|
||||
func (c DBConfig) GetQuerier() (models.Querier, error) {
|
||||
db, err := c.GetCommon()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return models.New(db), nil
|
||||
}
|
||||
|
||||
// CacheConfig defines the configuration for Cloudflare cache
|
||||
type CacheConfig struct {
|
||||
Enabled bool `json:"enabled"`
|
||||
DefaultMaxAge int `json:"default_max_age"`
|
||||
BypassHeader string `json:"bypass_header"`
|
||||
BypassValue string `json:"bypass_value"`
|
||||
CacheableStatusCodes []int `json:"cacheable_status_codes"`
|
||||
CacheableContentTypes []string `json:"cacheable_content_types"`
|
||||
}
|
||||
|
||||
func getCacheConfig() CacheConfig {
|
||||
// Default values
|
||||
config := CacheConfig{
|
||||
Enabled: true,
|
||||
DefaultMaxAge: 60, // 1 minute by default
|
||||
BypassHeader: "X-Cache-Bypass",
|
||||
BypassValue: "true",
|
||||
CacheableStatusCodes: []int{
|
||||
200, 301, 302,
|
||||
},
|
||||
CacheableContentTypes: []string{
|
||||
"text/html",
|
||||
"text/css",
|
||||
"text/javascript",
|
||||
"application/javascript",
|
||||
"application/json",
|
||||
"image/jpeg",
|
||||
"image/png",
|
||||
"image/gif",
|
||||
"image/webp",
|
||||
},
|
||||
}
|
||||
|
||||
// Override with environment variables if provided
|
||||
if enabled := cloudflare.Getenv("CACHE_ENABLED"); enabled != "" {
|
||||
config.Enabled = enabled == "true"
|
||||
}
|
||||
|
||||
if maxAge := cloudflare.Getenv("CACHE_DEFAULT_MAX_AGE"); maxAge != "" {
|
||||
// Parse the string to int, defaulting to 60 if parsing fails
|
||||
if parsed, err := strconv.Atoi(maxAge); err == nil {
|
||||
config.DefaultMaxAge = parsed
|
||||
}
|
||||
}
|
||||
|
||||
if bypassHeader := cloudflare.Getenv("CACHE_BYPASS_HEADER"); bypassHeader != "" {
|
||||
config.BypassHeader = bypassHeader
|
||||
}
|
||||
|
||||
if bypassValue := cloudflare.Getenv("CACHE_BYPASS_VALUE"); bypassValue != "" {
|
||||
config.BypassValue = bypassValue
|
||||
}
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
type KVConfig struct {
|
||||
Sessions string `json:"sessions"`
|
||||
Handles string `json:"handles"`
|
||||
DefaultExpiry time.Duration `json:"expiry"`
|
||||
}
|
||||
|
||||
func getKVConfig() KVConfig {
|
||||
return KVConfig{
|
||||
Sessions: "SESSIONS",
|
||||
Handles: "HANDLES",
|
||||
DefaultExpiry: time.Hour * 1, // 1 hour by default
|
||||
}
|
||||
}
|
||||
|
||||
func (c KVConfig) GetSessionExpiry(t time.Time) int64 {
|
||||
return c.DefaultExpiry.Nanoseconds() + t.UnixNano()
|
||||
}
|
||||
|
||||
func (c KVConfig) GetSessions() (*kv.Namespace, error) {
|
||||
return kv.NewNamespace(c.Sessions)
|
||||
}
|
||||
|
||||
func (c KVConfig) GetHandles() (*kv.Namespace, error) {
|
||||
return kv.NewNamespace(c.Handles)
|
||||
}
|
||||
12
internal/config/errors.go
Normal file
12
internal/config/errors.go
Normal file
@@ -0,0 +1,12 @@
|
||||
package config
|
||||
|
||||
import "errors"
|
||||
|
||||
func newError(msg string) error {
|
||||
return errors.New(msg)
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidMode = newError("invalid mode")
|
||||
ErrDBNotFound = newError("db not found")
|
||||
)
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user