refactor: migrate to modular architecture for improved scalability

This commit is contained in:
2025-04-03 23:19:22 -04:00
parent cf42953653
commit fbbd9d4387
59 changed files with 513 additions and 1366 deletions

View File

@@ -41,7 +41,7 @@ tasks:
internal: true
requires:
vars: [PATH]
dir: "{{.PATH}}"
dir: "{{.ROOT_DIR}}/{{.PATH}}"
sources:
- "**/query.sql"
- "**/schema.sql"

View File

@@ -1 +0,0 @@
package account

View File

@@ -1,31 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.28.0
package account
import (
"context"
"database/sql"
)
type DBTX interface {
ExecContext(context.Context, string, ...interface{}) (sql.Result, error)
PrepareContext(context.Context, string) (*sql.Stmt, error)
QueryContext(context.Context, string, ...interface{}) (*sql.Rows, error)
QueryRowContext(context.Context, string, ...interface{}) *sql.Row
}
func New(db DBTX) *Queries {
return &Queries{db: db}
}
type Queries struct {
db DBTX
}
func (q *Queries) WithTx(tx *sql.Tx) *Queries {
return &Queries{
db: tx,
}
}

View File

@@ -1,27 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.28.0
package account
import (
"database/sql"
"time"
)
type Account struct {
ID string `json:"id"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
DeletedAt sql.NullTime `json:"deleted_at"`
Number int64 `json:"number"`
Sequence int64 `json:"sequence"`
Address string `json:"address"`
PublicKey string `json:"public_key"`
ChainID string `json:"chain_id"`
Controller string `json:"controller"`
IsSubsidiary bool `json:"is_subsidiary"`
IsValidator bool `json:"is_validator"`
IsDelegator bool `json:"is_delegator"`
IsAccountable bool `json:"is_accountable"`
}

View File

@@ -1,25 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.28.0
package account
import (
"context"
)
type Querier interface {
CreateAccount(ctx context.Context, arg CreateAccountParams) (Account, error)
GetAccountByAddress(ctx context.Context, address string) (Account, error)
GetAccountByID(ctx context.Context, id string) (Account, error)
GetAccountsByChainID(ctx context.Context, chainID string) ([]Account, error)
GetAccountsByController(ctx context.Context, controller string) ([]Account, error)
GetDelegatorAccounts(ctx context.Context) ([]Account, error)
GetValidatorAccounts(ctx context.Context) ([]Account, error)
ListAccounts(ctx context.Context) ([]Account, error)
SoftDeleteAccount(ctx context.Context, id string) error
UpdateAccount(ctx context.Context, arg UpdateAccountParams) (Account, error)
UpdateAccountSequence(ctx context.Context, arg UpdateAccountSequenceParams) (Account, error)
}
var _ Querier = (*Queries)(nil)

View File

@@ -1,76 +0,0 @@
-- name: CreateAccount :one
INSERT INTO accounts (
id,
number,
sequence,
address,
public_key,
chain_id,
controller,
is_subsidiary,
is_validator,
is_delegator,
is_accountable
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING *;
-- name: GetAccountByID :one
SELECT * FROM accounts
WHERE id = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetAccountByAddress :one
SELECT * FROM accounts
WHERE address = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetAccountsByChainID :many
SELECT * FROM accounts
WHERE chain_id = ? AND deleted_at IS NULL
ORDER BY number;
-- name: ListAccounts :many
SELECT * FROM accounts
WHERE deleted_at IS NULL
ORDER BY chain_id, number;
-- name: UpdateAccountSequence :one
UPDATE accounts
SET
sequence = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND deleted_at IS NULL
RETURNING *;
-- name: UpdateAccount :one
UPDATE accounts
SET
public_key = ?,
controller = ?,
is_subsidiary = ?,
is_validator = ?,
is_delegator = ?,
is_accountable = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND deleted_at IS NULL
RETURNING *;
-- name: SoftDeleteAccount :exec
UPDATE accounts
SET deleted_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: GetAccountsByController :many
SELECT * FROM accounts
WHERE controller = ? AND deleted_at IS NULL
ORDER BY chain_id, number;
-- name: GetValidatorAccounts :many
SELECT * FROM accounts
WHERE is_validator = true AND deleted_at IS NULL
ORDER BY chain_id, number;
-- name: GetDelegatorAccounts :many
SELECT * FROM accounts
WHERE is_delegator = true AND deleted_at IS NULL
ORDER BY chain_id, number;

View File

@@ -1,452 +0,0 @@
// Code generated by sqlc. DO NOT EDIT.
// versions:
// sqlc v1.28.0
// source: query.sql
package account
import (
"context"
)
const createAccount = `-- name: CreateAccount :one
INSERT INTO accounts (
id,
number,
sequence,
address,
public_key,
chain_id,
controller,
is_subsidiary,
is_validator,
is_delegator,
is_accountable
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable
`
type CreateAccountParams struct {
ID string `json:"id"`
Number int64 `json:"number"`
Sequence int64 `json:"sequence"`
Address string `json:"address"`
PublicKey string `json:"public_key"`
ChainID string `json:"chain_id"`
Controller string `json:"controller"`
IsSubsidiary bool `json:"is_subsidiary"`
IsValidator bool `json:"is_validator"`
IsDelegator bool `json:"is_delegator"`
IsAccountable bool `json:"is_accountable"`
}
func (q *Queries) CreateAccount(ctx context.Context, arg CreateAccountParams) (Account, error) {
row := q.db.QueryRowContext(ctx, createAccount,
arg.ID,
arg.Number,
arg.Sequence,
arg.Address,
arg.PublicKey,
arg.ChainID,
arg.Controller,
arg.IsSubsidiary,
arg.IsValidator,
arg.IsDelegator,
arg.IsAccountable,
)
var i Account
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
)
return i, err
}
const getAccountByAddress = `-- name: GetAccountByAddress :one
SELECT id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable FROM accounts
WHERE address = ? AND deleted_at IS NULL
LIMIT 1
`
func (q *Queries) GetAccountByAddress(ctx context.Context, address string) (Account, error) {
row := q.db.QueryRowContext(ctx, getAccountByAddress, address)
var i Account
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
)
return i, err
}
const getAccountByID = `-- name: GetAccountByID :one
SELECT id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable FROM accounts
WHERE id = ? AND deleted_at IS NULL
LIMIT 1
`
func (q *Queries) GetAccountByID(ctx context.Context, id string) (Account, error) {
row := q.db.QueryRowContext(ctx, getAccountByID, id)
var i Account
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
)
return i, err
}
const getAccountsByChainID = `-- name: GetAccountsByChainID :many
SELECT id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable FROM accounts
WHERE chain_id = ? AND deleted_at IS NULL
ORDER BY number
`
func (q *Queries) GetAccountsByChainID(ctx context.Context, chainID string) ([]Account, error) {
rows, err := q.db.QueryContext(ctx, getAccountsByChainID, chainID)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Account
for rows.Next() {
var i Account
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
); 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 getAccountsByController = `-- name: GetAccountsByController :many
SELECT id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable FROM accounts
WHERE controller = ? AND deleted_at IS NULL
ORDER BY chain_id, number
`
func (q *Queries) GetAccountsByController(ctx context.Context, controller string) ([]Account, error) {
rows, err := q.db.QueryContext(ctx, getAccountsByController, controller)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Account
for rows.Next() {
var i Account
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
); 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 getDelegatorAccounts = `-- name: GetDelegatorAccounts :many
SELECT id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable FROM accounts
WHERE is_delegator = true AND deleted_at IS NULL
ORDER BY chain_id, number
`
func (q *Queries) GetDelegatorAccounts(ctx context.Context) ([]Account, error) {
rows, err := q.db.QueryContext(ctx, getDelegatorAccounts)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Account
for rows.Next() {
var i Account
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
); 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 getValidatorAccounts = `-- name: GetValidatorAccounts :many
SELECT id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable FROM accounts
WHERE is_validator = true AND deleted_at IS NULL
ORDER BY chain_id, number
`
func (q *Queries) GetValidatorAccounts(ctx context.Context) ([]Account, error) {
rows, err := q.db.QueryContext(ctx, getValidatorAccounts)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Account
for rows.Next() {
var i Account
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
); 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 listAccounts = `-- name: ListAccounts :many
SELECT id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable FROM accounts
WHERE deleted_at IS NULL
ORDER BY chain_id, number
`
func (q *Queries) ListAccounts(ctx context.Context) ([]Account, error) {
rows, err := q.db.QueryContext(ctx, listAccounts)
if err != nil {
return nil, err
}
defer rows.Close()
var items []Account
for rows.Next() {
var i Account
if err := rows.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
); 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 softDeleteAccount = `-- name: SoftDeleteAccount :exec
UPDATE accounts
SET deleted_at = CURRENT_TIMESTAMP
WHERE id = ?
`
func (q *Queries) SoftDeleteAccount(ctx context.Context, id string) error {
_, err := q.db.ExecContext(ctx, softDeleteAccount, id)
return err
}
const updateAccount = `-- name: UpdateAccount :one
UPDATE accounts
SET
public_key = ?,
controller = ?,
is_subsidiary = ?,
is_validator = ?,
is_delegator = ?,
is_accountable = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND deleted_at IS NULL
RETURNING id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable
`
type UpdateAccountParams struct {
PublicKey string `json:"public_key"`
Controller string `json:"controller"`
IsSubsidiary bool `json:"is_subsidiary"`
IsValidator bool `json:"is_validator"`
IsDelegator bool `json:"is_delegator"`
IsAccountable bool `json:"is_accountable"`
ID string `json:"id"`
}
func (q *Queries) UpdateAccount(ctx context.Context, arg UpdateAccountParams) (Account, error) {
row := q.db.QueryRowContext(ctx, updateAccount,
arg.PublicKey,
arg.Controller,
arg.IsSubsidiary,
arg.IsValidator,
arg.IsDelegator,
arg.IsAccountable,
arg.ID,
)
var i Account
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
)
return i, err
}
const updateAccountSequence = `-- name: UpdateAccountSequence :one
UPDATE accounts
SET
sequence = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND deleted_at IS NULL
RETURNING id, created_at, updated_at, deleted_at, number, sequence, address, public_key, chain_id, controller, is_subsidiary, is_validator, is_delegator, is_accountable
`
type UpdateAccountSequenceParams struct {
Sequence int64 `json:"sequence"`
ID string `json:"id"`
}
func (q *Queries) UpdateAccountSequence(ctx context.Context, arg UpdateAccountSequenceParams) (Account, error) {
row := q.db.QueryRowContext(ctx, updateAccountSequence, arg.Sequence, arg.ID)
var i Account
err := row.Scan(
&i.ID,
&i.CreatedAt,
&i.UpdatedAt,
&i.DeletedAt,
&i.Number,
&i.Sequence,
&i.Address,
&i.PublicKey,
&i.ChainID,
&i.Controller,
&i.IsSubsidiary,
&i.IsValidator,
&i.IsDelegator,
&i.IsAccountable,
)
return i, err
}

View File

@@ -1,24 +0,0 @@
-- 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);

View File

@@ -1,11 +0,0 @@
package account
func View() templ.Component {
return initialAccountView()
}
templ initialAccountView() {
<div>
<h1>Account</h1>
</div>
}

View File

@@ -1,44 +0,0 @@
// 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() templ.Component {
return initialAccountView()
}
func initialAccountView() 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

View File

@@ -1 +0,0 @@
package asset

View File

@@ -1,22 +0,0 @@
-- 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);

View File

@@ -1,48 +0,0 @@
-- 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 = ?;

View File

@@ -1 +0,0 @@
package credential

View File

@@ -1,48 +0,0 @@
-- 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 = ?;

View File

@@ -1,23 +0,0 @@
-- 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);

View File

@@ -1,11 +0,0 @@
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"

View File

@@ -1,11 +0,0 @@
package credential
func View() templ.Component {
return initialAssetView()
}
templ initialAssetView() {
<div>
<h1>Account</h1>
</div>
}

View File

@@ -1,44 +0,0 @@
// 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 View() templ.Component {
return initialAssetView()
}
func initialAssetView() 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

View File

@@ -1 +0,0 @@
package device

View File

@@ -1,48 +0,0 @@
-- 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 = ?;

View File

@@ -1,23 +0,0 @@
-- 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);

View File

@@ -1,11 +0,0 @@
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"

View File

@@ -1,44 +0,0 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.857
package device
//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() templ.Component {
return initialAssetView()
}
func initialAssetView() 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/identity/controller.go Normal file
View File

@@ -0,0 +1 @@
package identity

183
x/identity/query.sql Normal file
View File

@@ -0,0 +1,183 @@
-- name: CreateAccount :one
INSERT INTO accounts (
id,
number,
sequence,
address,
public_key,
chain_id,
controller,
is_subsidiary,
is_validator,
is_delegator,
is_accountable
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
RETURNING *;
-- name: GetAccountByID :one
SELECT * FROM accounts
WHERE id = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetAccountByAddress :one
SELECT * FROM accounts
WHERE address = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetAccountsByChainID :many
SELECT * FROM accounts
WHERE chain_id = ? AND deleted_at IS NULL
ORDER BY number;
-- name: ListAccounts :many
SELECT * FROM accounts
WHERE deleted_at IS NULL
ORDER BY chain_id, number;
-- name: UpdateAccountSequence :one
UPDATE accounts
SET
sequence = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND deleted_at IS NULL
RETURNING *;
-- name: UpdateAccount :one
UPDATE accounts
SET
public_key = ?,
controller = ?,
is_subsidiary = ?,
is_validator = ?,
is_delegator = ?,
is_accountable = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ? AND deleted_at IS NULL
RETURNING *;
-- name: SoftDeleteAccount :exec
UPDATE accounts
SET deleted_at = CURRENT_TIMESTAMP
WHERE id = ?;
-- name: GetAccountsByController :many
SELECT * FROM accounts
WHERE controller = ? AND deleted_at IS NULL
ORDER BY chain_id, number;
-- name: GetValidatorAccounts :many
SELECT * FROM accounts
WHERE is_validator = true AND deleted_at IS NULL
ORDER BY chain_id, number;
-- name: GetDelegatorAccounts :many
SELECT * FROM accounts
WHERE is_delegator = true AND deleted_at IS NULL
ORDER BY chain_id, number;
-- name: InsertCredential :one
INSERT INTO credentials (
handle,
credential_id,
origin,
type,
transports
) VALUES (?, ?, ?, ?, ?)
RETURNING *;
-- name: GetCredentialsByHandle :many
SELECT * FROM credentials
WHERE handle = ?
AND deleted_at IS NULL;
-- name: GetCredentialByID :one
SELECT * FROM credentials
WHERE credential_id = ?
AND deleted_at IS NULL
LIMIT 1;
-- name: SoftDeleteCredential :exec
UPDATE credentials
SET deleted_at = CURRENT_TIMESTAMP
WHERE credential_id = ?;
-- Additional credential methods for better integration with devices
-- name: UpdateCredential :one
UPDATE credentials
SET
authenticator_attachment = ?,
transports = ?,
updated_at = CURRENT_TIMESTAMP
WHERE credential_id = ? AND deleted_at IS NULL
RETURNING *;
-- name: GetCredentialsByProfile :many
SELECT c.* 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;
-- Device table methods
-- 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 *;
-- name: GetDeviceByID :one
SELECT * FROM devices
WHERE id = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetDeviceByFingerprint :one
SELECT * FROM devices
WHERE profile_id = ? AND fingerprint = ? AND deleted_at IS NULL
LIMIT 1;
-- name: ListDevicesByProfile :many
SELECT * FROM devices
WHERE profile_id = ? AND deleted_at IS NULL
ORDER BY last_used_at DESC;
-- name: GetTrustedDevicesByProfile :many
SELECT * FROM devices
WHERE profile_id = ? AND is_trusted = true AND deleted_at IS NULL
ORDER BY last_used_at DESC;
-- 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 *;
-- 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 *;
-- name: SoftDeleteDevice :exec
UPDATE devices
SET deleted_at = CURRENT_TIMESTAMP
WHERE id = ?;

72
x/identity/schema.sql Normal file
View File

@@ -0,0 +1,72 @@
-- 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);
-- 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
);
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);
-- Devices link profiles to their authenticated devices
CREATE TABLE devices (
id TEXT PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
profile_id TEXT NOT NULL,
credential_id TEXT NOT NULL,
name TEXT NOT NULL, -- User-friendly device name
device_type TEXT NOT NULL, -- mobile, desktop, tablet, etc.
os_name TEXT NOT NULL, -- iOS, Android, Windows, macOS, etc.
os_version TEXT NOT NULL, -- OS version string
browser_name TEXT, -- Browser name if applicable
browser_version TEXT, -- Browser version if applicable
last_used_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
is_trusted BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_trusted IN (0,1)),
is_current BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_current IN (0,1)),
fingerprint TEXT NOT NULL, -- Device fingerprint for additional verification
user_agent TEXT, -- Full user agent string
ip_address TEXT, -- Last known IP address
FOREIGN KEY (profile_id) REFERENCES profiles(id),
FOREIGN KEY (credential_id) REFERENCES credentials(id),
UNIQUE(profile_id, fingerprint)
);
CREATE INDEX idx_devices_profile_id ON devices(profile_id);
CREATE INDEX idx_devices_credential_id ON devices(credential_id);
CREATE INDEX idx_devices_is_trusted ON devices(is_trusted);
CREATE INDEX idx_devices_last_used_at ON devices(last_used_at);
CREATE INDEX idx_devices_deleted_at ON devices(deleted_at);

View File

@@ -7,5 +7,5 @@ sql:
go:
emit_interface: true
emit_json_tags: true
package: "asset"
out: "orm.gen.go"
package: "identity"
out: "."

View File

@@ -1,4 +1,4 @@
package device
package identity
func View() templ.Component {
return initialAssetView()

View File

@@ -1,7 +1,7 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.857
package asset
package identity
//lint:file-ignore SA4006 This context is only used if a nested component is present.

View File

@@ -1,3 +1,51 @@
-- 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 = ?;
-- name: CreateAsset :one
INSERT INTO assets (
id,

View File

@@ -1,3 +1,24 @@
-- 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);
-- Balances track asset holdings for accounts
CREATE TABLE balances (
id TEXT PRIMARY KEY,

View File

@@ -8,4 +8,4 @@ sql:
emit_interface: true
emit_json_tags: true
package: "balance"
out: "orm.gen.go"
out: "."

View File

@@ -1,4 +1,4 @@
package balance
package portfolio
func View() templ.Component {
return initialAssetView()

View File

@@ -1 +0,0 @@
package profile

View File

@@ -1,48 +0,0 @@
-- 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 = ?;

View File

@@ -1,23 +0,0 @@
-- 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);

View File

@@ -1,11 +0,0 @@
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"

View File

@@ -1,11 +0,0 @@
package profile
func View() templ.Component {
return initialAssetView()
}
templ initialAssetView() {
<div>
<h1>Account</h1>
</div>
}

View File

@@ -1,44 +0,0 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.3.857
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 View() templ.Component {
return initialAssetView()
}
func initialAssetView() 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

View File

@@ -1 +0,0 @@
package session

View File

@@ -1,48 +0,0 @@
-- 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 = ?;

View File

@@ -1,23 +0,0 @@
-- 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);

View File

@@ -1,11 +0,0 @@
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"

View File

@@ -1,11 +0,0 @@
package session
func View() templ.Component {
return initialAssetView()
}
templ initialAssetView() {
<div>
<h1>Account</h1>
</div>
}

1
x/user/controller.go Normal file
View File

@@ -0,0 +1 @@
package user

116
x/user/query.sql Normal file
View File

@@ -0,0 +1,116 @@
-- 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;
-- name: CreateSession :one
INSERT INTO sessions (
id,
browser_name,
browser_version,
client_ipaddr,
platform,
is_desktop,
is_mobile,
is_tablet,
is_tv,
is_bot,
challenge,
is_human_first,
is_human_last,
profile_id
) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )
RETURNING *;
-- name: GetChallengeBySessionID :one
SELECT challenge FROM sessions
WHERE id = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetHumanVerificationNumbers :one
SELECT is_human_first, is_human_last FROM sessions
WHERE id = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetSessionByID :one
SELECT * FROM sessions
WHERE id = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetSessionByClientIP :one
SELECT * FROM sessions
WHERE client_ipaddr = ? AND deleted_at IS NULL
LIMIT 1;
-- name: UpdateSessionHumanVerification :one
UPDATE sessions
SET
is_human_first = ?,
is_human_last = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ?
RETURNING *;
-- name: UpdateSessionWithProfileID :one
UPDATE sessions
SET
profile_id = ?,
updated_at = CURRENT_TIMESTAMP
WHERE id = ?
RETURNING *;
-- name: CheckHandleExists :one
SELECT COUNT(*) > 0 as handle_exists FROM profiles
WHERE handle = ?
AND deleted_at IS NULL;
-- name: InsertProfile :one
INSERT INTO profiles (
address,
handle,
origin,
name
) VALUES (?, ?, ?, ?)
RETURNING *;
-- name: GetProfileByID :one
SELECT * FROM profiles
WHERE id = ? AND deleted_at IS NULL
LIMIT 1;
-- name: GetProfileByAddress :one
SELECT * FROM profiles
WHERE address = ? AND deleted_at IS NULL
LIMIT 1;
-- name: SoftDeleteProfile :exec
UPDATE profiles
SET deleted_at = CURRENT_TIMESTAMP
WHERE address = ?;
-- name: UpdateProfile :one
UPDATE profiles
SET
name = ?,
handle = ?,
updated_at = CURRENT_TIMESTAMP
WHERE address = ?
AND deleted_at IS NULL
RETURNING *;
-- name: GetProfileByHandle :one
SELECT * FROM profiles
WHERE handle = ?
AND deleted_at IS NULL
LIMIT 1;

62
x/user/schema.sql Normal file
View File

@@ -0,0 +1,62 @@
-- 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)
);
-- Indexes for common queries
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);
-- Sessions track user authentication state
CREATE TABLE sessions (
id TEXT PRIMARY KEY,
created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
updated_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP,
deleted_at TIMESTAMP,
browser_name TEXT NOT NULL,
browser_version TEXT NOT NULL,
client_ipaddr TEXT NOT NULL,
platform TEXT NOT NULL,
is_desktop BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_desktop IN (0,1)),
is_mobile BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_mobile IN (0,1)),
is_tablet BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_tablet IN (0,1)),
is_tv BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_tv IN (0,1)),
is_bot BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_bot IN (0,1)),
challenge TEXT NOT NULL,
is_human_first BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_human_first IN (0,1)),
is_human_last BOOLEAN NOT NULL DEFAULT FALSE CHECK(is_human_last IN (0,1)),
profile_id INTEGER NOT NULL
);
CREATE INDEX idx_sessions_profile_id ON sessions(profile_id);
CREATE INDEX idx_sessions_client_ipaddr ON sessions(client_ipaddr);
CREATE INDEX idx_sessions_deleted_at ON sessions(deleted_at);
-- 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);

View File

@@ -7,5 +7,5 @@ sql:
go:
emit_interface: true
emit_json_tags: true
package: "account"
package: "user"
out: "."

View File

@@ -1,4 +1,4 @@
package asset
package user
func View() templ.Component {
return initialAssetView()

View File

@@ -1 +0,0 @@
package vault

View File

@@ -1,13 +0,0 @@
-- 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;

View File

@@ -1,18 +0,0 @@
-- 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);

View File

@@ -1,11 +0,0 @@
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"

View File

@@ -1,11 +0,0 @@
package vault
func View() templ.Component {
return initialVaultView()
}
templ initialVaultView() {
<div>
<h1>Account</h1>
</div>
}

View File

@@ -1,44 +0,0 @@
// 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() templ.Component {
return initialVaultView()
}
func initialVaultView() 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