diff --git a/README.md b/README.md index 629afd5..0bf24d4 100644 --- a/README.md +++ b/README.md @@ -21,7 +21,7 @@ If you do not, or have already run the above, run: In order to find the peer id of a running node, execute the following command from the `node/` folder: - GOEXPERIMENT=arenas go run ./... --peer-id + GOEXPERIMENT=arenas go run ./... -peer-id The peer id will be printed to stdout. @@ -36,6 +36,16 @@ Please note: this interface, while read-only, is unauthenticated and not rate- limited. It is recommended that you only enable if you are properly controlling access via firewall or only query via localhost. +## Token Balance + +In order to query the token balance of a running node, execute the following command from the `node/` folder: + + GOEXPERIMENT=arenas go run ./... -balance + +The confirmed token balance will be printed to stdout in QUILs. + +Note that this feature requires that [gRPC support](#experimental--grpcrest-support) is enabled. + ## Purpose The ceremony application provides a secure reference string (SRS) from which diff --git a/node/app/db_console.go b/node/app/db_console.go index 4dec62b..e6d028a 100644 --- a/node/app/db_console.go +++ b/node/app/db_console.go @@ -110,16 +110,11 @@ func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) { if m.conn.GetState() == connectivity.Ready { if m.lastChecked < (time.Now().UnixMilli() - 10_000) { m.lastChecked = time.Now().UnixMilli() - info, err := m.client.GetTokenInfo( - context.Background(), - &protobufs.GetTokenInfoRequest{}, - ) + + tokenBalance, err := FetchTokenBalance(m.client) if err == nil { - conversionFactor, _ := new(big.Int).SetString("1DCD65000", 16) - m.owned = new(big.Int).SetBytes(info.OwnedTokens) - m.owned.Div(m.owned, conversionFactor) - m.unconfirmedOwned = new(big.Int).SetBytes(info.UnconfirmedOwnedTokens) - m.unconfirmedOwned.Div(m.unconfirmedOwned, conversionFactor) + m.owned = tokenBalance.Owned + m.unconfirmedOwned = tokenBalance.UnconfirmedOwned } } } @@ -781,12 +776,13 @@ func consoleModel( } } -// Runs the DB console -func (c *DBConsole) Run() { - grpcWarn := true - addr := "localhost:8337" - if c.nodeConfig.ListenGRPCMultiaddr != "" { - ma, err := multiaddr.NewMultiaddr(c.nodeConfig.ListenGRPCMultiaddr) +var defaultGrpcAddress = "localhost:8337" + +// Connect to the node via GRPC +func ConnectToNode(nodeConfig *config.Config) (*grpc.ClientConn, error) { + addr := defaultGrpcAddress + if nodeConfig.ListenGRPCMultiaddr != "" { + ma, err := multiaddr.NewMultiaddr(nodeConfig.ListenGRPCMultiaddr) if err != nil { panic(err) } @@ -795,10 +791,9 @@ func (c *DBConsole) Run() { if err != nil { panic(err) } - grpcWarn = false } - conn, err := grpc.Dial( + return grpc.Dial( addr, grpc.WithTransportCredentials( insecure.NewCredentials(), @@ -808,11 +803,46 @@ func (c *DBConsole) Run() { grpc.MaxCallRecvMsgSize(600*1024*1024), ), ) +} + +type TokenBalance struct { + Owned *big.Int + UnconfirmedOwned *big.Int +} + +func FetchTokenBalance(client protobufs.NodeServiceClient) (TokenBalance, error) { + info, err := client.GetTokenInfo( + context.Background(), + &protobufs.GetTokenInfoRequest{}, + ) + if err != nil { + return TokenBalance{}, errors.Wrap(err, "error getting token info") + } + + conversionFactor, _ := new(big.Int).SetString("1DCD65000", 16) + + owned := new(big.Int).SetBytes(info.OwnedTokens) + owned.Div(owned, conversionFactor) + + unconfirmedOwned := new(big.Int).SetBytes(info.UnconfirmedOwnedTokens) + unconfirmedOwned.Div(unconfirmedOwned, conversionFactor) + + return TokenBalance{ + Owned: owned, + UnconfirmedOwned: unconfirmedOwned, + }, nil +} + +// Runs the DB console +func (c *DBConsole) Run() { + conn, err := ConnectToNode(c.nodeConfig) if err != nil { panic(err) } - defer conn.Close() + + grpcWarn := c.nodeConfig.ListenGRPCMultiaddr == "" + p := tea.NewProgram(consoleModel(conn, c.nodeConfig, grpcWarn)) if _, err := p.Run(); err != nil { panic(err) diff --git a/node/main.go b/node/main.go index 4502218..446efa2 100644 --- a/node/main.go +++ b/node/main.go @@ -10,6 +10,7 @@ import ( "os" "os/signal" "path/filepath" + "source.quilibrium.com/quilibrium/monorepo/node/protobufs" "syscall" "github.com/libp2p/go-libp2p/core/crypto" @@ -28,17 +29,21 @@ var ( filepath.Join(".", ".config"), "the configuration directory", ) - importPrivKey = flag.String( - "import-priv-key", - "", - "creates a new config using a specific key from the phase one ceremony", + balance = flag.Bool( + "balance", + false, + "print the node's confirmed token balance to stdout and exit", ) dbConsole = flag.Bool( "db-console", false, "starts the node in database console mode", ) - + importPrivKey = flag.String( + "import-priv-key", + "", + "creates a new config using a specific key from the phase one ceremony", + ) peerId = flag.Bool( "peer-id", false, @@ -49,6 +54,35 @@ var ( func main() { flag.Parse() + if *balance { + config, err := config.LoadConfig(*configDirectory, "") + if err != nil { + panic(err) + } + + if config.ListenGRPCMultiaddr == "" { + _, _ = fmt.Fprintf(os.Stderr, "gRPC Not Enabled, Please Configure\n") + os.Exit(1) + } + + conn, err := app.ConnectToNode(config) + if err != nil { + panic(err) + } + defer conn.Close() + + client := protobufs.NewNodeServiceClient(conn) + + balance, err := app.FetchTokenBalance(client) + if err != nil { + panic(err) + } + + fmt.Println("Confirmed balance:", balance.Owned, "QUIL") + + return + } + if *peerId { config, err := config.LoadConfig(*configDirectory, "") if err != nil {