cmd: improve pretty-printing, add get-version
- update get-height's description - update some fields to prefer uint64 rather than `int` all those fields would never take negative values and should be able to grow quite a lot - switch commands from display to humanize `humanize` gives us some pretty handy human readable conversions, so let's just go with it rather than rolling our own - add get-version command - prettify get-transaction pool example out (hash reduced in size): AGE HASH FEE (µɱ) FEE (µɱ per-kB) SIZE in/out 1 minute ago 1a053e4058839b21c4 9 6.4 1.5 kB 1/2 1 minute ago fb61680a1584ca1ec3 9 6.4 1.5 kB 1/2 1 minute ago a58de0d2747cdd6a5d 12 6.4 2.0 kB 2/2 1 minute ago c54f4b33ed81335f78 308 160.6 2.0 kB 2/2 57 seconds ago ab210c55bd9c3efe09 12 6.4 2.0 kB 2/2 55 seconds ago 88df3311e19b1280b5 9 6.4 1.5 kB 1/2 51 seconds ago a3aa674ed3d4eb56c6 127 32.5 4.0 kB 6/2 51 seconds ago e896abe686d2f816fc 9 6.4 1.5 kB 1/2 31 seconds ago eb6ea6662ce754d025 9 6.4 1.5 kB 1/2 31 seconds ago 592204223e607cc5d9 9 6.4 1.5 kB 1/2 24 seconds ago ba8d52f90fd45dd32d 12 6.4 2.0 kB 2/2 24 seconds ago 792e68ded7805037c9 12 6.4 2.0 kB 2/2 - move response types to a single file - rework pretty-printing of txn-based cmds Signed-off-by: Ciro S. Costa <utxobr@protonmail.com>
This commit is contained in:
parent
425893dd54
commit
9cf4665b88
|
@ -39,7 +39,7 @@ func (c *getBansCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
|
||||
resp, err := client.GetBans(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get block count: %w", err)
|
||||
return fmt.Errorf("get bans count: %w", err)
|
||||
}
|
||||
|
||||
if c.JSON {
|
||||
|
|
|
@ -1,12 +1,17 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
"github.com/cirocosta/go-monero/cmd/monero/options"
|
||||
"github.com/cirocosta/go-monero/pkg/constant"
|
||||
"github.com/cirocosta/go-monero/pkg/rpc/daemon"
|
||||
)
|
||||
|
||||
|
@ -14,6 +19,9 @@ type getBlockCommand struct {
|
|||
Height uint64
|
||||
Hash string
|
||||
BlockJSON bool
|
||||
JSON bool
|
||||
|
||||
client *daemon.Client
|
||||
}
|
||||
|
||||
func (c *getBlockCommand) Cmd() *cobra.Command {
|
||||
|
@ -29,6 +37,8 @@ func (c *getBlockCommand) Cmd() *cobra.Command {
|
|||
cmd.Flags().StringVar(&c.Hash, "hash",
|
||||
"", "block hash to retrieve the information of")
|
||||
|
||||
cmd.Flags().BoolVar(&c.JSON, "json",
|
||||
false, "whether or not to output the result as json")
|
||||
cmd.Flags().BoolVar(&c.BlockJSON, "block-json",
|
||||
false, "display just the block json (from the `json` field)")
|
||||
|
||||
|
@ -44,6 +54,10 @@ func (c *getBlockCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
return fmt.Errorf("client: %w", err)
|
||||
}
|
||||
|
||||
if c.Hash == "" && c.Height == 0 {
|
||||
return fmt.Errorf("hash or height must be set")
|
||||
}
|
||||
|
||||
resp, err := client.GetBlock(ctx, daemon.GetBlockRequestParameters{
|
||||
Hash: c.Hash,
|
||||
Height: c.Height,
|
||||
|
@ -52,16 +66,68 @@ func (c *getBlockCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
return fmt.Errorf("get block: %w", err)
|
||||
}
|
||||
|
||||
if !c.BlockJSON {
|
||||
return display.JSON(resp)
|
||||
if c.JSON {
|
||||
if !c.BlockJSON {
|
||||
return display.JSON(resp)
|
||||
}
|
||||
|
||||
inner, err := resp.InnerJSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("inner json: %w", err)
|
||||
}
|
||||
|
||||
return display.JSON(inner)
|
||||
}
|
||||
|
||||
inner, err := resp.InnerJSON()
|
||||
c.client = client
|
||||
return c.pretty(ctx, resp)
|
||||
}
|
||||
|
||||
func (c *getBlockCommand) pretty(ctx context.Context, v *daemon.GetBlockResult) error {
|
||||
table := display.NewTable()
|
||||
|
||||
blockDetails, err := v.InnerJSON()
|
||||
if err != nil {
|
||||
return fmt.Errorf("inner json: %w", err)
|
||||
}
|
||||
|
||||
return display.JSON(inner)
|
||||
table.AddRow("Hash:", v.BlockHeader.Hash)
|
||||
table.AddRow("Height:", v.BlockHeader.Height)
|
||||
table.AddRow("Age:", humanize.Time(time.Unix(v.BlockHeader.Timestamp, 0)))
|
||||
table.AddRow("Timestamp:", time.Unix(v.BlockHeader.Timestamp, 0))
|
||||
table.AddRow("Size:", humanize.IBytes(v.BlockHeader.BlockSize))
|
||||
table.AddRow("Reward:", fmt.Sprintf("%f XMR", float64(v.BlockHeader.Reward)/constant.XMR))
|
||||
table.AddRow("Total Fees:")
|
||||
table.AddRow("Version:", fmt.Sprintf("%d.%d", blockDetails.MajorVersion, blockDetails.MinorVersion))
|
||||
table.AddRow("Previous Block:", blockDetails.PrevID)
|
||||
table.AddRow("Nonce:", blockDetails.Nonce)
|
||||
table.AddRow("Miner TXN Hash:", v.MinerTxHash)
|
||||
fmt.Println(table)
|
||||
fmt.Println("")
|
||||
|
||||
txnsResult, err := c.client.GetTransactions(ctx, blockDetails.TxHashes)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get txns: %w", err)
|
||||
}
|
||||
|
||||
table = display.NewTable()
|
||||
table.AddRow("HASH", "FEE (µɱ)", "in/out", "SIZE")
|
||||
for _, txn := range txnsResult.Txs {
|
||||
txnDetails := &daemon.TransactionJSON{}
|
||||
if err := json.Unmarshal([]byte(txn.AsJSON), txnDetails); err != nil {
|
||||
return fmt.Errorf("unsmarshal txjson: %w", err)
|
||||
}
|
||||
|
||||
table.AddRow(
|
||||
txn.TxHash,
|
||||
txnDetails.RctSignatures.Txnfee/constant.MicroXMR,
|
||||
fmt.Sprintf("%d/%d", len(txnDetails.Vin), len(txnDetails.Vout)),
|
||||
humanize.IBytes(uint64(len(txn.AsHex))/2),
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -2,8 +2,10 @@ package daemon
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
|
@ -53,16 +55,20 @@ func (c *getConnectionsCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
func (c *getConnectionsCommand) pretty(v *daemon.GetConnectionsResult) {
|
||||
table := display.NewTable()
|
||||
|
||||
table.AddRow("ADDR", "IN", "STATE", "TIME", "RECV (kB)", "SEND (kB)")
|
||||
table.AddRow("ADDR", "IN", "STATE", "HEIGHT", "SINCE", "RECV", "SEND")
|
||||
|
||||
sort.Slice(v.Connections, func(i, j int) bool {
|
||||
return v.Connections[i].LiveTime > v.Connections[j].LiveTime
|
||||
})
|
||||
for _, connection := range v.Connections {
|
||||
table.AddRow(
|
||||
connection.Address,
|
||||
connection.Incoming,
|
||||
connection.State,
|
||||
time.Duration(connection.LiveTime)*time.Second,
|
||||
connection.RecvCount/1024,
|
||||
connection.SendCount/1024,
|
||||
connection.Height,
|
||||
humanize.Time(time.Now().Add(-1*time.Duration(connection.LiveTime)*time.Second)),
|
||||
humanize.IBytes(connection.RecvCount),
|
||||
humanize.IBytes(connection.SendCount),
|
||||
)
|
||||
}
|
||||
|
||||
|
|
|
@ -17,8 +17,10 @@ type getHeightCommand struct {
|
|||
func (c *getHeightCommand) Cmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "get-height",
|
||||
Short: "node's current height",
|
||||
RunE: c.RunE,
|
||||
Short: "node's current chain height",
|
||||
Long: `Retrieves the current chain height (most recent block height + 1)
|
||||
including the hash of the most recent block.`,
|
||||
RunE: c.RunE,
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&c.JSON, "json",
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
|
@ -54,8 +55,8 @@ func (c *getNetStatsCommand) pretty(v *daemon.GetNetStatsResult) {
|
|||
table := display.NewTable()
|
||||
|
||||
table.AddRow("Start Time", time.Unix(v.StartTime, 0))
|
||||
table.AddRow("Total In", display.ByteSize(v.TotalBytesIn))
|
||||
table.AddRow("Total Out", display.ByteSize(v.TotalBytesOut))
|
||||
table.AddRow("Total In", humanize.IBytes(v.TotalBytesIn))
|
||||
table.AddRow("Total Out", humanize.IBytes(v.TotalBytesOut))
|
||||
table.AddRow("Total Packets In", v.TotalPacketsIn)
|
||||
table.AddRow("Total Packets Out", v.TotalPacketsOut)
|
||||
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
|
@ -54,7 +55,7 @@ func (c *getPeerListCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
func (c *getPeerListCommand) pretty(v *daemon.GetPeerListResult) {
|
||||
table := display.NewTable()
|
||||
|
||||
table.AddRow("TYPE", "HOST", "PORT ", "RPC", "LAST SEEN")
|
||||
table.AddRow("TYPE", "HOST", "PORT ", "RPC", "SINCE")
|
||||
|
||||
for _, peer := range v.GrayList {
|
||||
table.AddRow("GRAY", peer.Host, peer.Port, peer.RPCPort, "")
|
||||
|
@ -64,7 +65,7 @@ func (c *getPeerListCommand) pretty(v *daemon.GetPeerListResult) {
|
|||
return v.WhiteList[i].LastSeen < v.WhiteList[j].LastSeen
|
||||
})
|
||||
for _, peer := range v.WhiteList {
|
||||
table.AddRow("WHITE", peer.Host, peer.Port, peer.RPCPort, display.Since(time.Unix(peer.LastSeen, 0)))
|
||||
table.AddRow("WHITE", peer.Host, peer.Port, peer.RPCPort, humanize.Time(time.Unix(peer.LastSeen, 0)))
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
"github.com/cirocosta/go-monero/cmd/monero/options"
|
||||
"github.com/cirocosta/go-monero/pkg/rpc/daemon"
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
|
@ -70,7 +71,7 @@ func (c *getPublicNodesCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
func (c *getPublicNodesCommand) pretty(v *daemon.GetPublicNodesResult) {
|
||||
table := display.NewTable()
|
||||
|
||||
table.AddRow("TYPE", "HOST", "RPC PORT", "LAST SEEN")
|
||||
table.AddRow("TYPE", "HOST", "RPC PORT", "SINCE")
|
||||
for _, peer := range v.GrayList {
|
||||
table.AddRow("GRAY", peer.Host, peer.RPCPort, "")
|
||||
}
|
||||
|
@ -79,7 +80,7 @@ func (c *getPublicNodesCommand) pretty(v *daemon.GetPublicNodesResult) {
|
|||
return v.WhiteList[i].LastSeen < v.WhiteList[j].LastSeen
|
||||
})
|
||||
for _, peer := range v.WhiteList {
|
||||
table.AddRow("WHITE", peer.Host, peer.RPCPort, display.Since(time.Unix(peer.LastSeen, 0)))
|
||||
table.AddRow("WHITE", peer.Host, peer.RPCPort, humanize.Time(time.Unix(peer.LastSeen, 0)))
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
|
|
|
@ -1,15 +1,23 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"sort"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
"github.com/cirocosta/go-monero/cmd/monero/options"
|
||||
"github.com/cirocosta/go-monero/pkg/constant"
|
||||
"github.com/cirocosta/go-monero/pkg/rpc/daemon"
|
||||
)
|
||||
|
||||
type getTransactionPoolCommand struct{}
|
||||
type getTransactionPoolCommand struct {
|
||||
JSON bool
|
||||
}
|
||||
|
||||
func (c *getTransactionPoolCommand) Cmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
|
@ -18,6 +26,9 @@ func (c *getTransactionPoolCommand) Cmd() *cobra.Command {
|
|||
RunE: c.RunE,
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&c.JSON, "json",
|
||||
false, "whether or not to output the result as json")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
|
@ -35,7 +46,39 @@ func (c *getTransactionPoolCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
return fmt.Errorf("get block count: %w", err)
|
||||
}
|
||||
|
||||
return display.JSON(resp)
|
||||
if c.JSON {
|
||||
return display.JSON(resp)
|
||||
}
|
||||
|
||||
return c.pretty(resp)
|
||||
}
|
||||
|
||||
func (c *getTransactionPoolCommand) pretty(v *daemon.GetTransactionPoolResult) error {
|
||||
table := display.NewTable()
|
||||
|
||||
table.AddRow("AGE", "HASH", "FEE (µɱ)", "FEE (µɱ per-kB)", "SIZE", "in/out")
|
||||
|
||||
sort.Slice(v.Transactions, func(i, j int) bool {
|
||||
return v.Transactions[i].ReceiveTime < v.Transactions[j].ReceiveTime
|
||||
})
|
||||
for _, txn := range v.Transactions {
|
||||
txnDetails := &daemon.TransactionJSON{}
|
||||
if err := json.Unmarshal([]byte(txn.TxJSON), txnDetails); err != nil {
|
||||
return fmt.Errorf("unsmarshal txjson: %w", err)
|
||||
}
|
||||
|
||||
table.AddRow(
|
||||
humanize.Time(time.Unix(txn.ReceiveTime, 0)),
|
||||
txn.IDHash,
|
||||
txn.Fee/constant.MicroXMR,
|
||||
fmt.Sprintf("%4.1f", (float64(txn.Fee)/constant.MicroXMR)/(float64(txn.BlobSize)/1024)),
|
||||
humanize.IBytes(txn.BlobSize),
|
||||
fmt.Sprintf("%d/%d", len(txnDetails.Vin), len(txnDetails.Vout)),
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
|
|
@ -4,6 +4,7 @@ import (
|
|||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
|
@ -67,7 +68,7 @@ func (c *getTransactionPoolStatsCommand) pretty(v *daemon.GetTransactionPoolStat
|
|||
table.AddRow("Double Spends:", v.PoolStats.NumDoubleSpends)
|
||||
table.AddRow("Failing Transactions:", v.PoolStats.NumFailing)
|
||||
table.AddRow("Not Relayed:", v.PoolStats.NumNotRelayed)
|
||||
table.AddRow("Oldest:", display.Since(time.Unix(v.PoolStats.Oldest, 0)))
|
||||
table.AddRow("Oldest:", humanize.Time(time.Unix(v.PoolStats.Oldest, 0)))
|
||||
table.AddRow("Txns Total:", v.PoolStats.TxsTotal)
|
||||
|
||||
table.AddRow("")
|
||||
|
|
|
@ -1,37 +1,48 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/dustin/go-humanize"
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
"github.com/cirocosta/go-monero/cmd/monero/options"
|
||||
"github.com/cirocosta/go-monero/pkg/constant"
|
||||
"github.com/cirocosta/go-monero/pkg/rpc/daemon"
|
||||
)
|
||||
|
||||
type getTransactionsCommand struct {
|
||||
Txns []string
|
||||
type getTransactionCommand struct {
|
||||
Txn string
|
||||
Unwrap bool
|
||||
JSON bool
|
||||
|
||||
client *daemon.Client
|
||||
}
|
||||
|
||||
func (c *getTransactionsCommand) Cmd() *cobra.Command {
|
||||
func (c *getTransactionCommand) Cmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "get-transactions",
|
||||
Short: "lookup one or more transactions by hash",
|
||||
Use: "get-transaction",
|
||||
Short: "lookup a transaction, in the pool or not",
|
||||
RunE: c.RunE,
|
||||
}
|
||||
|
||||
cmd.Flags().StringArrayVar(&c.Txns, "txn",
|
||||
[]string{}, "hash of a transaction to lookup")
|
||||
cmd.Flags().StringVar(&c.Txn, "txn",
|
||||
"", "hash of a transaction to lookup")
|
||||
cmd.MarkFlagRequired("txn")
|
||||
|
||||
cmd.Flags().BoolVar(&c.JSON, "json",
|
||||
false, "whether or not to output the result as json")
|
||||
cmd.Flags().BoolVar(&c.Unwrap, "unwrap",
|
||||
false, "whether or not to unwrap the json representation of the transaction")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c *getTransactionsCommand) RunE(_ *cobra.Command, _ []string) error {
|
||||
func (c *getTransactionCommand) RunE(_ *cobra.Command, _ []string) error {
|
||||
ctx, cancel := options.RootOptions.Context()
|
||||
defer cancel()
|
||||
|
||||
|
@ -40,23 +51,92 @@ func (c *getTransactionsCommand) RunE(_ *cobra.Command, _ []string) error {
|
|||
return fmt.Errorf("client: %w", err)
|
||||
}
|
||||
|
||||
resp, err := client.GetTransactions(ctx, c.Txns)
|
||||
resp, err := client.GetTransactions(ctx, []string{c.Txn})
|
||||
if err != nil {
|
||||
return fmt.Errorf("get transactions: %w", err)
|
||||
}
|
||||
|
||||
if !c.Unwrap {
|
||||
return display.JSON(resp)
|
||||
if c.JSON {
|
||||
if !c.Unwrap {
|
||||
return display.JSON(resp)
|
||||
}
|
||||
|
||||
txns, err := resp.GetTransactions()
|
||||
if err != nil {
|
||||
return fmt.Errorf("resp get txns: %w", err)
|
||||
}
|
||||
|
||||
return display.JSON(txns)
|
||||
}
|
||||
|
||||
txns, err := resp.GetTransactions()
|
||||
if err != nil {
|
||||
return fmt.Errorf("resp get txns: %w", err)
|
||||
c.client = client
|
||||
return c.pretty(ctx, resp)
|
||||
}
|
||||
|
||||
func (c *getTransactionCommand) pretty(ctx context.Context, v *daemon.GetTransactionsResult) error {
|
||||
table := display.NewTable()
|
||||
txn := v.Txs[0]
|
||||
|
||||
txnDetails := &daemon.TransactionJSON{}
|
||||
if err := json.Unmarshal([]byte(txn.AsJSON), txnDetails); err != nil {
|
||||
return fmt.Errorf("unsmarshal txjson: %w", err)
|
||||
}
|
||||
|
||||
return display.JSON(txns)
|
||||
confirmations := uint64(0)
|
||||
if txn.InPool == false {
|
||||
}
|
||||
|
||||
table.AddRow("Hash:", txn.TxHash)
|
||||
table.AddRow("Fee (µɱ):", txnDetails.RctSignatures.Txnfee/constant.MicroXMR)
|
||||
table.AddRow("In/Out:", fmt.Sprintf("%d/%d", len(txnDetails.Vin), len(txnDetails.Vout)))
|
||||
table.AddRow("Size:", humanize.IBytes(uint64(len(txn.AsHex))/2))
|
||||
|
||||
if txn.InPool == false {
|
||||
table.AddRow("Age:", humanize.Time(time.Unix(txn.BlockTimestamp, 0)))
|
||||
table.AddRow("Block:", txn.BlockHeight)
|
||||
|
||||
heightResp, err := c.client.GetHeight(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get block count: %w", err)
|
||||
}
|
||||
|
||||
confirmations = heightResp.Height - txn.BlockHeight
|
||||
table.AddRow("Confirmations:", confirmations)
|
||||
} else {
|
||||
table.AddRow("Confirmations:", 0)
|
||||
}
|
||||
fmt.Println(table)
|
||||
fmt.Println("")
|
||||
|
||||
table = display.NewTable()
|
||||
table.AddRow("INPUTS")
|
||||
table.AddRow("KEY IMAGE", "AMOUNT", "KEY OFFSETS")
|
||||
for _, vin := range txnDetails.Vin {
|
||||
table.AddRow(
|
||||
vin.Key.KImage,
|
||||
vin.Key.Amount,
|
||||
vin.Key.KeyOffsets,
|
||||
)
|
||||
}
|
||||
fmt.Println(table)
|
||||
fmt.Println("")
|
||||
|
||||
table = display.NewTable()
|
||||
table.AddRow("OUTPUTS")
|
||||
table.AddRow("STEALTH ADDR", "AMOUNT", "AMOUNT IDX")
|
||||
for idx, vout := range txnDetails.Vout {
|
||||
table.AddRow(
|
||||
vout.Target.Key,
|
||||
vout.Amount,
|
||||
txn.OutputIndices[idx],
|
||||
)
|
||||
}
|
||||
|
||||
fmt.Println(table)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCommand.AddCommand((&getTransactionsCommand{}).Cmd())
|
||||
RootCommand.AddCommand((&getTransactionCommand{}).Cmd())
|
||||
}
|
||||
|
|
64
cmd/monero/commands/daemon/get_version.go
Normal file
64
cmd/monero/commands/daemon/get_version.go
Normal file
|
@ -0,0 +1,64 @@
|
|||
package daemon
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cirocosta/go-monero/cmd/monero/display"
|
||||
"github.com/cirocosta/go-monero/cmd/monero/options"
|
||||
"github.com/cirocosta/go-monero/pkg/rpc/daemon"
|
||||
)
|
||||
|
||||
type getVersionCommand struct {
|
||||
JSON bool
|
||||
}
|
||||
|
||||
func (c *getVersionCommand) Cmd() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "get-version",
|
||||
Short: "version of the monero daemon",
|
||||
RunE: c.RunE,
|
||||
}
|
||||
|
||||
cmd.Flags().BoolVar(&c.JSON, "json",
|
||||
false, "whether or not to output the result as json")
|
||||
|
||||
return cmd
|
||||
}
|
||||
|
||||
func (c *getVersionCommand) RunE(_ *cobra.Command, _ []string) error {
|
||||
ctx, cancel := options.RootOptions.Context()
|
||||
defer cancel()
|
||||
|
||||
client, err := options.RootOptions.Client()
|
||||
if err != nil {
|
||||
return fmt.Errorf("client: %w", err)
|
||||
}
|
||||
|
||||
resp, err := client.GetVersion(ctx)
|
||||
if err != nil {
|
||||
return fmt.Errorf("get block count: %w", err)
|
||||
}
|
||||
|
||||
if c.JSON {
|
||||
return display.JSON(resp)
|
||||
}
|
||||
|
||||
c.pretty(resp)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *getVersionCommand) pretty(v *daemon.GetVersionResult) {
|
||||
table := display.NewTable()
|
||||
|
||||
table.AddRow("Release:", v.Release)
|
||||
table.AddRow("Major:", v.Version>>16)
|
||||
table.AddRow("Minor:", v.Version&((1<<16)-1))
|
||||
|
||||
fmt.Println(table)
|
||||
}
|
||||
|
||||
func init() {
|
||||
RootCommand.AddCommand((&getVersionCommand{}).Cmd())
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
package display
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
Byte = 1 << (10 * iota)
|
||||
Kilobyte
|
||||
Megabyte
|
||||
Gigabyte
|
||||
Terabyte
|
||||
Petabyte
|
||||
Exabyte
|
||||
)
|
||||
|
||||
// ByteSize returns a human-readable byte string of the form 10M, 12.5K, and so forth. The following units are available:
|
||||
// E: Exabyte
|
||||
// P: Petabyte
|
||||
// T: Terabyte
|
||||
// G: Gigabyte
|
||||
// M: Megabyte
|
||||
// K: Kilobyte
|
||||
// B: Byte
|
||||
// The unit that results in the smallest number greater than or equal to 1 is always chosen.
|
||||
//
|
||||
func ByteSize(bytes uint64) string {
|
||||
unit := ""
|
||||
value := float64(bytes)
|
||||
|
||||
switch {
|
||||
case bytes >= Exabyte:
|
||||
unit = "E"
|
||||
value = value / Exabyte
|
||||
case bytes >= Petabyte:
|
||||
unit = "P"
|
||||
value = value / Petabyte
|
||||
case bytes >= Terabyte:
|
||||
unit = "T"
|
||||
value = value / Terabyte
|
||||
case bytes >= Gigabyte:
|
||||
unit = "G"
|
||||
value = value / Gigabyte
|
||||
case bytes >= Megabyte:
|
||||
unit = "M"
|
||||
value = value / Megabyte
|
||||
case bytes >= Kilobyte:
|
||||
unit = "K"
|
||||
value = value / Kilobyte
|
||||
case bytes >= Byte:
|
||||
unit = "B"
|
||||
case bytes == 0:
|
||||
return "0B"
|
||||
}
|
||||
|
||||
result := strconv.FormatFloat(value, 'f', 1, 64)
|
||||
return strings.TrimSuffix(result, ".0") + unit
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
package display
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
// HoursInMonth represents the approximate number of hours in a month.
|
||||
//
|
||||
// Note that hours per month is approximate due to fluctuations in
|
||||
// month length.
|
||||
//
|
||||
HoursInMonth = 730
|
||||
|
||||
// HoursInDay represents the number of hours in a day.
|
||||
//
|
||||
HoursInDay = 24
|
||||
|
||||
// HoursInWeek represents the number of hours in a week.
|
||||
//
|
||||
HoursInWeek = HoursInDay * 7
|
||||
|
||||
// HoursInYear represents the number of hours in a year.
|
||||
//
|
||||
HoursInYear = HoursInDay * 365
|
||||
)
|
||||
|
||||
// Duration returns a string with a plain English description of the length of
|
||||
// time that the time.Duration t contains.
|
||||
//
|
||||
func Duration(t time.Duration) string {
|
||||
hours := int(t.Hours())
|
||||
minutes := int(t.Minutes())
|
||||
seconds := int(t.Seconds())
|
||||
|
||||
if hours >= HoursInYear {
|
||||
years := hours / HoursInYear
|
||||
|
||||
if years == 1 {
|
||||
return "a year ago"
|
||||
}
|
||||
return fmt.Sprintf("%d years ago", years)
|
||||
}
|
||||
|
||||
if hours >= HoursInMonth {
|
||||
months := hours / HoursInMonth
|
||||
|
||||
if months == 1 {
|
||||
return "about a month ago"
|
||||
}
|
||||
return fmt.Sprintf("about %d months ago", months)
|
||||
}
|
||||
|
||||
if hours >= HoursInWeek {
|
||||
weeks := hours / HoursInWeek
|
||||
|
||||
if weeks == 1 {
|
||||
return "a week ago"
|
||||
}
|
||||
return fmt.Sprintf("%d weeks ago", weeks)
|
||||
}
|
||||
|
||||
if hours >= HoursInDay {
|
||||
days := hours / HoursInDay
|
||||
|
||||
if days == 1 {
|
||||
return "a day ago"
|
||||
}
|
||||
return fmt.Sprintf("%d days ago", days)
|
||||
}
|
||||
|
||||
if hours > 0 {
|
||||
if hours == 1 {
|
||||
return "an hour ago"
|
||||
}
|
||||
return fmt.Sprintf("%d hours ago", hours)
|
||||
}
|
||||
|
||||
if minutes > 0 {
|
||||
if minutes == 1 {
|
||||
return "a minute ago"
|
||||
}
|
||||
return fmt.Sprintf("%d minutes ago", minutes)
|
||||
}
|
||||
|
||||
if seconds > 2 {
|
||||
return strconv.Itoa(seconds) + " seconds ago"
|
||||
}
|
||||
|
||||
return "just now"
|
||||
}
|
||||
|
||||
// Since provides an easy way to call Duration without having to call
|
||||
// time.Since on a time.Time first.
|
||||
func Since(t time.Time) string {
|
||||
return Duration(time.Since(t))
|
||||
}
|
1
go.mod
1
go.mod
|
@ -3,6 +3,7 @@ module github.com/cirocosta/go-monero
|
|||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/dustin/go-humanize v1.0.0
|
||||
github.com/golangci/golangci-lint v1.41.1
|
||||
github.com/gosuri/uitable v0.0.4
|
||||
github.com/mattn/go-isatty v0.0.13 // indirect
|
||||
|
|
1
go.sum
1
go.sum
|
@ -136,6 +136,7 @@ github.com/denis-tingajkin/go-header v0.4.2/go.mod h1:eLRHAVXzE5atsKAnNRDB90WHCF
|
|||
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
|
||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
|
|
|
@ -7,5 +7,7 @@ const (
|
|||
|
||||
// A monero corresponds to 1e12 atomic units.
|
||||
//
|
||||
XMR = 1_000_000_000_000 * AtomicUnit
|
||||
XMR = 1_000_000_000_000 * AtomicUnit
|
||||
MilliXMR = 1_000_000_000 * AtomicUnit
|
||||
MicroXMR = 1_000_000 * AtomicUnit
|
||||
)
|
||||
|
|
|
@ -16,35 +16,6 @@ const (
|
|||
endpointGetTransactions = "/get_transactions"
|
||||
)
|
||||
|
||||
type GetTransactionPoolResult struct {
|
||||
Credits int `json:"credits"`
|
||||
SpentKeyImages []struct {
|
||||
IDHash string `json:"id_hash"`
|
||||
TxsHashes []string `json:"txs_hashes"`
|
||||
} `json:"spent_key_images"`
|
||||
Status string `json:"status"`
|
||||
TopHash string `json:"top_hash"`
|
||||
Transactions []struct {
|
||||
BlobSize int `json:"blob_size"`
|
||||
DoNotRelay bool `json:"do_not_relay"`
|
||||
DoubleSpendSeen bool `json:"double_spend_seen"`
|
||||
Fee int `json:"fee"`
|
||||
IDHash string `json:"id_hash"`
|
||||
KeptByBlock bool `json:"kept_by_block"`
|
||||
LastFailedHeight int `json:"last_failed_height"`
|
||||
LastFailedIDHash string `json:"last_failed_id_hash"`
|
||||
LastRelayedTime int `json:"last_relayed_time"`
|
||||
MaxUsedBlockHeight int `json:"max_used_block_height"`
|
||||
MaxUsedBlockIDHash string `json:"max_used_block_id_hash"`
|
||||
ReceiveTime int `json:"receive_time"`
|
||||
Relayed bool `json:"relayed"`
|
||||
TxBlob string `json:"tx_blob"`
|
||||
TxJSON string `json:"tx_json"`
|
||||
Weight int `json:"weight"`
|
||||
} `json:"transactions"`
|
||||
Untrusted bool `json:"untrusted"`
|
||||
}
|
||||
|
||||
func (c *Client) GetTransactionPool(ctx context.Context) (*GetTransactionPoolResult, error) {
|
||||
resp := &GetTransactionPoolResult{}
|
||||
|
||||
|
@ -111,36 +82,15 @@ func (c *Client) GetNetStats(ctx context.Context) (*GetNetStatsResult, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
type GetTransactionsResult struct {
|
||||
Credits int `json:"credits"`
|
||||
Status string `json:"status"`
|
||||
TopHash string `json:"top_hash"`
|
||||
Txs []struct {
|
||||
AsHex string `json:"as_hex"`
|
||||
AsJSON string `json:"as_json"`
|
||||
BlockHeight int `json:"block_height"`
|
||||
BlockTimestamp int `json:"block_timestamp"`
|
||||
DoubleSpendSeen bool `json:"double_spend_seen"`
|
||||
InPool bool `json:"in_pool"`
|
||||
OutputIndices []int `json:"output_indices"`
|
||||
PrunableAsHex string `json:"prunable_as_hex"`
|
||||
PrunableHash string `json:"prunable_hash"`
|
||||
PrunedAsHex string `json:"pruned_as_hex"`
|
||||
TxHash string `json:"tx_hash"`
|
||||
} `json:"txs"`
|
||||
TxsAsHex []string `json:"txs_as_hex"`
|
||||
Untrusted bool `json:"untrusted"`
|
||||
}
|
||||
|
||||
func (r *GetTransactionsResult) GetTransactions() ([]*GetTransactionsResultJSONTxn, error) {
|
||||
txns := make([]*GetTransactionsResultJSONTxn, len(r.Txs))
|
||||
func (r *GetTransactionsResult) GetTransactions() ([]*TransactionJSON, error) {
|
||||
txns := make([]*TransactionJSON, len(r.Txs))
|
||||
|
||||
for idx, txn := range r.Txs {
|
||||
if len(txn.AsJSON) == 0 {
|
||||
return nil, fmt.Errorf("txn '%s' w/ empty `.as_json`", txn.TxHash)
|
||||
}
|
||||
|
||||
t := &GetTransactionsResultJSONTxn{}
|
||||
t := &TransactionJSON{}
|
||||
if err := json.Unmarshal([]byte(txn.AsJSON), t); err != nil {
|
||||
return nil, fmt.Errorf("unmarshal txn '%s': %w", txn.TxHash, err)
|
||||
}
|
||||
|
@ -151,55 +101,6 @@ func (r *GetTransactionsResult) GetTransactions() ([]*GetTransactionsResultJSONT
|
|||
return txns, nil
|
||||
}
|
||||
|
||||
type GetTransactionsResultJSONTxn struct {
|
||||
Version int `json:"version"`
|
||||
UnlockTime int `json:"unlock_time"`
|
||||
Vin []struct {
|
||||
Key struct {
|
||||
Amount int `json:"amount"`
|
||||
KeyOffsets []int `json:"key_offsets"`
|
||||
KImage string `json:"k_image"`
|
||||
} `json:"key"`
|
||||
} `json:"vin"`
|
||||
Vout []struct {
|
||||
Amount int `json:"amount"`
|
||||
Target struct {
|
||||
Key string `json:"key"`
|
||||
} `json:"target"`
|
||||
} `json:"vout"`
|
||||
Extra []int `json:"extra"`
|
||||
RctSignatures struct {
|
||||
Type int `json:"type"`
|
||||
Txnfee int `json:"txnFee"`
|
||||
Ecdhinfo []struct {
|
||||
Amount string `json:"amount"`
|
||||
} `json:"ecdhInfo"`
|
||||
Outpk []string `json:"outPk"`
|
||||
} `json:"rct_signatures"`
|
||||
RctsigPrunable struct {
|
||||
Nbp int `json:"nbp"`
|
||||
Bp []struct {
|
||||
A string `json:"A"`
|
||||
S string `json:"S"`
|
||||
T1 string `json:"T1"`
|
||||
T2 string `json:"T2"`
|
||||
Taux string `json:"taux"`
|
||||
Mu string `json:"mu"`
|
||||
L []string `json:"L"`
|
||||
R []string `json:"R"`
|
||||
LowerA string `json:"a"`
|
||||
B string `json:"b"`
|
||||
T string `json:"t"`
|
||||
} `json:"bp"`
|
||||
Clsags []struct {
|
||||
S []string `json:"s"`
|
||||
C1 string `json:"c1"`
|
||||
D string `json:"D"`
|
||||
} `json:"CLSAGs"`
|
||||
Pseudoouts []string `json:"pseudoOuts"`
|
||||
} `json:"rctsig_prunable"`
|
||||
}
|
||||
|
||||
func (c *Client) GetTransactions(ctx context.Context, txns []string) (*GetTransactionsResult, error) {
|
||||
resp := &GetTransactionsResult{}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ import (
|
|||
const (
|
||||
methodGetAlternateChains = "get_alternate_chains"
|
||||
methodGetBans = "get_bans"
|
||||
methodGetVersion = "get_version"
|
||||
methodGetBlock = "get_block"
|
||||
methodGetBlockCount = "get_block_count"
|
||||
methodGetBlockHeaderByHash = "get_block_header_by_hash"
|
||||
|
@ -81,6 +82,20 @@ func (c *Client) GetBans(ctx context.Context) (*GetBansResult, error) {
|
|||
return resp, nil
|
||||
}
|
||||
|
||||
// GetVersion retrieves the version of monerod that the node uses.
|
||||
//
|
||||
// (restricted)
|
||||
//
|
||||
func (c *Client) GetVersion(ctx context.Context) (*GetVersionResult, error) {
|
||||
resp := &GetVersionResult{}
|
||||
|
||||
if err := c.JSONRPC(ctx, methodGetVersion, nil, resp); err != nil {
|
||||
return nil, fmt.Errorf("jsonrpc: %w", err)
|
||||
}
|
||||
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GenerateBlocksRequestParameters is the set of parameters to be passed to the
|
||||
// GenerateBlocks RPC method.
|
||||
//
|
||||
|
|
|
@ -137,6 +137,15 @@ type HardForkInfoResult struct {
|
|||
RPCResultFooter `json:",inline"`
|
||||
}
|
||||
|
||||
// GetVersionResult is the result of a call to the GetVersion RPC method.
|
||||
//
|
||||
type GetVersionResult struct {
|
||||
Release bool `json:"release"`
|
||||
Version uint64 `json:"version"`
|
||||
|
||||
RPCResultFooter `json:",inline"`
|
||||
}
|
||||
|
||||
// GetBansResult is the result of a call to the GetBans RPC method.
|
||||
//
|
||||
type GetBansResult struct {
|
||||
|
@ -268,26 +277,26 @@ type GetPeerListResult struct {
|
|||
type GetConnectionsResult struct {
|
||||
Connections []struct {
|
||||
Address string `json:"address"`
|
||||
AvgDownload int `json:"avg_download"`
|
||||
AvgUpload int `json:"avg_upload"`
|
||||
AvgDownload uint64 `json:"avg_download"`
|
||||
AvgUpload uint64 `json:"avg_upload"`
|
||||
ConnectionID string `json:"connection_id"`
|
||||
CurrentDownload int `json:"current_download"`
|
||||
CurrentUpload int `json:"current_upload"`
|
||||
Height int `json:"height"`
|
||||
CurrentDownload uint64 `json:"current_download"`
|
||||
CurrentUpload uint64 `json:"current_upload"`
|
||||
Height uint64 `json:"height"`
|
||||
Host string `json:"host"`
|
||||
Incoming bool `json:"incoming"`
|
||||
IP string `json:"ip"`
|
||||
LiveTime int64 `json:"live_time"`
|
||||
LiveTime uint64 `json:"live_time"`
|
||||
LocalIP bool `json:"local_ip"`
|
||||
Localhost bool `json:"localhost"`
|
||||
PeerID string `json:"peer_id"`
|
||||
Port string `json:"port"`
|
||||
RecvCount int `json:"recv_count"`
|
||||
RecvIdleTime int `json:"recv_idle_time"`
|
||||
SendCount int `json:"send_count"`
|
||||
SendIdleTime int `json:"send_idle_time"`
|
||||
RecvCount uint64 `json:"recv_count"`
|
||||
RecvIdleTime uint64 `json:"recv_idle_time"`
|
||||
SendCount uint64 `json:"send_count"`
|
||||
SendIdleTime uint64 `json:"send_idle_time"`
|
||||
State string `json:"state"`
|
||||
SupportFlags int `json:"support_flags"`
|
||||
SupportFlags uint64 `json:"support_flags"`
|
||||
} `json:"connections"`
|
||||
|
||||
RPCResultFooter `json:",inline"`
|
||||
|
@ -451,7 +460,7 @@ type BlockHeader struct {
|
|||
// Timestamp is the unix timestamp at which the block was
|
||||
// recorded into the blockchain.
|
||||
//
|
||||
Timestamp uint64 `json:"timestamp"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
|
||||
// WideCumulativeDifficulty is the cumulative difficulty of all
|
||||
// blocks in the blockchain as a hexadecimal string
|
||||
|
@ -532,7 +541,7 @@ type GetBlockResultJSON struct {
|
|||
// Vout lists the transaction outputs.
|
||||
//
|
||||
Vout []struct {
|
||||
Amount int64 `json:"amount"`
|
||||
Amount uint64 `json:"amount"`
|
||||
Target struct {
|
||||
Key string `json:"key"`
|
||||
} `json:"target"`
|
||||
|
@ -557,6 +566,16 @@ type GetBlockResultJSON struct {
|
|||
TxHashes []string `json:"tx_hashes"`
|
||||
}
|
||||
|
||||
func (c *GetBlockResultJSON) MinerOutputs() uint64 {
|
||||
res := uint64(0)
|
||||
|
||||
for _, vout := range c.MinerTx.Vout {
|
||||
res += vout.Amount
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
// SyncInfoResult is the result of a call to the SyncInfo RPC method.
|
||||
//
|
||||
type SyncInfoResult struct {
|
||||
|
@ -643,3 +662,102 @@ type GetTransactionPoolStatsResult struct {
|
|||
|
||||
RPCResultFooter `json:",inline"`
|
||||
}
|
||||
|
||||
type GetTransactionsResult struct {
|
||||
Credits int `json:"credits"`
|
||||
Status string `json:"status"`
|
||||
TopHash string `json:"top_hash"`
|
||||
Txs []struct {
|
||||
AsHex string `json:"as_hex"`
|
||||
AsJSON string `json:"as_json"`
|
||||
BlockHeight uint64 `json:"block_height"`
|
||||
BlockTimestamp int64 `json:"block_timestamp"`
|
||||
DoubleSpendSeen bool `json:"double_spend_seen"`
|
||||
InPool bool `json:"in_pool"`
|
||||
OutputIndices []int `json:"output_indices"`
|
||||
PrunableAsHex string `json:"prunable_as_hex"`
|
||||
PrunableHash string `json:"prunable_hash"`
|
||||
PrunedAsHex string `json:"pruned_as_hex"`
|
||||
TxHash string `json:"tx_hash"`
|
||||
} `json:"txs"`
|
||||
TxsAsHex []string `json:"txs_as_hex"`
|
||||
Untrusted bool `json:"untrusted"`
|
||||
}
|
||||
|
||||
type TransactionJSON struct {
|
||||
Version int `json:"version"`
|
||||
UnlockTime int `json:"unlock_time"`
|
||||
Vin []struct {
|
||||
Key struct {
|
||||
Amount int `json:"amount"`
|
||||
KeyOffsets []int `json:"key_offsets"`
|
||||
KImage string `json:"k_image"`
|
||||
} `json:"key"`
|
||||
} `json:"vin"`
|
||||
Vout []struct {
|
||||
Amount int `json:"amount"`
|
||||
Target struct {
|
||||
Key string `json:"key"`
|
||||
} `json:"target"`
|
||||
} `json:"vout"`
|
||||
Extra []int `json:"extra"`
|
||||
RctSignatures struct {
|
||||
Type int `json:"type"`
|
||||
Txnfee int `json:"txnFee"`
|
||||
Ecdhinfo []struct {
|
||||
Amount string `json:"amount"`
|
||||
} `json:"ecdhInfo"`
|
||||
Outpk []string `json:"outPk"`
|
||||
} `json:"rct_signatures"`
|
||||
RctsigPrunable struct {
|
||||
Nbp int `json:"nbp"`
|
||||
Bp []struct {
|
||||
A string `json:"A"`
|
||||
S string `json:"S"`
|
||||
T1 string `json:"T1"`
|
||||
T2 string `json:"T2"`
|
||||
Taux string `json:"taux"`
|
||||
Mu string `json:"mu"`
|
||||
L []string `json:"L"`
|
||||
R []string `json:"R"`
|
||||
LowerA string `json:"a"`
|
||||
B string `json:"b"`
|
||||
T string `json:"t"`
|
||||
} `json:"bp"`
|
||||
Clsags []struct {
|
||||
S []string `json:"s"`
|
||||
C1 string `json:"c1"`
|
||||
D string `json:"D"`
|
||||
} `json:"CLSAGs"`
|
||||
Pseudoouts []string `json:"pseudoOuts"`
|
||||
} `json:"rctsig_prunable"`
|
||||
}
|
||||
|
||||
type GetTransactionPoolResult struct {
|
||||
Credits int `json:"credits"`
|
||||
SpentKeyImages []struct {
|
||||
IDHash string `json:"id_hash"`
|
||||
TxsHashes []string `json:"txs_hashes"`
|
||||
} `json:"spent_key_images"`
|
||||
Status string `json:"status"`
|
||||
TopHash string `json:"top_hash"`
|
||||
Transactions []struct {
|
||||
BlobSize uint64 `json:"blob_size"`
|
||||
DoNotRelay bool `json:"do_not_relay"`
|
||||
DoubleSpendSeen bool `json:"double_spend_seen"`
|
||||
Fee uint64 `json:"fee"`
|
||||
IDHash string `json:"id_hash"`
|
||||
KeptByBlock bool `json:"kept_by_block"`
|
||||
LastFailedHeight uint64 `json:"last_failed_height"`
|
||||
LastFailedIDHash string `json:"last_failed_id_hash"`
|
||||
LastRelayedTime uint64 `json:"last_relayed_time"`
|
||||
MaxUsedBlockHeight uint64 `json:"max_used_block_height"`
|
||||
MaxUsedBlockIDHash string `json:"max_used_block_id_hash"`
|
||||
ReceiveTime int64 `json:"receive_time"`
|
||||
Relayed bool `json:"relayed"`
|
||||
TxBlob string `json:"tx_blob"`
|
||||
TxJSON string `json:"tx_json"`
|
||||
Weight uint64 `json:"weight"`
|
||||
} `json:"transactions"`
|
||||
Untrusted bool `json:"untrusted"`
|
||||
}
|
Reference in a new issue