Skip to content

Commit

Permalink
fix events marshalling
Browse files Browse the repository at this point in the history
  • Loading branch information
chris124567 committed Jan 11, 2025
1 parent fbee1da commit 40f78cb
Show file tree
Hide file tree
Showing 5 changed files with 133 additions and 9 deletions.
18 changes: 9 additions & 9 deletions api/api_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -414,15 +414,15 @@ func TestAPI(t *testing.T) {
}},
// There is an issue with JSON unmarshaling of events.
// TODO: fix when explorer.Events are replaced with wallet.Events
// {
// resp, err := client.AddressEvents(addr1, 0, 500)
// if err != nil {
// t.Fatal(err)
// }
// if len(resp) == 0 {
// t.Fatal("no events for addr1")
// }
// }
{"Events", func(t *testing.T) {
resp, err := client.AddressEvents(addr1, 0, 500)
if err != nil {
t.Fatal(err)
}
if len(resp) == 0 {
t.Fatal("no events for addr1")
}
}},
{"Contract", func(t *testing.T) {
resp, err := client.Contract(txn1.FileContractID(0))
if err != nil {
Expand Down
12 changes: 12 additions & 0 deletions api/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,18 @@ func (c *Client) AddressEvents(address types.Address, offset, limit uint64) (res
return
}

// AddressUnconfirmedEvents returns the specified address' unconfirmed events.
func (c *Client) AddressUnconfirmedEvents(address types.Address) (resp []explorer.Event, err error) {
err = c.c.GET(fmt.Sprintf("/addresses/%s/events/unconfirmed", address), &resp)
return
}

// Event returns the specified event.
func (c *Client) Event(id types.Hash256) (resp explorer.Event, err error) {
err = c.c.GET(fmt.Sprintf("/events/%s", id), &resp)
return
}

// AddressBalance returns the specified address' balance.
func (c *Client) AddressBalance(address types.Address) (resp AddressBalanceResponse, err error) {
err = c.c.GET(fmt.Sprintf("/addresses/%s/balance", address), &resp)
Expand Down
49 changes: 49 additions & 0 deletions api/server.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,8 @@ type (
UnspentSiafundOutputs(address types.Address, offset, limit uint64) ([]explorer.SiafundOutput, error)
AddressEvents(address types.Address, offset, limit uint64) (events []explorer.Event, err error)
AddressUnconfirmedEvents(address types.Address) ([]explorer.Event, error)
Events(ids []types.Hash256) ([]explorer.Event, error)
UnconfirmedEvents(index types.ChainIndex, timestamp time.Time, v1 []types.Transaction, v2 []types.V2Transaction) ([]explorer.Event, error)
Contracts(ids []types.FileContractID) (result []explorer.ExtendedFileContract, err error)
ContractsKey(key types.PublicKey) (result []explorer.ExtendedFileContract, err error)
ContractRevisions(id types.FileContractID) (result []explorer.ExtendedFileContract, err error)
Expand Down Expand Up @@ -98,6 +100,9 @@ var (
// ErrHostNotFound is returned by /pubkey/:key/host when we are unable to
// find the host with the pubkey `key`.
ErrHostNotFound = errors.New("no host found")
// ErrEventNotFound is returned by /events/:id when we can't find the event
// with the id `id`.
ErrEventNotFound = errors.New("no event found")

// ErrNoSearchResults is returned by /search/:id when we do not find any
// elements with that ID.
Expand Down Expand Up @@ -483,6 +488,48 @@ func (s *server) addressessAddressEventsUnconfirmedHandler(jc jape.Context) {
jc.Encode(events)
}

func (s *server) eventsIDHandler(jc jape.Context) {
var id types.Hash256
if jc.DecodeParam("id", &id) != nil {
return
}

events, err := s.e.Events([]types.Hash256{id})
if err != nil {
return
} else if len(events) > 0 {
jc.Encode(events[0])
return
}

{
v1, v2 := s.cm.PoolTransactions(), s.cm.V2PoolTransactions()

relevantV1 := v1[:0]
for _, txn := range v1 {
relevantV1 = append(relevantV1, txn)
}

relevantV2 := v2[:0]
for _, txn := range v2 {
relevantV2 = append(relevantV2, txn)
}

events, err := s.e.UnconfirmedEvents(types.ChainIndex{}, types.CurrentTimestamp(), relevantV1, relevantV2)
if jc.Check("failed to annotate events", err) != nil {
return
}
for _, event := range events {
if event.ID == id {
jc.Encode(event)
return
}
}
}

jc.Error(ErrEventNotFound, http.StatusNotFound)
}

func (s *server) outputsSiacoinHandler(jc jape.Context) {
var id types.SiacoinOutputID
if jc.DecodeParam("id", &id) != nil {
Expand Down Expand Up @@ -746,6 +793,8 @@ func NewServer(e Explorer, cm ChainManager, s Syncer) http.Handler {
"GET /addresses/:address/events/unconfirmed": srv.addressessAddressEventsUnconfirmedHandler,
"GET /addresses/:address/balance": srv.addressessAddressBalanceHandler,

"GET /events/:id": srv.eventsIDHandler,

"GET /outputs/siacoin/:id": srv.outputsSiacoinHandler,
"GET /outputs/siafund/:id": srv.outputsSiafundHandler,

Expand Down
52 changes: 52 additions & 0 deletions explorer/events.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package explorer

import (
"encoding/json"
"fmt"
"time"

"go.sia.tech/core/consensus"
Expand Down Expand Up @@ -66,6 +68,56 @@ func (EventV1ContractResolution) isEvent() bool { return true }
func (EventV2Transaction) isEvent() bool { return true }
func (EventV2ContractResolution) isEvent() bool { return true }

// UnmarshalJSON implements the json.Unmarshaler interface.
func (e *Event) UnmarshalJSON(b []byte) error {
var je struct {
ID types.Hash256 `json:"id"`
Index types.ChainIndex `json:"index"`
Timestamp time.Time `json:"timestamp"`
MaturityHeight uint64 `json:"maturityHeight"`
Type string `json:"type"`
Data json.RawMessage `json:"data"`
Relevant []types.Address `json:"relevant,omitempty"`
}
if err := json.Unmarshal(b, &je); err != nil {
return err
}

e.ID = je.ID
e.Index = je.Index
e.Timestamp = je.Timestamp
e.MaturityHeight = je.MaturityHeight
e.Type = je.Type
e.Relevant = je.Relevant

var err error
switch je.Type {
case wallet.EventTypeMinerPayout, wallet.EventTypeFoundationSubsidy, wallet.EventTypeSiafundClaim:
var data EventPayout
err = json.Unmarshal(je.Data, &data)
e.Data = data
case wallet.EventTypeV1ContractResolution:
var data EventV1ContractResolution
err = json.Unmarshal(je.Data, &data)
e.Data = data
case wallet.EventTypeV2ContractResolution:
var data EventV2ContractResolution
err = json.Unmarshal(je.Data, &data)
e.Data = data
case wallet.EventTypeV1Transaction:
var data EventV1Transaction
err = json.Unmarshal(je.Data, &data)
e.Data = data
case wallet.EventTypeV2Transaction:
var data EventV2Transaction
err = json.Unmarshal(je.Data, &data)
e.Data = data
default:
return fmt.Errorf("unknown event type: %v", je.Type)
}
return err
}

// A ChainUpdate is a set of changes to the consensus state.
type ChainUpdate interface {
ForEachSiacoinElement(func(sce types.SiacoinElement, created, spent bool))
Expand Down
11 changes: 11 additions & 0 deletions explorer/explorer.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ type Store interface {
UnspentSiafundOutputs(address types.Address, offset, limit uint64) ([]SiafundOutput, error)
UnconfirmedEvents(index types.ChainIndex, timestamp time.Time, v1 []types.Transaction, v2 []types.V2Transaction) (annotated []Event, err error)
AddressEvents(address types.Address, offset, limit uint64) (events []Event, err error)
Events([]types.Hash256) ([]Event, error)
Balance(address types.Address) (sc types.Currency, immatureSC types.Currency, sf uint64, err error)
Contracts(ids []types.FileContractID) (result []ExtendedFileContract, err error)
ContractsKey(key types.PublicKey) (result []ExtendedFileContract, err error)
Expand Down Expand Up @@ -326,11 +327,21 @@ func (e *Explorer) AddressUnconfirmedEvents(address types.Address) ([]Event, err
return events, nil
}

// UnconfirmedEvents annotates a list of unconfirmed transactions.
func (e *Explorer) UnconfirmedEvents(index types.ChainIndex, timestamp time.Time, v1 []types.Transaction, v2 []types.V2Transaction) ([]Event, error) {
return e.s.UnconfirmedEvents(index, timestamp, v1, v2)
}

// AddressEvents returns the events of a single address.
func (e *Explorer) AddressEvents(address types.Address, offset, limit uint64) (events []Event, err error) {
return e.s.AddressEvents(address, offset, limit)
}

// Events returns the events with the specified IDs.
func (e *Explorer) Events(ids []types.Hash256) ([]Event, error) {
return e.s.Events(ids)
}

// Balance returns the balance of an address.
func (e *Explorer) Balance(address types.Address) (sc types.Currency, immatureSC types.Currency, sf uint64, err error) {
return e.s.Balance(address)
Expand Down

0 comments on commit 40f78cb

Please sign in to comment.