package dashboard import ( "net/http" "sync" "github.com/iotaledger/goshimmer/packages/binary/messagelayer/message" "github.com/iotaledger/goshimmer/plugins/messagelayer" "github.com/labstack/echo" "github.com/pkg/errors" ) // ExplorerMessage defines the struct of the ExplorerMessage. type ExplorerMessage struct { // ID is the message ID. ID string `json:"id"` // Timestamp is the timestamp of the message. Timestamp uint `json:"timestamp"` // TrunkMessageId is the Trunk ID of the message. TrunkMessageID string `json:"trunk_message_id"` // BranchMessageId is the Branch ID of the message. BranchMessageID string `json:"branch_message_id"` // Solid defines the solid status of the message. Solid bool `json:"solid"` } func createExplorerMessage(msg *message.Message) (*ExplorerMessage, error) { messageID := msg.Id() messageMetadata := messagelayer.Tangle.MessageMetadata(messageID) t := &ExplorerMessage{ ID: messageID.String(), Timestamp: 0, TrunkMessageID: msg.TrunkId().String(), BranchMessageID: msg.BranchId().String(), Solid: messageMetadata.Unwrap().IsSolid(), } return t, nil } // ExplorerAddress defines the struct of the ExplorerAddress. type ExplorerAddress struct { // Messagess hold the list of *ExplorerMessage. Messages []*ExplorerMessage `json:"message"` } // SearchResult defines the struct of the SearchResult. type SearchResult struct { // Message is the *ExplorerMessage. Message *ExplorerMessage `json:"message"` // Address is the *ExplorerAddress. Address *ExplorerAddress `json:"address"` } func setupExplorerRoutes(routeGroup *echo.Group) { routeGroup.GET("/message/:id", func(c echo.Context) (err error) { messageID, err := message.NewId(c.Param("id")) if err != nil { return } t, err := findMessage(messageID) if err != nil { return } return c.JSON(http.StatusOK, t) }) routeGroup.GET("/address/:id", func(c echo.Context) error { addr, err := findAddress(c.Param("id")) if err != nil { return err } return c.JSON(http.StatusOK, addr) }) routeGroup.GET("/search/:search", func(c echo.Context) error { search := c.Param("search") result := &SearchResult{} if len(search) < 81 { return errors.Wrapf(ErrInvalidParameter, "search id invalid: %s", search) } wg := sync.WaitGroup{} wg.Add(2) go func() { defer wg.Done() messageID, err := message.NewId(search) if err != nil { return } msg, err := findMessage(messageID) if err == nil { result.Message = msg } }() go func() { defer wg.Done() addr, err := findAddress(search) if err == nil { result.Address = addr } }() wg.Wait() return c.JSON(http.StatusOK, result) }) } func findMessage(messageID message.Id) (explorerMsg *ExplorerMessage, err error) { if !messagelayer.Tangle.Message(messageID).Consume(func(msg *message.Message) { explorerMsg, err = createExplorerMessage(msg) }) { err = errors.Wrapf(ErrNotFound, "message: %s", messageID.String()) } return } func findAddress(address string) (*ExplorerAddress, error) { return nil, errors.Wrapf(ErrNotFound, "address %s not found", address) // TODO: ADD ADDRESS LOOKUPS ONCE THE VALUE TRANSFER ONTOLOGY IS MERGED }