go-blockchain/explorer_command.go
Virgil 29c0e77281 refactor(blockchain): validate chain runtime inputs
Co-Authored-By: Charon <charon@lethean.io>
2026-04-04 11:20:47 +00:00

90 lines
2.3 KiB
Go

// Copyright (c) 2017-2026 Lethean (https://lt.hn)
//
// Licensed under the European Union Public Licence (EUPL) version 1.2.
// SPDX-License-Identifier: EUPL-1.2
package blockchain
import (
"context"
"os"
"os/signal"
"path/filepath"
"sync"
"syscall"
coreerr "dappco.re/go/core/log"
cli "dappco.re/go/core/cli/pkg/cli"
store "dappco.re/go/core/store"
"dappco.re/go/core/blockchain/chain"
"dappco.re/go/core/blockchain/tui"
"github.com/spf13/cobra"
)
const chainExplorerFrameTitle = "Chain Explorer"
// newChainExplorerCommand builds the interactive `chain explorer` command.
//
// Example:
//
// core-chain chain explorer --data-dir ~/.lethean/chain
//
// Use it alongside `AddChainCommands` to expose the TUI node view.
func newChainExplorerCommand(dataDir, seed *string, testnet *bool) *cobra.Command {
return &cobra.Command{
Use: chainExplorerCommandName,
Short: chainExplorerCommandShort,
Long: chainExplorerCommandLong,
Example: chainExplorerExample,
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runChainExplorer(*dataDir, *seed, *testnet)
},
}
}
func runChainExplorer(dataDir, seed string, testnet bool) error {
if err := validateChainRuntimeInputs(dataDir, seed); err != nil {
return err
}
if err := ensureChainDataDirExists(dataDir); err != nil {
return err
}
dbPath := filepath.Join(dataDir, "chain.db")
chainStore, err := store.New(dbPath)
if err != nil {
return coreerr.E("runChainExplorer", "open store", err)
}
defer chainStore.Close()
blockchain := chain.New(chainStore)
chainConfig, hardForks, resolvedSeed := chainConfigForSeed(testnet, seed)
ctx, cancel := signal.NotifyContext(context.Background(), os.Interrupt, syscall.SIGTERM)
defer cancel()
var wg sync.WaitGroup
wg.Add(1)
go func() {
defer wg.Done()
runChainSyncLoop(ctx, blockchain, &chainConfig, hardForks, resolvedSeed)
}()
node := tui.NewNode(blockchain)
status := tui.NewStatusModel(node)
explorer := tui.NewExplorerModel(blockchain)
hints := tui.NewKeyHintsModel()
explorerFrame := cli.NewFrame(chainExplorerFrameTitle)
explorerFrame.Header(status)
explorerFrame.Content(explorer)
explorerFrame.Footer(hints)
explorerFrame.Run()
cancel() // Signal the sync loop to stop.
wg.Wait() // Wait for it before closing store.
return nil
}