mirror of
https://github.com/luxfi/bank.git
synced 2026-11-03 06:39:01 +00:00
180 lines
4.8 KiB
Go
180 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
|
|
"github.com/hanzoai/base"
|
|
"github.com/hanzoai/base/apis"
|
|
"github.com/hanzoai/base/core"
|
|
"github.com/hanzoai/base/plugins/migratecmd"
|
|
"github.com/hanzoai/base/plugins/platform"
|
|
"github.com/hanzoai/base/tools/hook"
|
|
bank "github.com/luxfi/bank"
|
|
"github.com/luxfi/bank/collections"
|
|
"github.com/luxfi/bank/hooks"
|
|
)
|
|
|
|
// envOr returns the env value or fallback if unset / empty.
|
|
func envOr(key, fallback string) string {
|
|
if v := os.Getenv(key); v != "" {
|
|
return v
|
|
}
|
|
return fallback
|
|
}
|
|
|
|
func main() {
|
|
app := base.New()
|
|
|
|
// ---- flags ----
|
|
|
|
var migrationsDir string
|
|
app.RootCmd.PersistentFlags().StringVar(
|
|
&migrationsDir,
|
|
"migrationsDir",
|
|
"./migrations",
|
|
"the directory with user-defined migrations",
|
|
)
|
|
|
|
var automigrate bool
|
|
app.RootCmd.PersistentFlags().BoolVar(
|
|
&automigrate,
|
|
"automigrate",
|
|
true,
|
|
"enable/disable auto migrations",
|
|
)
|
|
|
|
// ---- plugins ----
|
|
|
|
migratecmd.MustRegister(app, app.RootCmd, migratecmd.Config{
|
|
TemplateLang: migratecmd.TemplateLangGo,
|
|
Automigrate: automigrate,
|
|
Dir: migrationsDir,
|
|
})
|
|
|
|
// Hanzo Platform plugin — wires Lux IAM (lux.id) for OIDC SSO and
|
|
// activates per-principal SQLite isolation (one encrypted DB per org/user).
|
|
// Defaults pin the Lux brand; every value overridable via env.
|
|
platform.MustRegister(app, platform.PlatformConfig{
|
|
IAMEndpoint: envOr("IAM_ENDPOINT", "https://lux.id"),
|
|
KMSEndpoint: envOr("KMS_ENDPOINT", "https://kms.lux.network"),
|
|
IAMClientID: envOr("IAM_CLIENT_ID", "lux-bankd"),
|
|
IAMClientSecret: os.Getenv("IAM_CLIENT_SECRET"),
|
|
IAMOrg: envOr("IAM_ORG", "lux"),
|
|
IAMApp: envOr("IAM_APP", "lux-bankd"),
|
|
PrincipalIsolation: envOr("PRINCIPAL_ISOLATION", "sqlite"),
|
|
PrincipalEncryptionKey: os.Getenv("PRINCIPAL_ENCRYPTION_KEY"),
|
|
OrgStorageEndpoint: os.Getenv("ORG_STORAGE_ENDPOINT"),
|
|
OrgStorageBucket: envOr("ORG_STORAGE_BUCKET", "orgs"),
|
|
})
|
|
|
|
// ---- collections ----
|
|
|
|
// Ensure custom collections exist after bootstrap (DB is ready).
|
|
app.OnBootstrap().BindFunc(func(e *core.BootstrapEvent) error {
|
|
if err := e.Next(); err != nil {
|
|
return err
|
|
}
|
|
|
|
// Users auth collection (built-in) is auto-created by Base.
|
|
// Create domain-specific collections.
|
|
for _, ensure := range []func(core.App) error{
|
|
collections.EnsureAccountCollection,
|
|
collections.EnsureBeneficiaryCollection,
|
|
collections.EnsureTransactionCollection,
|
|
collections.EnsureFeeCollection,
|
|
collections.EnsureSessionCollection,
|
|
collections.EnsureBalanceCollection,
|
|
collections.EnsureAuditCollection,
|
|
collections.EnsureDocumentCollection,
|
|
collections.EnsureWalletCollection,
|
|
collections.EnsureConversionCollection,
|
|
} {
|
|
if err := ensure(app); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
// ---- hooks ----
|
|
|
|
hooks.RegisterCurrencyCloudWebhooks(app)
|
|
hooks.RegisterComplianceHooks(app)
|
|
hooks.RegisterPaymentHooks(app)
|
|
hooks.RegisterAccountHooks(app)
|
|
hooks.RegisterFeeHooks(app)
|
|
hooks.RegisterAuditHooks(app)
|
|
hooks.RegisterDocumentHooks(app)
|
|
hooks.RegisterWalletHooks(app)
|
|
hooks.RegisterEmailHooks(app)
|
|
hooks.RegisterCronJobs(app)
|
|
|
|
// ---- routes ----
|
|
|
|
bank.RegisterRoutes(app)
|
|
|
|
app.OnServe().Bind(&hook.Handler[*core.ServeEvent]{
|
|
Id: "bankExtraRoutes",
|
|
Func: func(e *core.ServeEvent) error {
|
|
// Health endpoint (unauthenticated).
|
|
e.Router.GET("/v1/bank/health", func(re *core.RequestEvent) error {
|
|
return re.JSON(http.StatusOK, map[string]string{"status": "ok"})
|
|
})
|
|
|
|
// Account summary endpoint.
|
|
e.Router.GET("/v1/bank/account/summary", func(re *core.RequestEvent) error {
|
|
if re.Auth == nil {
|
|
return apis.NewUnauthorizedError("unauthorized", nil)
|
|
}
|
|
|
|
records, err := app.FindRecordsByFilter(
|
|
collections.AccountCollectionName,
|
|
"owner = {:userId}",
|
|
"-created",
|
|
10,
|
|
0,
|
|
map[string]any{"userId": re.Auth.Id},
|
|
)
|
|
if err != nil {
|
|
return apis.NewBadRequestError("failed to fetch accounts", nil)
|
|
}
|
|
|
|
type accountSummary struct {
|
|
ID string `json:"id"`
|
|
Entity string `json:"entityName"`
|
|
Currency string `json:"currency"`
|
|
Status string `json:"status"`
|
|
KYCStatus string `json:"kycStatus"`
|
|
}
|
|
|
|
result := make([]accountSummary, 0, len(records))
|
|
for _, r := range records {
|
|
result = append(result, accountSummary{
|
|
ID: r.Id,
|
|
Entity: r.GetString("entityName"),
|
|
Currency: r.GetString("currency"),
|
|
Status: r.GetString("status"),
|
|
KYCStatus: r.GetString("kycStatus"),
|
|
})
|
|
}
|
|
|
|
return re.JSON(http.StatusOK, result)
|
|
}).Bind(apis.RequireAuth())
|
|
|
|
return e.Next()
|
|
},
|
|
})
|
|
|
|
// ---- start ----
|
|
|
|
// Override default listen address to port 8070.
|
|
app.RootCmd.SetArgs([]string{"serve", "--http", "0.0.0.0:8070"})
|
|
|
|
if err := app.Start(); err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
}
|