mirror of
https://github.com/cf-sonr/motr.git
synced 2026-01-12 02:59:13 +00:00
feat: introduce modular architecture for enhanced feature isolation
This commit is contained in:
@@ -3,6 +3,9 @@
|
||||
version: "3"
|
||||
silent: true
|
||||
|
||||
includes:
|
||||
generate: { taskfile: ./Generate.yml, flatten: true }
|
||||
|
||||
vars:
|
||||
ROOT_DIR:
|
||||
sh: git rev-parse --show-toplevel
|
||||
@@ -27,14 +30,7 @@ tasks:
|
||||
- defer: rm -rf .task
|
||||
- task: build:go
|
||||
# - task: build:docker
|
||||
|
||||
gen:
|
||||
desc: Generates code
|
||||
cmds:
|
||||
- defer: rm -rf .task
|
||||
- task: gen:templ
|
||||
- task: gen:sqlc
|
||||
|
||||
#
|
||||
clean:
|
||||
cmds:
|
||||
- rm -rf bin
|
||||
@@ -73,30 +69,6 @@ tasks:
|
||||
cmds:
|
||||
- go build -o bin/motr.wasm .
|
||||
|
||||
gen:templ:
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
sources:
|
||||
- "**/*.templ"
|
||||
generates:
|
||||
- "**/_templ.go"
|
||||
cmds:
|
||||
- templ generate
|
||||
|
||||
gen:sqlc:
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}/internal/sink"
|
||||
sources:
|
||||
- "**/query.sql"
|
||||
- "**/schema.sql"
|
||||
generates:
|
||||
- "**/db.go"
|
||||
- "**/querier.go"
|
||||
- "**/models.go"
|
||||
- "**/query.sql.go"
|
||||
cmds:
|
||||
- sqlc generate
|
||||
|
||||
test:go:
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
|
||||
54
.taskfiles/Generate.yml
Normal file
54
.taskfiles/Generate.yml
Normal file
@@ -0,0 +1,54 @@
|
||||
# yaml-language-server: $schema=https://taskfile.dev/schema.json
|
||||
|
||||
version: "3"
|
||||
silent: true
|
||||
|
||||
vars:
|
||||
ROOT_DIR:
|
||||
sh: git rev-parse --show-toplevel
|
||||
|
||||
tasks:
|
||||
gen:
|
||||
desc: Generates code
|
||||
sources:
|
||||
- "x/account"
|
||||
- "x/asset"
|
||||
- "x/balance"
|
||||
- "x/credential"
|
||||
- "x/device"
|
||||
- "x/profile"
|
||||
- "x/session"
|
||||
- "x/vault"
|
||||
cmds:
|
||||
- defer: rm -rf .task
|
||||
- task: gen:templ
|
||||
- for: sources
|
||||
task: gen:sqlc
|
||||
vars:
|
||||
PATH: "{{.ITEM}}"
|
||||
|
||||
gen:templ:
|
||||
internal: true
|
||||
dir: "{{.ROOT_DIR}}"
|
||||
sources:
|
||||
- "**/*.templ"
|
||||
generates:
|
||||
- "**/_templ.go"
|
||||
cmds:
|
||||
- templ generate
|
||||
|
||||
gen:sqlc:
|
||||
internal: true
|
||||
requires:
|
||||
vars: [PATH]
|
||||
dir: "{{.PATH}}"
|
||||
sources:
|
||||
- "**/query.sql"
|
||||
- "**/schema.sql"
|
||||
generates:
|
||||
- "**/db.go"
|
||||
- "**/querier.go"
|
||||
- "**/models.go"
|
||||
- "**/query.sql.go"
|
||||
cmds:
|
||||
- sqlc generate
|
||||
@@ -40,6 +40,20 @@ type Asset struct {
|
||||
CoingeckoID sql.NullString `json:"coingecko_id"`
|
||||
}
|
||||
|
||||
type Balance struct {
|
||||
ID string `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt sql.NullTime `json:"deleted_at"`
|
||||
AccountID string `json:"account_id"`
|
||||
AssetID string `json:"asset_id"`
|
||||
Amount string `json:"amount"`
|
||||
LastUpdatedHeight int64 `json:"last_updated_height"`
|
||||
IsDelegated bool `json:"is_delegated"`
|
||||
IsStaked bool `json:"is_staked"`
|
||||
IsVesting bool `json:"is_vesting"`
|
||||
}
|
||||
|
||||
type Credential struct {
|
||||
ID string `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
@@ -53,6 +67,27 @@ type Credential struct {
|
||||
Transports string `json:"transports"`
|
||||
}
|
||||
|
||||
type Device struct {
|
||||
ID string `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
DeletedAt sql.NullTime `json:"deleted_at"`
|
||||
ProfileID string `json:"profile_id"`
|
||||
CredentialID string `json:"credential_id"`
|
||||
Name string `json:"name"`
|
||||
DeviceType string `json:"device_type"`
|
||||
OsName string `json:"os_name"`
|
||||
OsVersion string `json:"os_version"`
|
||||
BrowserName sql.NullString `json:"browser_name"`
|
||||
BrowserVersion sql.NullString `json:"browser_version"`
|
||||
LastUsedAt time.Time `json:"last_used_at"`
|
||||
IsTrusted bool `json:"is_trusted"`
|
||||
IsCurrent bool `json:"is_current"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
UserAgent sql.NullString `json:"user_agent"`
|
||||
IpAddress sql.NullString `json:"ip_address"`
|
||||
}
|
||||
|
||||
type Profile struct {
|
||||
ID string `json:"id"`
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
|
||||
@@ -10,22 +10,41 @@ import (
|
||||
|
||||
type Querier interface {
|
||||
CheckHandleExists(ctx context.Context, handle string) (bool, error)
|
||||
// Balance table methods
|
||||
CreateBalance(ctx context.Context, arg CreateBalanceParams) (Balance, error)
|
||||
// Device table methods
|
||||
CreateDevice(ctx context.Context, arg CreateDeviceParams) (Device, error)
|
||||
CreateSession(ctx context.Context, arg CreateSessionParams) (Session, error)
|
||||
GetBalanceByAccountAndAsset(ctx context.Context, arg GetBalanceByAccountAndAssetParams) (Balance, error)
|
||||
GetBalanceByID(ctx context.Context, id string) (Balance, error)
|
||||
GetChallengeBySessionID(ctx context.Context, id string) (string, error)
|
||||
GetCredentialByID(ctx context.Context, credentialID string) (Credential, error)
|
||||
GetCredentialsByHandle(ctx context.Context, handle string) ([]Credential, error)
|
||||
GetCredentialsByProfile(ctx context.Context, profileID string) ([]Credential, error)
|
||||
GetDeviceByFingerprint(ctx context.Context, arg GetDeviceByFingerprintParams) (Device, error)
|
||||
GetDeviceByID(ctx context.Context, id string) (Device, error)
|
||||
GetHumanVerificationNumbers(ctx context.Context, id string) (GetHumanVerificationNumbersRow, error)
|
||||
GetProfileByAddress(ctx context.Context, address string) (Profile, error)
|
||||
GetProfileByHandle(ctx context.Context, handle string) (Profile, error)
|
||||
GetProfileByID(ctx context.Context, id string) (Profile, error)
|
||||
GetSessionByClientIP(ctx context.Context, clientIpaddr string) (Session, error)
|
||||
GetSessionByID(ctx context.Context, id string) (Session, error)
|
||||
GetTrustedDevicesByProfile(ctx context.Context, profileID string) ([]Device, error)
|
||||
GetVaultConfigByCID(ctx context.Context, cid string) (Vault, error)
|
||||
GetVaultRedirectURIBySessionID(ctx context.Context, sessionID string) (string, error)
|
||||
InsertCredential(ctx context.Context, arg InsertCredentialParams) (Credential, error)
|
||||
InsertProfile(ctx context.Context, arg InsertProfileParams) (Profile, error)
|
||||
ListBalancesByAccount(ctx context.Context, accountID string) ([]Balance, error)
|
||||
ListDevicesByProfile(ctx context.Context, profileID string) ([]Device, error)
|
||||
SoftDeleteBalance(ctx context.Context, id string) error
|
||||
SoftDeleteCredential(ctx context.Context, credentialID string) error
|
||||
SoftDeleteDevice(ctx context.Context, id string) error
|
||||
SoftDeleteProfile(ctx context.Context, address string) error
|
||||
UpdateBalance(ctx context.Context, arg UpdateBalanceParams) (Balance, error)
|
||||
// Additional credential methods for better integration with devices
|
||||
UpdateCredential(ctx context.Context, arg UpdateCredentialParams) (Credential, error)
|
||||
UpdateDevice(ctx context.Context, arg UpdateDeviceParams) (Device, error)
|
||||
UpdateDeviceLastUsed(ctx context.Context, arg UpdateDeviceLastUsedParams) (Device, error)
|
||||
UpdateProfile(ctx context.Context, arg UpdateProfileParams) (Profile, error)
|
||||
UpdateSessionHumanVerification(ctx context.Context, arg UpdateSessionHumanVerificationParams) (Session, error)
|
||||
UpdateSessionWithProfileID(ctx context.Context, arg UpdateSessionWithProfileIDParams) (Session, error)
|
||||
|
||||
@@ -7,6 +7,7 @@ package models
|
||||
|
||||
import (
|
||||
"context"
|
||||
"database/sql"
|
||||
)
|
||||
|
||||
const checkHandleExists = `-- name: CheckHandleExists :one
|
||||
@@ -22,6 +23,139 @@ func (q *Queries) CheckHandleExists(ctx context.Context, handle string) (bool, e
|
||||
return handle_exists, err
|
||||
}
|
||||
|
||||
const createBalance = `-- name: CreateBalance :one
|
||||
INSERT INTO balances (
|
||||
id,
|
||||
account_id,
|
||||
asset_id,
|
||||
amount,
|
||||
last_updated_height,
|
||||
is_delegated,
|
||||
is_staked,
|
||||
is_vesting
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING id, created_at, updated_at, deleted_at, account_id, asset_id, amount, last_updated_height, is_delegated, is_staked, is_vesting
|
||||
`
|
||||
|
||||
type CreateBalanceParams struct {
|
||||
ID string `json:"id"`
|
||||
AccountID string `json:"account_id"`
|
||||
AssetID string `json:"asset_id"`
|
||||
Amount string `json:"amount"`
|
||||
LastUpdatedHeight int64 `json:"last_updated_height"`
|
||||
IsDelegated bool `json:"is_delegated"`
|
||||
IsStaked bool `json:"is_staked"`
|
||||
IsVesting bool `json:"is_vesting"`
|
||||
}
|
||||
|
||||
// Balance table methods
|
||||
func (q *Queries) CreateBalance(ctx context.Context, arg CreateBalanceParams) (Balance, error) {
|
||||
row := q.db.QueryRowContext(ctx, createBalance,
|
||||
arg.ID,
|
||||
arg.AccountID,
|
||||
arg.AssetID,
|
||||
arg.Amount,
|
||||
arg.LastUpdatedHeight,
|
||||
arg.IsDelegated,
|
||||
arg.IsStaked,
|
||||
arg.IsVesting,
|
||||
)
|
||||
var i Balance
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.AccountID,
|
||||
&i.AssetID,
|
||||
&i.Amount,
|
||||
&i.LastUpdatedHeight,
|
||||
&i.IsDelegated,
|
||||
&i.IsStaked,
|
||||
&i.IsVesting,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createDevice = `-- name: CreateDevice :one
|
||||
INSERT INTO devices (
|
||||
id,
|
||||
profile_id,
|
||||
credential_id,
|
||||
name,
|
||||
device_type,
|
||||
os_name,
|
||||
os_version,
|
||||
browser_name,
|
||||
browser_version,
|
||||
is_trusted,
|
||||
is_current,
|
||||
fingerprint,
|
||||
user_agent,
|
||||
ip_address
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING id, created_at, updated_at, deleted_at, profile_id, credential_id, name, device_type, os_name, os_version, browser_name, browser_version, last_used_at, is_trusted, is_current, fingerprint, user_agent, ip_address
|
||||
`
|
||||
|
||||
type CreateDeviceParams struct {
|
||||
ID string `json:"id"`
|
||||
ProfileID string `json:"profile_id"`
|
||||
CredentialID string `json:"credential_id"`
|
||||
Name string `json:"name"`
|
||||
DeviceType string `json:"device_type"`
|
||||
OsName string `json:"os_name"`
|
||||
OsVersion string `json:"os_version"`
|
||||
BrowserName sql.NullString `json:"browser_name"`
|
||||
BrowserVersion sql.NullString `json:"browser_version"`
|
||||
IsTrusted bool `json:"is_trusted"`
|
||||
IsCurrent bool `json:"is_current"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
UserAgent sql.NullString `json:"user_agent"`
|
||||
IpAddress sql.NullString `json:"ip_address"`
|
||||
}
|
||||
|
||||
// Device table methods
|
||||
func (q *Queries) CreateDevice(ctx context.Context, arg CreateDeviceParams) (Device, error) {
|
||||
row := q.db.QueryRowContext(ctx, createDevice,
|
||||
arg.ID,
|
||||
arg.ProfileID,
|
||||
arg.CredentialID,
|
||||
arg.Name,
|
||||
arg.DeviceType,
|
||||
arg.OsName,
|
||||
arg.OsVersion,
|
||||
arg.BrowserName,
|
||||
arg.BrowserVersion,
|
||||
arg.IsTrusted,
|
||||
arg.IsCurrent,
|
||||
arg.Fingerprint,
|
||||
arg.UserAgent,
|
||||
arg.IpAddress,
|
||||
)
|
||||
var i Device
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.ProfileID,
|
||||
&i.CredentialID,
|
||||
&i.Name,
|
||||
&i.DeviceType,
|
||||
&i.OsName,
|
||||
&i.OsVersion,
|
||||
&i.BrowserName,
|
||||
&i.BrowserVersion,
|
||||
&i.LastUsedAt,
|
||||
&i.IsTrusted,
|
||||
&i.IsCurrent,
|
||||
&i.Fingerprint,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const createSession = `-- name: CreateSession :one
|
||||
INSERT INTO sessions (
|
||||
id,
|
||||
@@ -99,6 +233,61 @@ func (q *Queries) CreateSession(ctx context.Context, arg CreateSessionParams) (S
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getBalanceByAccountAndAsset = `-- name: GetBalanceByAccountAndAsset :one
|
||||
SELECT id, created_at, updated_at, deleted_at, account_id, asset_id, amount, last_updated_height, is_delegated, is_staked, is_vesting FROM balances
|
||||
WHERE account_id = ? AND asset_id = ? AND deleted_at IS NULL
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetBalanceByAccountAndAssetParams struct {
|
||||
AccountID string `json:"account_id"`
|
||||
AssetID string `json:"asset_id"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetBalanceByAccountAndAsset(ctx context.Context, arg GetBalanceByAccountAndAssetParams) (Balance, error) {
|
||||
row := q.db.QueryRowContext(ctx, getBalanceByAccountAndAsset, arg.AccountID, arg.AssetID)
|
||||
var i Balance
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.AccountID,
|
||||
&i.AssetID,
|
||||
&i.Amount,
|
||||
&i.LastUpdatedHeight,
|
||||
&i.IsDelegated,
|
||||
&i.IsStaked,
|
||||
&i.IsVesting,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getBalanceByID = `-- name: GetBalanceByID :one
|
||||
SELECT id, created_at, updated_at, deleted_at, account_id, asset_id, amount, last_updated_height, is_delegated, is_staked, is_vesting FROM balances
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetBalanceByID(ctx context.Context, id string) (Balance, error) {
|
||||
row := q.db.QueryRowContext(ctx, getBalanceByID, id)
|
||||
var i Balance
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.AccountID,
|
||||
&i.AssetID,
|
||||
&i.Amount,
|
||||
&i.LastUpdatedHeight,
|
||||
&i.IsDelegated,
|
||||
&i.IsStaked,
|
||||
&i.IsVesting,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getChallengeBySessionID = `-- name: GetChallengeBySessionID :one
|
||||
SELECT challenge FROM sessions
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
@@ -177,6 +366,115 @@ func (q *Queries) GetCredentialsByHandle(ctx context.Context, handle string) ([]
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getCredentialsByProfile = `-- name: GetCredentialsByProfile :many
|
||||
SELECT c.id, c.created_at, c.updated_at, c.deleted_at, c.handle, c.credential_id, c.authenticator_attachment, c.origin, c.type, c.transports FROM credentials c
|
||||
JOIN devices d ON c.credential_id = d.credential_id
|
||||
WHERE d.profile_id = ? AND c.deleted_at IS NULL AND d.deleted_at IS NULL
|
||||
`
|
||||
|
||||
func (q *Queries) GetCredentialsByProfile(ctx context.Context, profileID string) ([]Credential, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getCredentialsByProfile, profileID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Credential
|
||||
for rows.Next() {
|
||||
var i Credential
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.Handle,
|
||||
&i.CredentialID,
|
||||
&i.AuthenticatorAttachment,
|
||||
&i.Origin,
|
||||
&i.Type,
|
||||
&i.Transports,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getDeviceByFingerprint = `-- name: GetDeviceByFingerprint :one
|
||||
SELECT id, created_at, updated_at, deleted_at, profile_id, credential_id, name, device_type, os_name, os_version, browser_name, browser_version, last_used_at, is_trusted, is_current, fingerprint, user_agent, ip_address FROM devices
|
||||
WHERE profile_id = ? AND fingerprint = ? AND deleted_at IS NULL
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
type GetDeviceByFingerprintParams struct {
|
||||
ProfileID string `json:"profile_id"`
|
||||
Fingerprint string `json:"fingerprint"`
|
||||
}
|
||||
|
||||
func (q *Queries) GetDeviceByFingerprint(ctx context.Context, arg GetDeviceByFingerprintParams) (Device, error) {
|
||||
row := q.db.QueryRowContext(ctx, getDeviceByFingerprint, arg.ProfileID, arg.Fingerprint)
|
||||
var i Device
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.ProfileID,
|
||||
&i.CredentialID,
|
||||
&i.Name,
|
||||
&i.DeviceType,
|
||||
&i.OsName,
|
||||
&i.OsVersion,
|
||||
&i.BrowserName,
|
||||
&i.BrowserVersion,
|
||||
&i.LastUsedAt,
|
||||
&i.IsTrusted,
|
||||
&i.IsCurrent,
|
||||
&i.Fingerprint,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getDeviceByID = `-- name: GetDeviceByID :one
|
||||
SELECT id, created_at, updated_at, deleted_at, profile_id, credential_id, name, device_type, os_name, os_version, browser_name, browser_version, last_used_at, is_trusted, is_current, fingerprint, user_agent, ip_address FROM devices
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
LIMIT 1
|
||||
`
|
||||
|
||||
func (q *Queries) GetDeviceByID(ctx context.Context, id string) (Device, error) {
|
||||
row := q.db.QueryRowContext(ctx, getDeviceByID, id)
|
||||
var i Device
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.ProfileID,
|
||||
&i.CredentialID,
|
||||
&i.Name,
|
||||
&i.DeviceType,
|
||||
&i.OsName,
|
||||
&i.OsVersion,
|
||||
&i.BrowserName,
|
||||
&i.BrowserVersion,
|
||||
&i.LastUsedAt,
|
||||
&i.IsTrusted,
|
||||
&i.IsCurrent,
|
||||
&i.Fingerprint,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getHumanVerificationNumbers = `-- name: GetHumanVerificationNumbers :one
|
||||
SELECT is_human_first, is_human_last FROM sessions
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
@@ -324,6 +622,54 @@ func (q *Queries) GetSessionByID(ctx context.Context, id string) (Session, error
|
||||
return i, err
|
||||
}
|
||||
|
||||
const getTrustedDevicesByProfile = `-- name: GetTrustedDevicesByProfile :many
|
||||
SELECT id, created_at, updated_at, deleted_at, profile_id, credential_id, name, device_type, os_name, os_version, browser_name, browser_version, last_used_at, is_trusted, is_current, fingerprint, user_agent, ip_address FROM devices
|
||||
WHERE profile_id = ? AND is_trusted = true AND deleted_at IS NULL
|
||||
ORDER BY last_used_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) GetTrustedDevicesByProfile(ctx context.Context, profileID string) ([]Device, error) {
|
||||
rows, err := q.db.QueryContext(ctx, getTrustedDevicesByProfile, profileID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Device
|
||||
for rows.Next() {
|
||||
var i Device
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.ProfileID,
|
||||
&i.CredentialID,
|
||||
&i.Name,
|
||||
&i.DeviceType,
|
||||
&i.OsName,
|
||||
&i.OsVersion,
|
||||
&i.BrowserName,
|
||||
&i.BrowserVersion,
|
||||
&i.LastUsedAt,
|
||||
&i.IsTrusted,
|
||||
&i.IsCurrent,
|
||||
&i.Fingerprint,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const getVaultConfigByCID = `-- name: GetVaultConfigByCID :one
|
||||
SELECT id, created_at, updated_at, deleted_at, handle, origin, address, cid, config, session_id, redirect_uri FROM vaults
|
||||
WHERE cid = ?
|
||||
@@ -445,6 +791,106 @@ func (q *Queries) InsertProfile(ctx context.Context, arg InsertProfileParams) (P
|
||||
return i, err
|
||||
}
|
||||
|
||||
const listBalancesByAccount = `-- name: ListBalancesByAccount :many
|
||||
SELECT id, created_at, updated_at, deleted_at, account_id, asset_id, amount, last_updated_height, is_delegated, is_staked, is_vesting FROM balances
|
||||
WHERE account_id = ? AND deleted_at IS NULL
|
||||
ORDER BY asset_id
|
||||
`
|
||||
|
||||
func (q *Queries) ListBalancesByAccount(ctx context.Context, accountID string) ([]Balance, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listBalancesByAccount, accountID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Balance
|
||||
for rows.Next() {
|
||||
var i Balance
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.AccountID,
|
||||
&i.AssetID,
|
||||
&i.Amount,
|
||||
&i.LastUpdatedHeight,
|
||||
&i.IsDelegated,
|
||||
&i.IsStaked,
|
||||
&i.IsVesting,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const listDevicesByProfile = `-- name: ListDevicesByProfile :many
|
||||
SELECT id, created_at, updated_at, deleted_at, profile_id, credential_id, name, device_type, os_name, os_version, browser_name, browser_version, last_used_at, is_trusted, is_current, fingerprint, user_agent, ip_address FROM devices
|
||||
WHERE profile_id = ? AND deleted_at IS NULL
|
||||
ORDER BY last_used_at DESC
|
||||
`
|
||||
|
||||
func (q *Queries) ListDevicesByProfile(ctx context.Context, profileID string) ([]Device, error) {
|
||||
rows, err := q.db.QueryContext(ctx, listDevicesByProfile, profileID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer rows.Close()
|
||||
var items []Device
|
||||
for rows.Next() {
|
||||
var i Device
|
||||
if err := rows.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.ProfileID,
|
||||
&i.CredentialID,
|
||||
&i.Name,
|
||||
&i.DeviceType,
|
||||
&i.OsName,
|
||||
&i.OsVersion,
|
||||
&i.BrowserName,
|
||||
&i.BrowserVersion,
|
||||
&i.LastUsedAt,
|
||||
&i.IsTrusted,
|
||||
&i.IsCurrent,
|
||||
&i.Fingerprint,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
items = append(items, i)
|
||||
}
|
||||
if err := rows.Close(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if err := rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return items, nil
|
||||
}
|
||||
|
||||
const softDeleteBalance = `-- name: SoftDeleteBalance :exec
|
||||
UPDATE balances
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) SoftDeleteBalance(ctx context.Context, id string) error {
|
||||
_, err := q.db.ExecContext(ctx, softDeleteBalance, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const softDeleteCredential = `-- name: SoftDeleteCredential :exec
|
||||
UPDATE credentials
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
@@ -456,6 +902,17 @@ func (q *Queries) SoftDeleteCredential(ctx context.Context, credentialID string)
|
||||
return err
|
||||
}
|
||||
|
||||
const softDeleteDevice = `-- name: SoftDeleteDevice :exec
|
||||
UPDATE devices
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?
|
||||
`
|
||||
|
||||
func (q *Queries) SoftDeleteDevice(ctx context.Context, id string) error {
|
||||
_, err := q.db.ExecContext(ctx, softDeleteDevice, id)
|
||||
return err
|
||||
}
|
||||
|
||||
const softDeleteProfile = `-- name: SoftDeleteProfile :exec
|
||||
UPDATE profiles
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
@@ -467,6 +924,180 @@ func (q *Queries) SoftDeleteProfile(ctx context.Context, address string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
const updateBalance = `-- name: UpdateBalance :one
|
||||
UPDATE balances
|
||||
SET
|
||||
amount = ?,
|
||||
last_updated_height = ?,
|
||||
is_delegated = ?,
|
||||
is_staked = ?,
|
||||
is_vesting = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING id, created_at, updated_at, deleted_at, account_id, asset_id, amount, last_updated_height, is_delegated, is_staked, is_vesting
|
||||
`
|
||||
|
||||
type UpdateBalanceParams struct {
|
||||
Amount string `json:"amount"`
|
||||
LastUpdatedHeight int64 `json:"last_updated_height"`
|
||||
IsDelegated bool `json:"is_delegated"`
|
||||
IsStaked bool `json:"is_staked"`
|
||||
IsVesting bool `json:"is_vesting"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateBalance(ctx context.Context, arg UpdateBalanceParams) (Balance, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateBalance,
|
||||
arg.Amount,
|
||||
arg.LastUpdatedHeight,
|
||||
arg.IsDelegated,
|
||||
arg.IsStaked,
|
||||
arg.IsVesting,
|
||||
arg.ID,
|
||||
)
|
||||
var i Balance
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.AccountID,
|
||||
&i.AssetID,
|
||||
&i.Amount,
|
||||
&i.LastUpdatedHeight,
|
||||
&i.IsDelegated,
|
||||
&i.IsStaked,
|
||||
&i.IsVesting,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateCredential = `-- name: UpdateCredential :one
|
||||
UPDATE credentials
|
||||
SET
|
||||
authenticator_attachment = ?,
|
||||
transports = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE credential_id = ? AND deleted_at IS NULL
|
||||
RETURNING id, created_at, updated_at, deleted_at, handle, credential_id, authenticator_attachment, origin, type, transports
|
||||
`
|
||||
|
||||
type UpdateCredentialParams struct {
|
||||
AuthenticatorAttachment string `json:"authenticator_attachment"`
|
||||
Transports string `json:"transports"`
|
||||
CredentialID string `json:"credential_id"`
|
||||
}
|
||||
|
||||
// Additional credential methods for better integration with devices
|
||||
func (q *Queries) UpdateCredential(ctx context.Context, arg UpdateCredentialParams) (Credential, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateCredential, arg.AuthenticatorAttachment, arg.Transports, arg.CredentialID)
|
||||
var i Credential
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.Handle,
|
||||
&i.CredentialID,
|
||||
&i.AuthenticatorAttachment,
|
||||
&i.Origin,
|
||||
&i.Type,
|
||||
&i.Transports,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateDevice = `-- name: UpdateDevice :one
|
||||
UPDATE devices
|
||||
SET
|
||||
name = ?,
|
||||
is_trusted = ?,
|
||||
is_current = ?,
|
||||
last_used_at = CURRENT_TIMESTAMP,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING id, created_at, updated_at, deleted_at, profile_id, credential_id, name, device_type, os_name, os_version, browser_name, browser_version, last_used_at, is_trusted, is_current, fingerprint, user_agent, ip_address
|
||||
`
|
||||
|
||||
type UpdateDeviceParams struct {
|
||||
Name string `json:"name"`
|
||||
IsTrusted bool `json:"is_trusted"`
|
||||
IsCurrent bool `json:"is_current"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateDevice(ctx context.Context, arg UpdateDeviceParams) (Device, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateDevice,
|
||||
arg.Name,
|
||||
arg.IsTrusted,
|
||||
arg.IsCurrent,
|
||||
arg.ID,
|
||||
)
|
||||
var i Device
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.ProfileID,
|
||||
&i.CredentialID,
|
||||
&i.Name,
|
||||
&i.DeviceType,
|
||||
&i.OsName,
|
||||
&i.OsVersion,
|
||||
&i.BrowserName,
|
||||
&i.BrowserVersion,
|
||||
&i.LastUsedAt,
|
||||
&i.IsTrusted,
|
||||
&i.IsCurrent,
|
||||
&i.Fingerprint,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateDeviceLastUsed = `-- name: UpdateDeviceLastUsed :one
|
||||
UPDATE devices
|
||||
SET
|
||||
last_used_at = CURRENT_TIMESTAMP,
|
||||
ip_address = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING id, created_at, updated_at, deleted_at, profile_id, credential_id, name, device_type, os_name, os_version, browser_name, browser_version, last_used_at, is_trusted, is_current, fingerprint, user_agent, ip_address
|
||||
`
|
||||
|
||||
type UpdateDeviceLastUsedParams struct {
|
||||
IpAddress sql.NullString `json:"ip_address"`
|
||||
ID string `json:"id"`
|
||||
}
|
||||
|
||||
func (q *Queries) UpdateDeviceLastUsed(ctx context.Context, arg UpdateDeviceLastUsedParams) (Device, error) {
|
||||
row := q.db.QueryRowContext(ctx, updateDeviceLastUsed, arg.IpAddress, arg.ID)
|
||||
var i Device
|
||||
err := row.Scan(
|
||||
&i.ID,
|
||||
&i.CreatedAt,
|
||||
&i.UpdatedAt,
|
||||
&i.DeletedAt,
|
||||
&i.ProfileID,
|
||||
&i.CredentialID,
|
||||
&i.Name,
|
||||
&i.DeviceType,
|
||||
&i.OsName,
|
||||
&i.OsVersion,
|
||||
&i.BrowserName,
|
||||
&i.BrowserVersion,
|
||||
&i.LastUsedAt,
|
||||
&i.IsTrusted,
|
||||
&i.IsCurrent,
|
||||
&i.Fingerprint,
|
||||
&i.UserAgent,
|
||||
&i.IpAddress,
|
||||
)
|
||||
return i, err
|
||||
}
|
||||
|
||||
const updateProfile = `-- name: UpdateProfile :one
|
||||
UPDATE profiles
|
||||
SET
|
||||
|
||||
1
x/account/controller.go
Normal file
1
x/account/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package account
|
||||
9
x/account/model.go
Normal file
9
x/account/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package account
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Account = models.Account
|
||||
|
||||
type AccountModel interface{}
|
||||
|
||||
type AccountViewModel struct{}
|
||||
0
x/account/query.sql
Normal file
0
x/account/query.sql
Normal file
24
x/account/schema.sql
Normal file
24
x/account/schema.sql
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
-- 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,
|
||||
chain_id TEXT NOT NULL,
|
||||
controller 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))
|
||||
);
|
||||
|
||||
CREATE INDEX idx_accounts_address ON accounts(address);
|
||||
CREATE INDEX idx_accounts_chain_id ON accounts(chain_id);
|
||||
CREATE INDEX idx_accounts_deleted_at ON accounts(deleted_at);
|
||||
|
||||
|
||||
11
x/account/sqlc.yaml
Normal file
11
x/account/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "account"
|
||||
out: "orm.gen.go"
|
||||
11
x/account/view.templ
Normal file
11
x/account/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package account
|
||||
|
||||
func View(a *AccountViewModel) templ.Component {
|
||||
return initialAccountView(a)
|
||||
}
|
||||
|
||||
templ initialAccountView(a *AccountViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/account/view_templ.go
Normal file
44
x/account/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// 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 View(a *AccountViewModel) templ.Component {
|
||||
return initialAccountView(a)
|
||||
}
|
||||
|
||||
func initialAccountView(a *AccountViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
1
x/asset/controller.go
Normal file
1
x/asset/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package asset
|
||||
9
x/asset/model.go
Normal file
9
x/asset/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package asset
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Asset = models.Asset
|
||||
|
||||
type AssetModel interface{}
|
||||
|
||||
type AssetViewModel struct{}
|
||||
0
x/asset/query.sql
Normal file
0
x/asset/query.sql
Normal file
22
x/asset/schema.sql
Normal file
22
x/asset/schema.sql
Normal file
@@ -0,0 +1,22 @@
|
||||
|
||||
-- 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)
|
||||
);
|
||||
|
||||
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);
|
||||
|
||||
|
||||
11
x/asset/sqlc.yaml
Normal file
11
x/asset/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "asset"
|
||||
out: "orm.gen.go"
|
||||
11
x/asset/view.templ
Normal file
11
x/asset/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package asset
|
||||
|
||||
func View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
templ initialAssetView(a *AssetViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/asset/view_templ.go
Normal file
44
x/asset/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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 View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
func initialAssetView(a *AssetViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
1
x/balance/controller.go
Normal file
1
x/balance/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package balance
|
||||
9
x/balance/model.go
Normal file
9
x/balance/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package balance
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Asset = models.Asset
|
||||
|
||||
type AssetModel interface{}
|
||||
|
||||
type AssetViewModel struct{}
|
||||
48
x/balance/query.sql
Normal file
48
x/balance/query.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
-- Balance table methods
|
||||
-- name: CreateBalance :one
|
||||
INSERT INTO balances (
|
||||
id,
|
||||
account_id,
|
||||
asset_id,
|
||||
amount,
|
||||
last_updated_height,
|
||||
is_delegated,
|
||||
is_staked,
|
||||
is_vesting
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetBalanceByID :one
|
||||
SELECT * FROM balances
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetBalanceByAccountAndAsset :one
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND asset_id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListBalancesByAccount :many
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND deleted_at IS NULL
|
||||
ORDER BY asset_id;
|
||||
|
||||
-- name: UpdateBalance :one
|
||||
UPDATE balances
|
||||
SET
|
||||
amount = ?,
|
||||
last_updated_height = ?,
|
||||
is_delegated = ?,
|
||||
is_staked = ?,
|
||||
is_vesting = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: SoftDeleteBalance :exec
|
||||
UPDATE balances
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?;
|
||||
|
||||
|
||||
23
x/balance/schema.sql
Normal file
23
x/balance/schema.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- Balances track asset holdings for accounts
|
||||
CREATE TABLE balances (
|
||||
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,
|
||||
asset_id TEXT NOT NULL,
|
||||
amount TEXT NOT NULL, -- Stored as string to handle large decimal numbers precisely
|
||||
last_updated_height INTEGER NOT NULL DEFAULT 0,
|
||||
is_delegated BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_delegated IN (0,1)),
|
||||
is_staked BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_staked IN (0,1)),
|
||||
is_vesting BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_vesting IN (0,1)),
|
||||
FOREIGN KEY (account_id) REFERENCES accounts(id),
|
||||
FOREIGN KEY (asset_id) REFERENCES assets(id),
|
||||
UNIQUE(account_id, asset_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_balances_account_id ON balances(account_id);
|
||||
CREATE INDEX idx_balances_asset_id ON balances(asset_id);
|
||||
CREATE INDEX idx_balances_deleted_at ON balances(deleted_at);
|
||||
|
||||
|
||||
11
x/balance/sqlc.yaml
Normal file
11
x/balance/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "balance"
|
||||
out: "orm.gen.go"
|
||||
11
x/balance/view.templ
Normal file
11
x/balance/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package asset
|
||||
|
||||
func View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
templ initialAssetView(a *AssetViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/balance/view_templ.go
Normal file
44
x/balance/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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 View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
func initialAssetView(a *AssetViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
1
x/credential/controller.go
Normal file
1
x/credential/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package balance
|
||||
9
x/credential/model.go
Normal file
9
x/credential/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package balance
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Asset = models.Asset
|
||||
|
||||
type AssetModel interface{}
|
||||
|
||||
type AssetViewModel struct{}
|
||||
48
x/credential/query.sql
Normal file
48
x/credential/query.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
-- Balance table methods
|
||||
-- name: CreateBalance :one
|
||||
INSERT INTO balances (
|
||||
id,
|
||||
account_id,
|
||||
asset_id,
|
||||
amount,
|
||||
last_updated_height,
|
||||
is_delegated,
|
||||
is_staked,
|
||||
is_vesting
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetBalanceByID :one
|
||||
SELECT * FROM balances
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetBalanceByAccountAndAsset :one
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND asset_id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListBalancesByAccount :many
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND deleted_at IS NULL
|
||||
ORDER BY asset_id;
|
||||
|
||||
-- name: UpdateBalance :one
|
||||
UPDATE balances
|
||||
SET
|
||||
amount = ?,
|
||||
last_updated_height = ?,
|
||||
is_delegated = ?,
|
||||
is_staked = ?,
|
||||
is_vesting = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: SoftDeleteBalance :exec
|
||||
UPDATE balances
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?;
|
||||
|
||||
|
||||
23
x/credential/schema.sql
Normal file
23
x/credential/schema.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- Balances track asset holdings for accounts
|
||||
CREATE TABLE balances (
|
||||
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,
|
||||
asset_id TEXT NOT NULL,
|
||||
amount TEXT NOT NULL, -- Stored as string to handle large decimal numbers precisely
|
||||
last_updated_height INTEGER NOT NULL DEFAULT 0,
|
||||
is_delegated BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_delegated IN (0,1)),
|
||||
is_staked BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_staked IN (0,1)),
|
||||
is_vesting BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_vesting IN (0,1)),
|
||||
FOREIGN KEY (account_id) REFERENCES accounts(id),
|
||||
FOREIGN KEY (asset_id) REFERENCES assets(id),
|
||||
UNIQUE(account_id, asset_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_balances_account_id ON balances(account_id);
|
||||
CREATE INDEX idx_balances_asset_id ON balances(asset_id);
|
||||
CREATE INDEX idx_balances_deleted_at ON balances(deleted_at);
|
||||
|
||||
|
||||
11
x/credential/sqlc.yaml
Normal file
11
x/credential/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "credential"
|
||||
out: "orm.gen.go"
|
||||
11
x/credential/view.templ
Normal file
11
x/credential/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package asset
|
||||
|
||||
func View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
templ initialAssetView(a *AssetViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/credential/view_templ.go
Normal file
44
x/credential/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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 View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
func initialAssetView(a *AssetViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
1
x/device/controller.go
Normal file
1
x/device/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package balance
|
||||
9
x/device/model.go
Normal file
9
x/device/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package balance
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Asset = models.Asset
|
||||
|
||||
type AssetModel interface{}
|
||||
|
||||
type AssetViewModel struct{}
|
||||
48
x/device/query.sql
Normal file
48
x/device/query.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
-- Balance table methods
|
||||
-- name: CreateBalance :one
|
||||
INSERT INTO balances (
|
||||
id,
|
||||
account_id,
|
||||
asset_id,
|
||||
amount,
|
||||
last_updated_height,
|
||||
is_delegated,
|
||||
is_staked,
|
||||
is_vesting
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetBalanceByID :one
|
||||
SELECT * FROM balances
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetBalanceByAccountAndAsset :one
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND asset_id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListBalancesByAccount :many
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND deleted_at IS NULL
|
||||
ORDER BY asset_id;
|
||||
|
||||
-- name: UpdateBalance :one
|
||||
UPDATE balances
|
||||
SET
|
||||
amount = ?,
|
||||
last_updated_height = ?,
|
||||
is_delegated = ?,
|
||||
is_staked = ?,
|
||||
is_vesting = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: SoftDeleteBalance :exec
|
||||
UPDATE balances
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?;
|
||||
|
||||
|
||||
23
x/device/schema.sql
Normal file
23
x/device/schema.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- Balances track asset holdings for accounts
|
||||
CREATE TABLE balances (
|
||||
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,
|
||||
asset_id TEXT NOT NULL,
|
||||
amount TEXT NOT NULL, -- Stored as string to handle large decimal numbers precisely
|
||||
last_updated_height INTEGER NOT NULL DEFAULT 0,
|
||||
is_delegated BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_delegated IN (0,1)),
|
||||
is_staked BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_staked IN (0,1)),
|
||||
is_vesting BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_vesting IN (0,1)),
|
||||
FOREIGN KEY (account_id) REFERENCES accounts(id),
|
||||
FOREIGN KEY (asset_id) REFERENCES assets(id),
|
||||
UNIQUE(account_id, asset_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_balances_account_id ON balances(account_id);
|
||||
CREATE INDEX idx_balances_asset_id ON balances(asset_id);
|
||||
CREATE INDEX idx_balances_deleted_at ON balances(deleted_at);
|
||||
|
||||
|
||||
11
x/device/sqlc.yaml
Normal file
11
x/device/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "device"
|
||||
out: "orm.gen.go"
|
||||
11
x/device/view.templ
Normal file
11
x/device/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package asset
|
||||
|
||||
func View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
templ initialAssetView(a *AssetViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/device/view_templ.go
Normal file
44
x/device/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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 View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
func initialAssetView(a *AssetViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
1
x/profile/controller.go
Normal file
1
x/profile/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package balance
|
||||
9
x/profile/model.go
Normal file
9
x/profile/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package balance
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Asset = models.Asset
|
||||
|
||||
type AssetModel interface{}
|
||||
|
||||
type AssetViewModel struct{}
|
||||
48
x/profile/query.sql
Normal file
48
x/profile/query.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
-- Balance table methods
|
||||
-- name: CreateBalance :one
|
||||
INSERT INTO balances (
|
||||
id,
|
||||
account_id,
|
||||
asset_id,
|
||||
amount,
|
||||
last_updated_height,
|
||||
is_delegated,
|
||||
is_staked,
|
||||
is_vesting
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetBalanceByID :one
|
||||
SELECT * FROM balances
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetBalanceByAccountAndAsset :one
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND asset_id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListBalancesByAccount :many
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND deleted_at IS NULL
|
||||
ORDER BY asset_id;
|
||||
|
||||
-- name: UpdateBalance :one
|
||||
UPDATE balances
|
||||
SET
|
||||
amount = ?,
|
||||
last_updated_height = ?,
|
||||
is_delegated = ?,
|
||||
is_staked = ?,
|
||||
is_vesting = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: SoftDeleteBalance :exec
|
||||
UPDATE balances
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?;
|
||||
|
||||
|
||||
23
x/profile/schema.sql
Normal file
23
x/profile/schema.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- Balances track asset holdings for accounts
|
||||
CREATE TABLE balances (
|
||||
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,
|
||||
asset_id TEXT NOT NULL,
|
||||
amount TEXT NOT NULL, -- Stored as string to handle large decimal numbers precisely
|
||||
last_updated_height INTEGER NOT NULL DEFAULT 0,
|
||||
is_delegated BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_delegated IN (0,1)),
|
||||
is_staked BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_staked IN (0,1)),
|
||||
is_vesting BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_vesting IN (0,1)),
|
||||
FOREIGN KEY (account_id) REFERENCES accounts(id),
|
||||
FOREIGN KEY (asset_id) REFERENCES assets(id),
|
||||
UNIQUE(account_id, asset_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_balances_account_id ON balances(account_id);
|
||||
CREATE INDEX idx_balances_asset_id ON balances(asset_id);
|
||||
CREATE INDEX idx_balances_deleted_at ON balances(deleted_at);
|
||||
|
||||
|
||||
11
x/profile/sqlc.yaml
Normal file
11
x/profile/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "profile"
|
||||
out: "orm.gen.go"
|
||||
11
x/profile/view.templ
Normal file
11
x/profile/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package asset
|
||||
|
||||
func View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
templ initialAssetView(a *AssetViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/profile/view_templ.go
Normal file
44
x/profile/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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 View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
func initialAssetView(a *AssetViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
1
x/routes.go
Normal file
1
x/routes.go
Normal file
@@ -0,0 +1 @@
|
||||
package x
|
||||
1
x/session/controller.go
Normal file
1
x/session/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package balance
|
||||
9
x/session/model.go
Normal file
9
x/session/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package balance
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Asset = models.Asset
|
||||
|
||||
type AssetModel interface{}
|
||||
|
||||
type AssetViewModel struct{}
|
||||
48
x/session/query.sql
Normal file
48
x/session/query.sql
Normal file
@@ -0,0 +1,48 @@
|
||||
|
||||
-- Balance table methods
|
||||
-- name: CreateBalance :one
|
||||
INSERT INTO balances (
|
||||
id,
|
||||
account_id,
|
||||
asset_id,
|
||||
amount,
|
||||
last_updated_height,
|
||||
is_delegated,
|
||||
is_staked,
|
||||
is_vesting
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
RETURNING *;
|
||||
|
||||
-- name: GetBalanceByID :one
|
||||
SELECT * FROM balances
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetBalanceByAccountAndAsset :one
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND asset_id = ? AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: ListBalancesByAccount :many
|
||||
SELECT * FROM balances
|
||||
WHERE account_id = ? AND deleted_at IS NULL
|
||||
ORDER BY asset_id;
|
||||
|
||||
-- name: UpdateBalance :one
|
||||
UPDATE balances
|
||||
SET
|
||||
amount = ?,
|
||||
last_updated_height = ?,
|
||||
is_delegated = ?,
|
||||
is_staked = ?,
|
||||
is_vesting = ?,
|
||||
updated_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ? AND deleted_at IS NULL
|
||||
RETURNING *;
|
||||
|
||||
-- name: SoftDeleteBalance :exec
|
||||
UPDATE balances
|
||||
SET deleted_at = CURRENT_TIMESTAMP
|
||||
WHERE id = ?;
|
||||
|
||||
|
||||
23
x/session/schema.sql
Normal file
23
x/session/schema.sql
Normal file
@@ -0,0 +1,23 @@
|
||||
-- Balances track asset holdings for accounts
|
||||
CREATE TABLE balances (
|
||||
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,
|
||||
asset_id TEXT NOT NULL,
|
||||
amount TEXT NOT NULL, -- Stored as string to handle large decimal numbers precisely
|
||||
last_updated_height INTEGER NOT NULL DEFAULT 0,
|
||||
is_delegated BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_delegated IN (0,1)),
|
||||
is_staked BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_staked IN (0,1)),
|
||||
is_vesting BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_vesting IN (0,1)),
|
||||
FOREIGN KEY (account_id) REFERENCES accounts(id),
|
||||
FOREIGN KEY (asset_id) REFERENCES assets(id),
|
||||
UNIQUE(account_id, asset_id)
|
||||
);
|
||||
|
||||
CREATE INDEX idx_balances_account_id ON balances(account_id);
|
||||
CREATE INDEX idx_balances_asset_id ON balances(asset_id);
|
||||
CREATE INDEX idx_balances_deleted_at ON balances(deleted_at);
|
||||
|
||||
|
||||
11
x/session/sqlc.yaml
Normal file
11
x/session/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "session"
|
||||
out: "orm.gen.go"
|
||||
11
x/session/view.templ
Normal file
11
x/session/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package asset
|
||||
|
||||
func View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
templ initialAssetView(a *AssetViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/session/view_templ.go
Normal file
44
x/session/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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 View(a *AssetViewModel) templ.Component {
|
||||
return initialAssetView(a)
|
||||
}
|
||||
|
||||
func initialAssetView(a *AssetViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
1
x/vault/controller.go
Normal file
1
x/vault/controller.go
Normal file
@@ -0,0 +1 @@
|
||||
package vault
|
||||
9
x/vault/model.go
Normal file
9
x/vault/model.go
Normal file
@@ -0,0 +1,9 @@
|
||||
package vault
|
||||
|
||||
import "github.com/onsonr/motr/internal/models"
|
||||
|
||||
type Vault = models.Vault
|
||||
|
||||
type VaultModel interface{}
|
||||
|
||||
type VaultViewModel struct{}
|
||||
13
x/vault/query.sql
Normal file
13
x/vault/query.sql
Normal file
@@ -0,0 +1,13 @@
|
||||
|
||||
-- name: GetVaultConfigByCID :one
|
||||
SELECT * FROM vaults
|
||||
WHERE cid = ?
|
||||
AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
-- name: GetVaultRedirectURIBySessionID :one
|
||||
SELECT redirect_uri FROM vaults
|
||||
WHERE session_id = ?
|
||||
AND deleted_at IS NULL
|
||||
LIMIT 1;
|
||||
|
||||
18
x/vault/schema.sql
Normal file
18
x/vault/schema.sql
Normal file
@@ -0,0 +1,18 @@
|
||||
-- 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,
|
||||
session_id TEXT NOT NULL,
|
||||
redirect_uri TEXT NOT NULL
|
||||
);
|
||||
|
||||
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);
|
||||
11
x/vault/sqlc.yaml
Normal file
11
x/vault/sqlc.yaml
Normal file
@@ -0,0 +1,11 @@
|
||||
version: "2"
|
||||
sql:
|
||||
- engine: "sqlite"
|
||||
queries: "query.sql"
|
||||
schema: "schema.sql"
|
||||
gen:
|
||||
go:
|
||||
emit_interface: true
|
||||
emit_json_tags: true
|
||||
package: "vault"
|
||||
out: "orm.gen.go"
|
||||
11
x/vault/view.templ
Normal file
11
x/vault/view.templ
Normal file
@@ -0,0 +1,11 @@
|
||||
package vault
|
||||
|
||||
func View(a *VaultViewModel) templ.Component {
|
||||
return initialVaultView(a)
|
||||
}
|
||||
|
||||
templ initialVaultView(a *VaultViewModel) {
|
||||
<div>
|
||||
<h1>Account</h1>
|
||||
</div>
|
||||
}
|
||||
44
x/vault/view_templ.go
Normal file
44
x/vault/view_templ.go
Normal file
@@ -0,0 +1,44 @@
|
||||
// Code generated by templ - DO NOT EDIT.
|
||||
|
||||
// templ: version: v0.3.857
|
||||
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 View(a *VaultViewModel) templ.Component {
|
||||
return initialVaultView(a)
|
||||
}
|
||||
|
||||
func initialVaultView(a *VaultViewModel) 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><h1>Account</h1></div>")
|
||||
if templ_7745c5c3_Err != nil {
|
||||
return templ_7745c5c3_Err
|
||||
}
|
||||
return nil
|
||||
})
|
||||
}
|
||||
|
||||
var _ = templruntime.GeneratedTemplate
|
||||
Reference in New Issue
Block a user