← back to kyawgyi13122-ship-it__launchpad

Function bodies 1,118 total

All specs Real LLM only Function bodies
run method · go · L218-L235 (18 LOC)
cmd/volume-gen/worker.go
func (w *Worker) run() {
	defer close(w.done)

	// Run generation immediately on start
	w.generateTransactions()

	ticker := time.NewTicker(w.config.Interval)
	defer ticker.Stop()

	for {
		select {
		case <-ticker.C:
			w.generateTransactions()
		case <-w.stopChan:
			return
		}
	}
}
generateTransactions method · go · L238-L269 (32 LOC)
cmd/volume-gen/worker.go
func (w *Worker) generateTransactions() {
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Minute)
	defer cancel()

	// Query all chains with virtual_active status
	pagination := types.Pagination{
		Page:  1,
		Limit: 100, // Get up to 100 chains per tick
	}
	chains, _, err := w.chainRepo.ListByStatus(ctx, models.ChainStatusVirtualActive, pagination)
	if err != nil {
		log.Printf("[FakeVolume Worker] Error querying chains: %v", err)
		return
	}

	if len(chains) == 0 {
		log.Printf("[FakeVolume Worker] No active chains found")
		return
	}

	log.Printf("[FakeVolume Worker] Generating transactions for %d active chain(s)", len(chains))

	// Generate 1-3 transactions per chain per interval
	for i := range chains {
		numTransactions := randomInt(1, 3)
		for j := 0; j < numTransactions; j++ {
			if err := w.generateSingleTransaction(ctx, &chains[i]); err != nil {
				log.Printf("[FakeVolume Worker] Error generating transaction for chain %s: %v", chains[i].ChainName, err)
			}
generateSingleTransaction method · go · L272-L274 (3 LOC)
cmd/volume-gen/worker.go
func (w *Worker) generateSingleTransaction(ctx context.Context, chain *models.Chain) error {
	return w.generateSingleTransactionWithTime(ctx, chain, time.Now())
}
generateSingleTransactionWithTime method · go · L277-L322 (46 LOC)
cmd/volume-gen/worker.go
func (w *Worker) generateSingleTransactionWithTime(ctx context.Context, chain *models.Chain, timestamp time.Time) error {
	// Get the virtual pool for this chain
	pool, err := w.poolRepo.GetPoolByChainID(ctx, chain.ID)
	if err != nil {
		return fmt.Errorf("failed to get virtual pool: %w", err)
	}

	// Get or create chain state
	state, err := w.getOrCreateChainState(ctx, chain)
	if err != nil {
		return fmt.Errorf("failed to get chain state: %w", err)
	}

	// Update state with current price
	if err := w.updateChainState(ctx, chain, pool); err != nil {
		return fmt.Errorf("failed to update chain state: %w", err)
	}

	// Select a user for trading
	profile, user, err := w.selectUserForTrade(state)
	if err != nil {
		// Fallback to old method if archetype selection fails
		user, err = w.getOrCreateRandomUser(ctx)
		if err != nil {
			return fmt.Errorf("failed to get random user: %w", err)
		}
		// Use simple 80/20 split as fallback
		isBuy := randomInt(1, 100) <= 80
		if isBuy {
			return w
executeBuyWithAmount method · go · L325-L345 (21 LOC)
cmd/volume-gen/worker.go
func (w *Worker) executeBuyWithAmount(ctx context.Context, chain *models.Chain, pool *models.VirtualPool, user *models.User, timestamp time.Time, cnpyAmount float64) error {
	// Ensure minimum CNPY amount (must be at least 1 when converted to uint64)
	if cnpyAmount < 1.0 {
		cnpyAmount = randomFloat(1.0, 10.0) // Fallback to small random amount
	}

	// Construct a SellOrder for the buy (user selling CNPY for tokens)
	order := &lib.SellOrder{
		AmountForSale:       uint64(cnpyAmount),
		RequestedAmount:     1, // Must be > 0 to indicate buy
		BuyerReceiveAddress: []byte(user.ID.String()),
	}

	// Process the order through OrderProcessor with backdated timestamp
	err := w.orderProcessor.ProcessOrder(ctx, order, chain.ID, &timestamp)
	if err != nil {
		return fmt.Errorf("order processing failed: %w", err)
	}

	return nil
}
executeBuy method · go · L348-L385 (38 LOC)
cmd/volume-gen/worker.go
func (w *Worker) executeBuy(ctx context.Context, chain *models.Chain, pool *models.VirtualPool, user *models.User, timestamp time.Time) error {
	// Random CNPY amount between 0.1 and 100.0 CNPY
	cnpyAmount := randomFloat(1, 100.0)

	// Construct a SellOrder for the buy (user selling CNPY for tokens)
	order := &lib.SellOrder{
		AmountForSale:       uint64(cnpyAmount),
		RequestedAmount:     1, // Must be > 0 to indicate buy
		BuyerReceiveAddress: []byte(user.ID.String()),
	}

	// Process the order through OrderProcessor with backdated timestamp
	err := w.orderProcessor.ProcessOrder(ctx, order, chain.ID, &timestamp)
	if err != nil {
		return fmt.Errorf("order processing failed: %w", err)
	}

	log.Printf("[FakeVolume Worker] BUY: Chain=%s, CNPY=%.4f", chain.ChainName, cnpyAmount)

	// Refresh pool state after the buy to get updated reserve
	updatedPool, err := w.poolRepo.GetPoolByChainID(ctx, chain.ID)
	if err != nil {
		log.Printf("[FakeVolume Worker] Failed to get updated pool for chain
executeSell method · go · L388-L439 (52 LOC)
cmd/volume-gen/worker.go
func (w *Worker) executeSell(ctx context.Context, chain *models.Chain, pool *models.VirtualPool, user *models.User, timestamp time.Time) error {
	// Get user position (create if doesn't exist with some tokens)
	position, err := w.poolRepo.GetUserPosition(ctx, user.ID, chain.ID)
	if err != nil {
		return fmt.Errorf("failed to get user position: %w", err)
	}

	// If user has no position or insufficient tokens, give them some tokens first
	if position == nil || position.TokenBalance < 1000 {
		// Give user tokens by doing a buy first
		log.Printf("[FakeVolume Worker] SELL->BUY conversion: User %s has insufficient balance (%d tokens), executing buy instead", user.ID, func() int64 {
			if position == nil {
				return 0
			}
			return position.TokenBalance
		}())
		return w.executeBuy(ctx, chain, pool, user, timestamp)
	}

	// Fetch fresh position data immediately before calculating sell amount
	// This prevents using stale data when multiple trades happen in quick succession
	position, err 
Repobility · severity-and-effort ranking · https://repobility.com
initializeFakeUsers method · go · L442-L480 (39 LOC)
cmd/volume-gen/worker.go
func (w *Worker) initializeFakeUsers() error {
	ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
	defer cancel()

	numUsers := len(w.fakeUserProfiles)
	log.Printf("[FakeVolume Worker] Initializing pool of %d fake users...", numUsers)

	// Create/get users and map to profiles
	for i, profile := range w.fakeUserProfiles {
		walletAddress := profile.Address

		// Try to get existing user first
		user, err := w.userRepo.GetByWalletAddress(ctx, walletAddress)
		if err == nil && user != nil {
			w.userIDMap[user.ID] = i
			log.Printf("[FakeVolume Worker] Found existing user %s (archetype: %s)", walletAddress, profile.Archetype)
			continue
		}

		// Create new fake user
		newUser := &models.User{
			WalletAddress:    walletAddress,
			Username:         nil,
			IsVerified:       false,
			VerificationTier: "basic",
		}

		user, err = w.userRepo.Create(ctx, newUser)
		if err != nil {
			return fmt.Errorf("failed to create fake user %d: %w", i, err)
		}

		w.userIDMap[us
getOrCreateRandomUser method · go · L483-L507 (25 LOC)
cmd/volume-gen/worker.go
func (w *Worker) getOrCreateRandomUser(ctx context.Context) (*models.User, error) {
	if len(w.userIDMap) == 0 {
		return nil, fmt.Errorf("fake user pool is empty")
	}

	// Pick a random user ID from the map
	var userID uuid.UUID
	randomIndex := w.rng.Intn(len(w.userIDMap))
	i := 0
	for uid := range w.userIDMap {
		if i == randomIndex {
			userID = uid
			break
		}
		i++
	}

	// Get the user from database
	user, err := w.userRepo.GetByID(ctx, userID)
	if err != nil {
		return nil, fmt.Errorf("failed to get fake user: %w", err)
	}

	return user, nil
}
checkAndFillHistoricalData method · go · L512-L582 (71 LOC)
cmd/volume-gen/worker.go
func (w *Worker) checkAndFillHistoricalData() error {
	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Minute)
	defer cancel()

	const minTradeCount = 100

	// Get virtual_active chains
	pagination := types.Pagination{
		Page:  1,
		Limit: 100,
	}
	activeChains, _, err := w.chainRepo.ListByStatus(ctx, models.ChainStatusVirtualActive, pagination)
	if err != nil {
		return fmt.Errorf("failed to query virtual_active chains: %w", err)
	}

	// Get graduated chains
	graduatedChains, _, err := w.chainRepo.ListByStatus(ctx, models.ChainStatusGraduated, pagination)
	if err != nil {
		return fmt.Errorf("failed to query graduated chains: %w", err)
	}

	// Combine both lists
	allChains := append(activeChains, graduatedChains...)

	if len(allChains) == 0 {
		log.Println("[FakeVolume Worker] No eligible chains found (virtual_active or graduated), skipping historical data check")
		return nil
	}

	log.Printf("[FakeVolume Worker] Checking %d chains (%d active, %d graduated) for histor
generateHistoricalData method · go · L587-L636 (50 LOC)
cmd/volume-gen/worker.go
func (w *Worker) generateHistoricalData() error {
	ctx, cancel := context.WithTimeout(context.Background(), 60*time.Minute)
	defer cancel()

	// Get virtual_active chains
	pagination := types.Pagination{
		Page:  1,
		Limit: 100,
	}
	activeChains, _, err := w.chainRepo.ListByStatus(ctx, models.ChainStatusVirtualActive, pagination)
	if err != nil {
		return fmt.Errorf("failed to query virtual_active chains: %w", err)
	}

	// Get graduated chains
	graduatedChains, _, err := w.chainRepo.ListByStatus(ctx, models.ChainStatusGraduated, pagination)
	if err != nil {
		return fmt.Errorf("failed to query graduated chains: %w", err)
	}

	// Combine both lists
	chains := append(activeChains, graduatedChains...)

	if len(chains) == 0 {
		log.Println("[FakeVolume Worker] No eligible chains found (virtual_active or graduated), skipping historical generation")
		return nil
	}

	log.Printf("[FakeVolume Worker] Generating one year of historical data for %d chains (%d active, %d graduated)...",
		len(cha
generateHistoricalDataForChain method · go · L641-L717 (77 LOC)
cmd/volume-gen/worker.go
func (w *Worker) generateHistoricalDataForChain(ctx context.Context, chain *models.Chain, numTrades int) error {
	// Explicitly skip draft, pending_launch, and failed chains
	if chain.Status == models.ChainStatusDraft ||
		chain.Status == models.ChainStatusPendingLaunch ||
		chain.Status == models.ChainStatusFailed {
		log.Printf("[FakeVolume Worker] Skipping historical generation for chain %s (status: %s) - ineligible status",
			chain.ChainName, chain.Status)
		return nil
	}

	// Get the virtual pool for this chain
	pool, err := w.poolRepo.GetPoolByChainID(ctx, chain.ID)
	if err != nil {
		return fmt.Errorf("failed to get virtual pool: %w", err)
	}

	startTime := time.Now()
	log.Printf("[FakeVolume Worker] Generating %d trades for chain %s (status: %s, backdated over 6 months)...",
		numTrades, chain.ChainName, chain.Status)

	successCount := 0
	errorCount := 0

	// Calculate time intervals for backdating
	// Spread trades evenly over the past 6 months (180 days)
	now := time.Now()
	
randomInt function · go · L722-L731 (10 LOC)
cmd/volume-gen/worker.go
func randomInt(min, max int) int {
	if min >= max {
		return min
	}
	n, err := rand.Int(rand.Reader, big.NewInt(int64(max-min+1)))
	if err != nil {
		return min
	}
	return int(n.Int64()) + min
}
randomFloat function · go · L734-L748 (15 LOC)
cmd/volume-gen/worker.go
func randomFloat(min, max float64) float64 {
	// Generate random bytes
	var b [8]byte
	rand.Read(b[:])

	// Convert to uint64
	n := uint64(b[0]) | uint64(b[1])<<8 | uint64(b[2])<<16 | uint64(b[3])<<24 |
		uint64(b[4])<<32 | uint64(b[5])<<40 | uint64(b[6])<<48 | uint64(b[7])<<56

	// Normalize to [0, 1)
	f := float64(n) / float64(1<<64)

	// Scale to [min, max)
	return min + f*(max-min)
}
generateRandomAddress function · go · L751-L755 (5 LOC)
cmd/volume-gen/worker.go
func generateRandomAddress() string {
	b := make([]byte, 20)
	rand.Read(b)
	return "0x" + hex.EncodeToString(b)
}
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
getOrCreateChainState method · go · L758-L830 (73 LOC)
cmd/volume-gen/worker.go
func (w *Worker) getOrCreateChainState(ctx context.Context, chain *models.Chain) (*ChainMarketState, error) {
	w.chainStatesMux.RLock()
	state, exists := w.chainStates[chain.ID]
	w.chainStatesMux.RUnlock()

	if exists {
		return state, nil
	}

	// Create new chain state
	w.chainStatesMux.Lock()
	defer w.chainStatesMux.Unlock()

	// Double-check after acquiring write lock
	if state, exists := w.chainStates[chain.ID]; exists {
		return state, nil
	}

	// Deterministically assign strategy based on chain ID
	strategy := DeterministicStrategyAssignment(chain.ID)
	strategyConfig := GetStrategyConfig(strategy)

	// Apply strategy to create chain-specific config
	chainConfig := ApplyStrategyToConfig(w.config, strategy)

	log.Printf("[FakeVolume Worker] Chain %s (ID: %d) assigned strategy: %s - %s",
		chain.ChainName, chain.ID, strategy, strategyConfig.Description)

	// Initialize price history
	priceHistory := NewPriceHistory(chain.ID, 100) // Keep last 100 prices

	// Get current pool to init
updateChainState method · go · L833-L855 (23 LOC)
cmd/volume-gen/worker.go
func (w *Worker) updateChainState(ctx context.Context, chain *models.Chain, pool *models.VirtualPool) error {
	state, err := w.getOrCreateChainState(ctx, chain)
	if err != nil {
		return err
	}

	// Update price history
	if pool.CurrentPriceCNPY > 0 {
		state.PriceHistory.AddPrice(pool.CurrentPriceCNPY, time.Now())
	}

	// Check for market phase transition
	if state.MarketCycleManager != nil && state.MarketCycleManager.ShouldTransitionPhase() {
		oldPhase := state.MarketCycleManager.GetCurrentPhase()
		state.MarketCycleManager.TransitionToNextPhase()
		newPhase := state.MarketCycleManager.GetCurrentPhase()
		log.Printf("[FakeVolume Worker] Chain %s: Market phase transition %s -> %s",
			chain.ChainName, oldPhase, newPhase)
	}

	state.LastUpdateTime = time.Now()
	return nil
}
selectUserForTrade method · go · L858-L886 (29 LOC)
cmd/volume-gen/worker.go
func (w *Worker) selectUserForTrade(state *ChainMarketState) (*UserProfile, *models.User, error) {
	// Select random user profile
	profileIdx := w.rng.Intn(len(w.fakeUserProfiles))
	profile := &w.fakeUserProfiles[profileIdx]

	// Find corresponding user in database
	var userID uuid.UUID
	for uid, idx := range w.userIDMap {
		if idx == profileIdx {
			userID = uid
			break
		}
	}

	if userID == uuid.Nil {
		return nil, nil, fmt.Errorf("user ID not found for profile %d", profileIdx)
	}

	// Get user from database
	ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
	defer cancel()

	user, err := w.userRepo.GetByID(ctx, userID)
	if err != nil {
		return nil, nil, fmt.Errorf("failed to get user: %w", err)
	}

	return profile, user, nil
}
determineTradeDirection method · go · L889-L918 (30 LOC)
cmd/volume-gen/worker.go
func (w *Worker) determineTradeDirection(
	profile *UserProfile,
	state *ChainMarketState,
	pool *models.VirtualPool,
) bool {
	currentPrice := pool.CurrentPriceCNPY
	sma := state.PriceHistory.GetSMA(20)

	// Base buy probability from user profile
	baseBuyProb := profile.BuyProbability * 100

	// Apply market phase adjustment
	if state.MarketCycleManager != nil {
		baseBuyProb = state.MarketCycleManager.AdjustBuyProbability(baseBuyProb/100) * 100
	}

	// Apply mean reversion bias
	if state.MeanReversionCalc != nil && sma > 0 {
		bias := state.MeanReversionCalc.CalculateBuyBias(currentPrice, sma)
		baseBuyProb += bias
	}

	// User archetype decides based on their personality
	var marketPhase MarketPhase
	if state.MarketCycleManager != nil {
		marketPhase = state.MarketCycleManager.GetCurrentPhase()
	}

	return profile.DecideBuyOrSell(currentPrice, sma, marketPhase, w.rng)
}
calculateTradeSize method · go · L921-L941 (21 LOC)
cmd/volume-gen/worker.go
func (w *Worker) calculateTradeSize(
	profile *UserProfile,
	state *ChainMarketState,
) float64 {
	// Base size from archetype
	intensityMultiplier := 1.0

	// Apply market phase volume multiplier
	if state.MarketCycleManager != nil {
		volumeMult := state.MarketCycleManager.GetVolumeMultiplier()
		intensityMultiplier *= volumeMult
	}

	// Apply trade size bias from market phase
	if state.MarketCycleManager != nil {
		sizeBias := state.MarketCycleManager.GetTradeSizeBias()
		intensityMultiplier *= sizeBias
	}

	return profile.GetTradeSize(intensityMultiplier, w.rng)
}
Load function · go · L56-L58 (3 LOC)
internal/config/config.go
func Load() (*Config, error) {
	return LoadConfig(), nil
}
LoadConfig function · go · L62-L88 (27 LOC)
internal/config/config.go
func LoadConfig() *Config {
	cfg := &Config{
		Port:               getEnv("PORT", "3001"),
		Environment:        getEnv("ENVIRONMENT", "development"),
		DatabaseURL:        getEnv("DATABASE_URL", ""),
		JWTSecret:          getEnv("JWT_SECRET", ""),
		JWTExpirationHours: getEnvInt("JWT_EXPIRATION_HOURS", 24),
		GithubClientID:     getEnv("GITHUB_CLIENT_ID", ""),
		GithubClientSecret: getEnv("GITHUB_CLIENT_SECRET", ""),
		MaxFileUploadSize:  getEnvInt64("MAX_FILE_UPLOAD_SIZE", 10*1024*1024), // 10MB
		RequestTimeout:     time.Duration(getEnvInt("REQUEST_TIMEOUT_SECONDS", 60)) * time.Second,
		DefaultPageSize:    getEnvInt("DEFAULT_PAGE_SIZE", 20),
		MaxPageSize:        getEnvInt("MAX_PAGE_SIZE", 100),
		ClickhouseAddr:     getEnv("CLICKHOUSE_ADDR", "clickhouse://65.21.56.89:9000?sslmode=disable"),
		RootChainURL:       getEnv("ROOT_CHAIN_URL", "ws://localhost:8081"),
		RootChainID:        uint64(getEnvInt("ROOT_CHAIN_ID", 1)),
		RootChainRPCURL:    getEnv("ROOT_CHAIN_RPC_URL", "http://lo
validate method · go · L90-L104 (15 LOC)
internal/config/config.go
func (c *Config) validate() error {
	if c.DatabaseURL == "" {
		return fmt.Errorf("DATABASE_URL is required")
	}

	if c.JWTSecret == "" {
		return fmt.Errorf("JWT_SECRET is required")
	}

	if len(c.JWTSecret) < 32 {
		return fmt.Errorf("JWT_SECRET must be at least 32 characters long")
	}

	return nil
}
Repobility (the analyzer behind this table) · https://repobility.com
IsDevelopment method · go · L106-L108 (3 LOC)
internal/config/config.go
func (c *Config) IsDevelopment() bool {
	return c.Environment == "development"
}
IsProduction method · go · L110-L112 (3 LOC)
internal/config/config.go
func (c *Config) IsProduction() bool {
	return c.Environment == "production"
}
getEnv function · go · L114-L119 (6 LOC)
internal/config/config.go
func getEnv(key, defaultValue string) string {
	if value := os.Getenv(key); value != "" {
		return value
	}
	return defaultValue
}
getEnvInt function · go · L121-L128 (8 LOC)
internal/config/config.go
func getEnvInt(key string, defaultValue int) int {
	if value := os.Getenv(key); value != "" {
		if intValue, err := strconv.Atoi(value); err == nil {
			return intValue
		}
	}
	return defaultValue
}
getEnvInt64 function · go · L130-L137 (8 LOC)
internal/config/config.go
func getEnvInt64(key string, defaultValue int64) int64 {
	if value := os.Getenv(key); value != "" {
		if intValue, err := strconv.ParseInt(value, 10, 64); err == nil {
			return intValue
		}
	}
	return defaultValue
}
getEnvBool function · go · L139-L146 (8 LOC)
internal/config/config.go
func getEnvBool(key string, defaultValue bool) bool {
	if value := os.Getenv(key); value != "" {
		if boolValue, err := strconv.ParseBool(value); err == nil {
			return boolValue
		}
	}
	return defaultValue
}
NewGenesisGenerator function · go · L43-L47 (5 LOC)
internal/graduator/genesis_generator.go
func NewGenesisGenerator(templatePath string) *GenesisGenerator {
	return &GenesisGenerator{
		renderer: NewTemplateRenderer(templatePath),
	}
}
Generate method · go · L50-L99 (50 LOC)
internal/graduator/genesis_generator.go
func (g *GenesisGenerator) Generate(
	ctx context.Context,
	chain *models.Chain,
	pool *models.VirtualPool,
	positions []types.UserPositionWithAddress,
) (string, error) {
	// Convert CNPY reserve to micro units (1 CNPY = 1,000,000 uCNPY)
	// CNPYReserve is stored as float64 in CNPY units, must be converted to uint64 in micro units
	cnpyAmountInMicroCNPY := uint64(pool.CNPYReserve * 1_000_000)

	// Convert to genesis accounts and pool points
	accounts := make([]GenesisAccount, len(positions))
	poolPoints := make([]*GenesisPoolPoint, len(positions))

	for i, pos := range positions {
		accounts[i] = GenesisAccount{
			Address: pos.WalletAddress,
			Amount:  pos.TokenBalance,
		}

		// Create pool points - use token balance as points
		points := uint64(pos.TokenBalance)
		poolPoints[i] = &GenesisPoolPoint{
			Address: pos.WalletAddress,
			Points:  points,
		}
	}

	// Calculate TotalPoolPoints per specification: genesis_supply - virtual_pool_token_reserve
	totalPoolPoints := uint64(chain.
Powered by Repobility — scan your code at https://repobility.com
New function · go · L23-L37 (15 LOC)
internal/graduator/graduator.go
func New(
	chainGraduator ChainGraduator,
	poolGraduator VirtualPoolGraduator,
	notifier GraduationNotifier,
	templatePath string,
	rpcEndpoint string,
) *Graduator {
	return &Graduator{
		chainGraduator: chainGraduator,
		poolGraduator:  poolGraduator,
		genesisGen:     NewGenesisGenerator(templatePath),
		rpcClient:      NewGraduationRPCClient(rpcEndpoint),
		notifier:       notifier,
	}
}
CheckAndGraduate method · go · L40-L137 (98 LOC)
internal/graduator/graduator.go
func (g *Graduator) CheckAndGraduate(ctx context.Context, chainID uint64) error {
	// Get the chain with relationships
	chain, err := g.chainGraduator.GetByID(ctx, chainID, []string{"creator", "repository"})
	if err != nil {
		return fmt.Errorf("failed to get chain: %w", err)
	}

	// Check if already graduated
	if chain.IsGraduated {
		return ErrAlreadyGraduated
	}

	// Get virtual pool
	pool, err := g.poolGraduator.GetPoolByChainID(ctx, chainID)
	if err != nil {
		return fmt.Errorf("failed to get virtual pool: %w", err)
	}

	// Check if pool value meets graduation threshold
	if pool.CNPYReserve < chain.GraduationThreshold {
		return fmt.Errorf("%w: current %v, required %v", ErrThresholdNotMet, pool.CNPYReserve, chain.GraduationThreshold)
	}

	// Get positions for genesis generation
	positions, err := g.poolGraduator.GetPositionsWithUsersByChainID(ctx, chainID)
	if err != nil {
		return fmt.Errorf("failed to get positions: %w", err)
	}

	// Generate genesis file
	genesisFile, err := g.
NewGraduationRPCClient function · go · L35-L42 (8 LOC)
internal/graduator/rpc_client.go
func NewGraduationRPCClient(endpoint string) *GraduationRPCClient {
	return &GraduationRPCClient{
		endpoint: endpoint,
		httpClient: &http.Client{
			Timeout: 30 * time.Second,
		},
	}
}
Graduate method · go · L45-L119 (75 LOC)
internal/graduator/rpc_client.go
func (c *GraduationRPCClient) Graduate(ctx context.Context, chain *models.Chain, genesisFile string) error {
	// Validate required relationships are loaded
	if chain.Creator == nil {
		return ErrCreatorNotLoaded
	}

	// Validate BlockTimeSeconds is set
	if chain.BlockTimeSeconds == nil {
		return ErrBlockTimeNotSet
	}

	// Handle missing repository - log warning but continue with placeholder
	githubRepo := ""
	if chain.Repository == nil {
		log.Printf("[WARNING] Chain %s (ID: %d) graduating without repository configuration", chain.ChainName, chain.ID)
		githubRepo = "pending-configuration"
	} else {
		githubRepo = chain.Repository.GithubURL
	}

	// Prepare tokenomics data
	tokenomics := map[string]interface{}{
		"token_name":          chain.TokenName,
		"token_symbol":        chain.TokenSymbol,
		"token_total_supply":  chain.GenesisSupply,
		"block_reward_amount": chain.BlockRewardAmount,
	}

	// Prepare RPC payload
	payload := GraduationRPCPayload{
		Username:         getStringValue(c
getStringValue function · go · L122-L127 (6 LOC)
internal/graduator/rpc_client.go
func getStringValue(s *string) string {
	if s == nil {
		return ""
	}
	return *s
}
NewTemplateRenderer function · go · L15-L19 (5 LOC)
internal/graduator/template_renderer.go
func NewTemplateRenderer(templatePath string) *TemplateRenderer {
	return &TemplateRenderer{
		templatePath: templatePath,
	}
}
Render method · go · L22-L36 (15 LOC)
internal/graduator/template_renderer.go
func (r *TemplateRenderer) Render(data interface{}) (string, error) {
	// Parse template file
	tmpl, err := template.ParseFiles(r.templatePath)
	if err != nil {
		return "", fmt.Errorf("failed to parse template: %w", err)
	}

	// Execute template to buffer
	var buf bytes.Buffer
	if err := tmpl.Execute(&buf, data); err != nil {
		return "", fmt.Errorf("failed to execute template: %w", err)
	}

	return buf.String(), nil
}
NewAddressBookHandler function · go · L24-L30 (7 LOC)
internal/handlers/address_book.go
func NewAddressBookHandler(addressBookService *addressbook.Service, validator *validators.Validator, logger *zap.Logger) *AddressBookHandler {
	return &AddressBookHandler{
		addressBookService: addressBookService,
		validator:          validator,
		logger:             logger,
	}
}
Repobility · severity-and-effort ranking · https://repobility.com
CreateEntry method · go · L33-L79 (47 LOC)
internal/handlers/address_book.go
func (h *AddressBookHandler) CreateEntry(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Get authenticated user ID from context
	userIDStr, ok := ctx.Value("userID").(string)
	if !ok {
		response.Unauthorized(w, "Authentication required")
		return
	}

	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid user ID", err.Error())
		return
	}

	var req models.CreateAddressBookEntryRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		response.BadRequest(w, "Invalid JSON payload", err.Error())
		return
	}

	// Validate request
	if err := h.validator.Validate(&req); err != nil {
		validationErrors := h.validator.FormatErrors(err)
		response.ValidationError(w, validationErrors)
		return
	}

	// Create address book entry
	entry, err := h.addressBookService.CreateEntry(ctx, userID, &req)
	if err != nil {
		if err == addressbook.ErrDuplicateAddressEntry {
			response.Conflict(w, "Address already exists in address book", "")
GetEntry method · go · L82-L123 (42 LOC)
internal/handlers/address_book.go
func (h *AddressBookHandler) GetEntry(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Get authenticated user ID from context
	userIDStr, ok := ctx.Value("userID").(string)
	if !ok {
		response.Unauthorized(w, "Authentication required")
		return
	}

	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid user ID", err.Error())
		return
	}

	// Parse entry ID from URL
	entryIDStr := chi.URLParam(r, "id")
	entryID, err := uuid.Parse(entryIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid entry ID", err.Error())
		return
	}

	// Get entry
	entry, err := h.addressBookService.GetEntry(ctx, userID, entryID)
	if err != nil {
		if err == addressbook.ErrAddressBookEntryNotFound {
			response.NotFound(w, "Address book entry not found")
			return
		}
		middleware.GetLogger(ctx).Error("failed to get address book entry",
			zap.Error(err),
			zap.String("user_id", userID.String()),
			zap.String("entry_id", entryID.String()),
		)
		response.
ListEntries method · go · L126-L205 (80 LOC)
internal/handlers/address_book.go
func (h *AddressBookHandler) ListEntries(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Get authenticated user ID from context
	userIDStr, ok := ctx.Value("userID").(string)
	if !ok {
		response.Unauthorized(w, "Authentication required")
		return
	}

	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid user ID", err.Error())
		return
	}

	// Parse query parameters
	queryParams := r.URL.Query()

	// Pagination
	page := 1
	if pageStr := queryParams.Get("page"); pageStr != "" {
		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
			page = p
		}
	}

	limit := 20
	if limitStr := queryParams.Get("limit"); limitStr != "" {
		if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
			limit = l
		}
	}

	// Build filters
	filters := models.AddressBookFilters{}

	if chainID := queryParams.Get("chain_id"); chainID != "" {
		filters.ChainID = &chainID
	}

	if contactLabel := queryParams.Get("contact_label"); contactLabel
UpdateEntry method · go · L208-L262 (55 LOC)
internal/handlers/address_book.go
func (h *AddressBookHandler) UpdateEntry(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Get authenticated user ID from context
	userIDStr, ok := ctx.Value("userID").(string)
	if !ok {
		response.Unauthorized(w, "Authentication required")
		return
	}

	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid user ID", err.Error())
		return
	}

	// Parse entry ID from URL
	entryIDStr := chi.URLParam(r, "id")
	entryID, err := uuid.Parse(entryIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid entry ID", err.Error())
		return
	}

	var req models.UpdateAddressBookEntryRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		response.BadRequest(w, "Invalid JSON payload", err.Error())
		return
	}

	// Validate request
	if err := h.validator.Validate(&req); err != nil {
		validationErrors := h.validator.FormatErrors(err)
		response.ValidationError(w, validationErrors)
		return
	}

	// Update entry
	entry, err := h.addressB
DeleteEntry method · go · L265-L306 (42 LOC)
internal/handlers/address_book.go
func (h *AddressBookHandler) DeleteEntry(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Get authenticated user ID from context
	userIDStr, ok := ctx.Value("userID").(string)
	if !ok {
		response.Unauthorized(w, "Authentication required")
		return
	}

	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid user ID", err.Error())
		return
	}

	// Parse entry ID from URL
	entryIDStr := chi.URLParam(r, "id")
	entryID, err := uuid.Parse(entryIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid entry ID", err.Error())
		return
	}

	// Delete entry
	err = h.addressBookService.DeleteEntry(ctx, userID, entryID)
	if err != nil {
		if err == addressbook.ErrAddressBookEntryNotFound {
			response.NotFound(w, "Address book entry not found")
			return
		}
		middleware.GetLogger(ctx).Error("failed to delete address book entry",
			zap.Error(err),
			zap.String("user_id", userID.String()),
			zap.String("entry_id", entryID.String()),
		)
		respo
GetFavorites method · go · L309-L354 (46 LOC)
internal/handlers/address_book.go
func (h *AddressBookHandler) GetFavorites(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Get authenticated user ID from context
	userIDStr, ok := ctx.Value("userID").(string)
	if !ok {
		response.Unauthorized(w, "Authentication required")
		return
	}

	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid user ID", err.Error())
		return
	}

	// Parse query parameters
	queryParams := r.URL.Query()

	page := 1
	if pageStr := queryParams.Get("page"); pageStr != "" {
		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
			page = p
		}
	}

	limit := 20
	if limitStr := queryParams.Get("limit"); limitStr != "" {
		if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
			limit = l
		}
	}

	// Get favorites
	result, err := h.addressBookService.GetFavorites(ctx, userID, page, limit)
	if err != nil {
		middleware.GetLogger(ctx).Error("failed to get favorites",
			zap.Error(err),
			zap.String("user_id", userID.String())
SearchEntries method · go · L357-L409 (53 LOC)
internal/handlers/address_book.go
func (h *AddressBookHandler) SearchEntries(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	// Get authenticated user ID from context
	userIDStr, ok := ctx.Value("userID").(string)
	if !ok {
		response.Unauthorized(w, "Authentication required")
		return
	}

	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		response.BadRequest(w, "Invalid user ID", err.Error())
		return
	}

	// Parse query parameters
	queryParams := r.URL.Query()

	query := queryParams.Get("q")
	if query == "" {
		response.BadRequest(w, "Search query is required", "")
		return
	}

	page := 1
	if pageStr := queryParams.Get("page"); pageStr != "" {
		if p, err := strconv.Atoi(pageStr); err == nil && p > 0 {
			page = p
		}
	}

	limit := 20
	if limitStr := queryParams.Get("limit"); limitStr != "" {
		if l, err := strconv.Atoi(limitStr); err == nil && l > 0 && l <= 100 {
			limit = l
		}
	}

	// Search entries
	result, err := h.addressBookService.SearchEntries(ctx, userID, query, page, limit)
	if err !
NewAMMHandler function · go · L23-L29 (7 LOC)
internal/handlers/amm.go
func NewAMMHandler(ammService *amm.Service, validator *validators.Validator, logger *zap.Logger) *AMMHandler {
	return &AMMHandler{
		ammService: ammService,
		validator:  validator,
		logger:     logger,
	}
}
Provenance: Repobility (https://repobility.com) — every score reproducible from /scan/
DepositLiquidity method · go · L32-L59 (28 LOC)
internal/handlers/amm.go
func (h *AMMHandler) DepositLiquidity(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	var req models.DepositLiquidityRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		response.BadRequest(w, "Invalid JSON payload", err.Error())
		return
	}

	// Validate request
	if err := h.validator.Validate(&req); err != nil {
		validationErrors := h.validator.FormatErrors(err)
		response.ValidationError(w, validationErrors)
		return
	}

	// Deposit liquidity
	depositResponse, err := h.ammService.DepositLiquidity(ctx, &req)
	if err != nil {
		middleware.GetLogger(ctx).Error("failed to deposit liquidity",
			zap.Error(err),
		)
		response.InternalServerError(w, "Failed to deposit liquidity")
		return
	}

	response.Success(w, http.StatusOK, depositResponse)
}
WithdrawLiquidity method · go · L62-L89 (28 LOC)
internal/handlers/amm.go
func (h *AMMHandler) WithdrawLiquidity(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	var req models.WithdrawLiquidityRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		response.BadRequest(w, "Invalid JSON payload", err.Error())
		return
	}

	// Validate request
	if err := h.validator.Validate(&req); err != nil {
		validationErrors := h.validator.FormatErrors(err)
		response.ValidationError(w, validationErrors)
		return
	}

	// Withdraw liquidity
	withdrawResponse, err := h.ammService.WithdrawLiquidity(ctx, &req)
	if err != nil {
		middleware.GetLogger(ctx).Error("failed to withdraw liquidity",
			zap.Error(err),
		)
		response.InternalServerError(w, "Failed to withdraw liquidity")
		return
	}

	response.Success(w, http.StatusOK, withdrawResponse)
}
PlaceLimitOrder method · go · L92-L119 (28 LOC)
internal/handlers/amm.go
func (h *AMMHandler) PlaceLimitOrder(w http.ResponseWriter, r *http.Request) {
	ctx := r.Context()

	var req models.LimitOrderRequest
	if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
		response.BadRequest(w, "Invalid JSON payload", err.Error())
		return
	}

	// Validate request
	if err := h.validator.Validate(&req); err != nil {
		validationErrors := h.validator.FormatErrors(err)
		response.ValidationError(w, validationErrors)
		return
	}

	// Place limit order
	orderResponse, err := h.ammService.PlaceLimitOrder(ctx, &req)
	if err != nil {
		middleware.GetLogger(ctx).Error("failed to place limit order",
			zap.Error(err),
		)
		response.InternalServerError(w, "Failed to place limit order")
		return
	}

	response.Success(w, http.StatusOK, orderResponse)
}
‹ prevpage 4 / 23next ›