diff --git a/rpc/types.go b/rpc/types.go index dd890f4fae..9e37e33c74 100644 --- a/rpc/types.go +++ b/rpc/types.go @@ -68,7 +68,7 @@ const ( ) // UnmarshalJSON parses the given JSON fragment into a BlockNumber. It supports: -// - "latest", "earliest", "pending" and "committed" as string arguments +// - "committed", "finalized", "latest", "earliest" or "pending" as string arguments // - the block number // Returned errors: // - an invalid block number error when the given argument isn't a known strings @@ -109,6 +109,24 @@ func (bn BlockNumber) Int64() int64 { return (int64)(bn) } +// MarshalText implements encoding.TextMarshaler. It marshals: +// - "finalized", "latest", "earliest" or "pending" as strings +// - other numbers as hex +func (bn BlockNumber) MarshalText() ([]byte, error) { + switch bn { + case EarliestBlockNumber: + return []byte("earliest"), nil + case LatestBlockNumber: + return []byte("latest"), nil + case PendingBlockNumber: + return []byte("pending"), nil + case CommittedBlockNumber: + return []byte("finalized"), nil + default: + return hexutil.Uint64(bn).MarshalText() + } +} + func (e *EpochNumber) UnmarshalJSON(data []byte) error { input := trimData(data) if input == "latest" { diff --git a/rpc/types_test.go b/rpc/types_test.go index 47ab5f8aff..f2019c43e7 100644 --- a/rpc/types_test.go +++ b/rpc/types_test.go @@ -19,6 +19,7 @@ package rpc import ( "encoding/json" "math" + "reflect" "testing" "github.com/XinFinOrg/XDPoSChain/common" @@ -122,3 +123,35 @@ func TestBlockNumberOrHash_UnmarshalJSON(t *testing.T) { } } } + +func TestBlockNumberOrHash_WithNumber_MarshalAndUnmarshal(t *testing.T) { + tests := []struct { + name string + number int64 + }{ + {"max", math.MaxInt64}, + {"pending", int64(PendingBlockNumber)}, + {"latest", int64(LatestBlockNumber)}, + {"earliest", int64(EarliestBlockNumber)}, + {"finalized", int64(CommittedBlockNumber)}, + {"committed", int64(CommittedBlockNumber)}, + } + for _, test := range tests { + test := test + t.Run(test.name, func(t *testing.T) { + bnh := BlockNumberOrHashWithNumber(BlockNumber(test.number)) + marshalled, err := json.Marshal(bnh) + if err != nil { + t.Fatal("cannot marshal:", err) + } + var unmarshalled BlockNumberOrHash + err = json.Unmarshal(marshalled, &unmarshalled) + if err != nil { + t.Fatal("cannot unmarshal:", err) + } + if !reflect.DeepEqual(bnh, unmarshalled) { + t.Fatalf("wrong result: expected %v, got %v", bnh, unmarshalled) + } + }) + } +}