Add full monorepo: virtual-banker, backend, frontend, docs, scripts, deployment

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
defiQUG
2026-02-10 11:32:49 -08:00
parent aafcd913c2
commit 88bc76da91
815 changed files with 125522 additions and 264 deletions

View File

@@ -0,0 +1,35 @@
package config
import (
"os"
"strconv"
)
// SearchConfig holds Elasticsearch/OpenSearch configuration
type SearchConfig struct {
URL string
Username string
Password string
UseSSL bool
IndexPrefix string
}
// LoadSearchConfig loads search configuration from environment variables
func LoadSearchConfig() *SearchConfig {
useSSL, _ := strconv.ParseBool(getEnv("SEARCH_USE_SSL", "false"))
return &SearchConfig{
URL: getEnv("SEARCH_URL", "http://localhost:9200"),
Username: getEnv("SEARCH_USERNAME", ""),
Password: getEnv("SEARCH_PASSWORD", ""),
UseSSL: useSSL,
IndexPrefix: getEnv("SEARCH_INDEX_PREFIX", "explorer"),
}
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}

View File

@@ -0,0 +1,120 @@
package indexer
import (
"bytes"
"context"
"encoding/json"
"fmt"
"time"
"github.com/elastic/go-elasticsearch/v8"
"github.com/elastic/go-elasticsearch/v8/esapi"
)
// SearchIndexer handles indexing documents to Elasticsearch/OpenSearch
type SearchIndexer struct {
client *elasticsearch.Client
indexPrefix string
}
// NewSearchIndexer creates a new search indexer
func NewSearchIndexer(client *elasticsearch.Client, indexPrefix string) *SearchIndexer {
return &SearchIndexer{
client: client,
indexPrefix: indexPrefix,
}
}
// IndexBlock indexes a block document
func (s *SearchIndexer) IndexBlock(ctx context.Context, chainID int, block *BlockDocument) error {
indexName := fmt.Sprintf("%s-blocks-%d", s.indexPrefix, chainID)
return s.indexDocument(ctx, indexName, block.Hash, block)
}
// IndexTransaction indexes a transaction document
func (s *SearchIndexer) IndexTransaction(ctx context.Context, chainID int, tx *TransactionDocument) error {
indexName := fmt.Sprintf("%s-transactions-%d", s.indexPrefix, chainID)
return s.indexDocument(ctx, indexName, tx.Hash, tx)
}
// IndexAddress indexes an address document
func (s *SearchIndexer) IndexAddress(ctx context.Context, chainID int, addr *AddressDocument) error {
indexName := fmt.Sprintf("%s-addresses-%d", s.indexPrefix, chainID)
return s.indexDocument(ctx, indexName, addr.Address, addr)
}
// indexDocument indexes a document to Elasticsearch
func (s *SearchIndexer) indexDocument(ctx context.Context, indexName, docID string, doc interface{}) error {
body, err := json.Marshal(doc)
if err != nil {
return fmt.Errorf("failed to marshal document: %w", err)
}
req := esapi.IndexRequest{
Index: indexName,
DocumentID: docID,
Body: bytes.NewReader(body),
Refresh: "false",
}
res, err := req.Do(ctx, s.client)
if err != nil {
return fmt.Errorf("failed to index document: %w", err)
}
defer res.Body.Close()
if res.IsError() {
return fmt.Errorf("elasticsearch error: %s", res.String())
}
return nil
}
// BlockDocument represents a block in the search index
type BlockDocument struct {
BlockNumber int64 `json:"block_number"`
Hash string `json:"hash"`
Timestamp time.Time `json:"timestamp"`
Miner string `json:"miner"`
TransactionCount int `json:"transaction_count"`
GasUsed int64 `json:"gas_used"`
GasLimit int64 `json:"gas_limit"`
ChainID int `json:"chain_id"`
ParentHash string `json:"parent_hash"`
Size int64 `json:"size"`
}
// TransactionDocument represents a transaction in the search index
type TransactionDocument struct {
Hash string `json:"hash"`
BlockNumber int64 `json:"block_number"`
TransactionIndex int `json:"transaction_index"`
FromAddress string `json:"from_address"`
ToAddress string `json:"to_address"`
Value string `json:"value"`
ValueNumeric int64 `json:"value_numeric"`
GasPrice int64 `json:"gas_price"`
GasUsed int64 `json:"gas_used"`
Status string `json:"status"`
Timestamp time.Time `json:"timestamp"`
ChainID int `json:"chain_id"`
InputDataLength int `json:"input_data_length"`
IsContractCreation bool `json:"is_contract_creation"`
ContractAddress string `json:"contract_address,omitempty"`
}
// AddressDocument represents an address in the search index
type AddressDocument struct {
Address string `json:"address"`
ChainID int `json:"chain_id"`
Label string `json:"label,omitempty"`
Tags []string `json:"tags,omitempty"`
TokenCount int `json:"token_count"`
TransactionCount int64 `json:"transaction_count"`
FirstSeen time.Time `json:"first_seen"`
LastSeen time.Time `json:"last_seen"`
IsContract bool `json:"is_contract"`
ContractName string `json:"contract_name,omitempty"`
BalanceETH string `json:"balance_eth"`
BalanceUSD float64 `json:"balance_usd,omitempty"`
}