Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
7c8d0e1
FEAT: Start caching hyperblock with lookup keys
mariusmihaic Nov 21, 2025
30728a4
FEAT: Use templates to store cachable blocks
mariusmihaic Nov 21, 2025
6d65d6b
FEAT: Add part of time cacher
mariusmihaic Nov 24, 2025
93f69bf
FEAT: Test block processor cache
mariusmihaic Nov 24, 2025
498274b
CLN: Refactor solution
mariusmihaic Nov 24, 2025
c201a97
FEAT: Extend test to look for keys + lookup keys
mariusmihaic Nov 24, 2025
77c182a
FEAT: Inject timed cache in block processor
mariusmihaic Nov 24, 2025
9ec89c4
FEAT: Config cache duration + test get cached hyper block
mariusmihaic Nov 24, 2025
e82423b
FEAT: Test cached block by hash/nonce
mariusmihaic Nov 24, 2025
cf1a7a8
CLN: After self review
mariusmihaic Nov 25, 2025
9fc0379
FIX: After review pt 1
mariusmihaic Dec 2, 2025
acb543e
FIX: After review pt 2
mariusmihaic Dec 3, 2025
40e3866
Merge pull request #509 from multiversx/MX-17334-cache-block-response
AdoAdoAdo Dec 8, 2025
2c3e733
FEAT: Go core with get proxy block with exec res
mariusmihaic Dec 12, 2025
60e9629
Merge pull request #510 from multiversx/test-proxy-get-block-with-exe…
miiu96 Dec 22, 2025
2176395
process status fixes
miiu96 Dec 22, 2025
9391344
Merge pull request #511 from multiversx/fix-process-status
miiu96 Dec 22, 2025
2b5a701
enable epochs v2
sstanculeanu Jan 21, 2026
e54757a
Merge pull request #513 from multiversx/enable-epochs-v2
sstanculeanu Jan 21, 2026
94f5826
fix description
miiu96 Feb 13, 2026
8338035
fix
miiu96 Feb 13, 2026
5ae9db4
Merge pull request #515 from multiversx/fix-api-description
miiu96 Feb 13, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ For more details, go [here](https://docs.multiversx.com/sdk-and-tools/proxy/).
- `/v1.0/network/direct-staked-info` (GET) --> returns the list of direct staked values
- `/v1.0/network/delegated-info` (GET) --> returns the list of delegated values
- `/v1.0/network/enable-epochs` (GET) --> returns the activation epochs metric
- `/v1.0/network/enable-epochs-v2` (GET) --> returns the newer version of activation epochs
### node

- `/v1.0/node/heartbeatstatus` (GET) --> returns the heartbeat data from an observer from any shard. Has a cache to avoid many requests
Expand Down
11 changes: 11 additions & 0 deletions api/groups/baseNetworkGroup.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ func NewNetworkGroup(facadeHandler data.FacadeHandler) (*networkGroup, error) {
{Path: "/esdt/non-fungible-tokens", Handler: ng.getEsdtHandlerFunc(data.NonFungibleTokens), Method: http.MethodGet},
{Path: "/esdt/supply/:token", Handler: ng.getESDTSupply, Method: http.MethodGet},
{Path: "/enable-epochs", Handler: ng.getEnableEpochs, Method: http.MethodGet},
{Path: "/enable-epochs-v2", Handler: ng.getEnableEpochsV2, Method: http.MethodGet},
{Path: "/direct-staked-info", Handler: ng.getDirectStakedInfo, Method: http.MethodGet},
{Path: "/delegated-info", Handler: ng.getDelegatedInfo, Method: http.MethodGet},
{Path: "/ratings", Handler: ng.getRatingsConfig, Method: http.MethodGet},
Expand Down Expand Up @@ -144,6 +145,16 @@ func (group *networkGroup) getEnableEpochs(c *gin.Context) {
c.JSON(http.StatusOK, enableEpochsMetrics)
}

func (group *networkGroup) getEnableEpochsV2(c *gin.Context) {
enableEpochsMetrics, err := group.facade.GetEnableEpochsMetricsV2()
if err != nil {
shared.RespondWith(c, http.StatusInternalServerError, nil, err.Error(), data.ReturnCodeInternalError)
return
}

c.JSON(http.StatusOK, enableEpochsMetrics)
}

func (group *networkGroup) getESDTSupply(c *gin.Context) {
tokenIdentifier := c.Param("token")
if tokenIdentifier == "" {
Expand Down
81 changes: 78 additions & 3 deletions api/groups/baseNetworkGroup_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -216,7 +216,7 @@ func TestGetEconomicsData_ShouldWork(t *testing.T) {

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, expectedResp, ecDataResp)
assert.Equal(t, expectedResp.Data, ecDataResp.Data) //extra safe
assert.Equal(t, expectedResp.Data, ecDataResp.Data) // extra safe
}

func TestGetAllIssuedESDTs_ShouldErr(t *testing.T) {
Expand Down Expand Up @@ -325,7 +325,7 @@ func TestGetDelegatedInfo_ShouldWork(t *testing.T) {

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, expectedResp, delegatedInfoResp)
assert.Equal(t, expectedResp.Data, delegatedInfoResp.Data) //extra safe
assert.Equal(t, expectedResp.Data, delegatedInfoResp.Data) // extra safe
}

func TestGetDirectStaked_ShouldErr(t *testing.T) {
Expand Down Expand Up @@ -374,7 +374,7 @@ func TestGetDirectStaked_ShouldWork(t *testing.T) {

assert.Equal(t, http.StatusOK, resp.Code)
assert.Equal(t, expectedResp, directStakedResp)
assert.Equal(t, expectedResp.Data, directStakedResp.Data) //extra safe
assert.Equal(t, expectedResp.Data, directStakedResp.Data) // extra safe
}

func TestGetEnableEpochsMetrics_FacadeErrShouldErr(t *testing.T) {
Expand Down Expand Up @@ -452,6 +452,81 @@ func TestGetEnableEpochsMetrics_OkRequestShouldWork(t *testing.T) {
assert.Equal(t, value, res)
}

func TestGetEnableEpochsMetricsV2_FacadeErrShouldErr(t *testing.T) {
t.Parallel()

expectedErr := errors.New("expected err")
facade := &mock.FacadeStub{
GetEnableEpochsMetricsV2Handler: func() (*data.GenericAPIResponse, error) {
return nil, expectedErr
},
}
networkGroup, err := groups.NewNetworkGroup(facade)
require.NoError(t, err)
ws := startProxyServer(networkGroup, networkPath)

req, _ := http.NewRequest("GET", "/network/enable-epochs-v2", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)
assert.Equal(t, http.StatusInternalServerError, resp.Code)

var result metricsResponse
loadResponse(resp.Body, &result)

assert.Equal(t, expectedErr.Error(), result.Error)
}

func TestGetEnableEpochsMetricsV2_BadRequestShouldErr(t *testing.T) {
t.Parallel()

facade := &mock.FacadeStub{
GetEnableEpochsMetricsV2Handler: func() (*data.GenericAPIResponse, error) {
return nil, errors.New("bad request")
},
}
networkGroup, err := groups.NewNetworkGroup(facade)
require.NoError(t, err)
ws := startProxyServer(networkGroup, networkPath)

req, _ := http.NewRequest("GET", "/network/enable-epochs-v2", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)

assert.Equal(t, http.StatusInternalServerError, resp.Code)
}

func TestGetEnableEpochsMetricsV2_OkRequestShouldWork(t *testing.T) {
t.Parallel()

key := "SupernovaEnableEpoch"
value := float64(4)
facade := &mock.FacadeStub{
GetEnableEpochsMetricsV2Handler: func() (*data.GenericAPIResponse, error) {
return &data.GenericAPIResponse{
Data: map[string]interface{}{
key: value,
},
Error: "",
}, nil
},
}
networkGroup, err := groups.NewNetworkGroup(facade)
require.NoError(t, err)
ws := startProxyServer(networkGroup, networkPath)

req, _ := http.NewRequest("GET", "/network/enable-epochs-v2", nil)
resp := httptest.NewRecorder()
ws.ServeHTTP(resp, req)
assert.Equal(t, http.StatusOK, resp.Code)

var result metricsResponse
loadResponse(resp.Body, &result)

res, ok := result.Data[key]
assert.True(t, ok)
assert.Equal(t, value, res)
}

func TestGetRatingsConfig_ShouldFail(t *testing.T) {
t.Parallel()

Expand Down
1 change: 1 addition & 0 deletions api/groups/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@ type NetworkFacadeHandler interface {
GetDirectStakedInfo() (*data.GenericAPIResponse, error)
GetDelegatedInfo() (*data.GenericAPIResponse, error)
GetEnableEpochsMetrics() (*data.GenericAPIResponse, error)
GetEnableEpochsMetricsV2() (*data.GenericAPIResponse, error)
GetESDTSupply(token string) (*data.ESDTSupplyResponse, error)
GetRatingsConfig() (*data.GenericAPIResponse, error)
GetGenesisNodesPubKeys() (*data.GenericAPIResponse, error)
Expand Down
6 changes: 6 additions & 0 deletions api/mock/facadeStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type FacadeStub struct {
GetNetworkMetricsHandler func(shardID uint32) (*data.GenericAPIResponse, error)
GetAllIssuedESDTsHandler func(tokenType string) (*data.GenericAPIResponse, error)
GetEnableEpochsMetricsHandler func() (*data.GenericAPIResponse, error)
GetEnableEpochsMetricsV2Handler func() (*data.GenericAPIResponse, error)
GetEconomicsDataMetricsHandler func() (*data.GenericAPIResponse, error)
GetDirectStakedInfoCalled func() (*data.GenericAPIResponse, error)
GetDelegatedInfoCalled func() (*data.GenericAPIResponse, error)
Expand Down Expand Up @@ -235,6 +236,11 @@ func (f *FacadeStub) GetEnableEpochsMetrics() (*data.GenericAPIResponse, error)
return f.GetEnableEpochsMetricsHandler()
}

// GetEnableEpochsMetricsV2 -
func (f *FacadeStub) GetEnableEpochsMetricsV2() (*data.GenericAPIResponse, error) {
return f.GetEnableEpochsMetricsV2Handler()
}

// GetRatingsConfig -
func (f *FacadeStub) GetRatingsConfig() (*data.GenericAPIResponse, error) {
return f.GetRatingsConfigCalled()
Expand Down
1 change: 1 addition & 0 deletions cmd/proxy/config/apiConfig/v1_0.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Routes = [
{ Name = "/direct-staked-info", Open = true, Secured = true, RateLimit = 0 },
{ Name = "/delegated-info", Open = true, Secured = true, RateLimit = 0 },
{ Name = "/enable-epochs", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/enable-epochs-v2", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/ratings", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/genesis-nodes", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/gas-configs", Open = true, Secured = false, RateLimit = 0 },
Expand Down
1 change: 1 addition & 0 deletions cmd/proxy/config/apiConfig/v_next.toml
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ Routes = [
{ Name = "/direct-staked-info", Open = true, Secured = true, RateLimit = 0 },
{ Name = "/delegated-info", Open = true, Secured = true, RateLimit = 0 },
{ Name = "/enable-epochs", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/enable-epochs-v2", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/ratings", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/genesis-nodes", Open = true, Secured = false, RateLimit = 0 },
{ Name = "/gas-configs", Open = true, Secured = false, RateLimit = 0 },
Expand Down
3 changes: 3 additions & 0 deletions cmd/proxy/config/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@
# before it should be updated
EconomicsMetricsCacheValidityDurationSec = 600 # 10 minutes

# BlockCacheDurationSec defines how long block/hyperblock results (queried by hash or nonce) are kept in cache, in seconds.
BlockCacheDurationSec = 30

# BalancedObservers - if this flag is set to true, then the requests will be distributed equally between observers.
# Otherwise, there are chances that only one observer from a shard will process the requests
BalancedObservers = true
Expand Down
24 changes: 22 additions & 2 deletions cmd/proxy/config/swagger/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -316,7 +316,7 @@
"tags": [
"address"
],
"summary": "returns all ESDT tokens that the provided address interacted with",
"summary": "returns all the ESDT Tokens owned by the specified address.",
"parameters": [
{
"name": "address",
Expand Down Expand Up @@ -422,7 +422,7 @@
"tags": [
"address"
],
"summary": "returns all ESDT tokens that the provided address interacted with",
"summary": "returns the details of a specific ESDT token for a given address",
"parameters": [
{
"name": "address",
Expand Down Expand Up @@ -1071,6 +1071,26 @@
}
}
},
"/network/enable-epochs-v2": {
"get": {
"tags": [
"network"
],
"summary": "returns the activation epochs metric",
"responses": {
"200": {
"description": "successful operation",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/GenericResponse"
}
}
}
}
}
}
},
"/network/ratings": {
"get": {
"tags": [
Expand Down
15 changes: 13 additions & 2 deletions cmd/proxy/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
processFactory "github.com/multiversx/mx-chain-proxy-go/process/factory"
"github.com/multiversx/mx-chain-proxy-go/testing"
versionsFactory "github.com/multiversx/mx-chain-proxy-go/versions/factory"
"github.com/multiversx/mx-chain-storage-go/timecache"
"github.com/urfave/cli"
)

Expand Down Expand Up @@ -336,6 +337,7 @@ func createVersionsRegistryTestOrProduction(
HeartbeatCacheValidityDurationSec: 60,
ValStatsCacheValidityDurationSec: 60,
EconomicsMetricsCacheValidityDurationSec: 6,
BlockCacheDurationSec: 30,
FaucetValue: "10000000000",
},
ApiLogging: config.ApiLoggingConfig{
Expand Down Expand Up @@ -512,13 +514,22 @@ func createVersionsRegistry(
return nil, err
}

closableComponents.Add(nodeGroupProc, valStatsProc, nodeStatusProc, bp)
cacheDuration := time.Duration(cfg.GeneralSettings.BlockCacheDurationSec) * time.Second
timedCache, err := timecache.NewTimeCacher(timecache.ArgTimeCacher{
DefaultSpan: cacheDuration,
CacheExpiry: cacheDuration,
})
if err != nil {
return nil, err
}

closableComponents.Add(nodeGroupProc, valStatsProc, nodeStatusProc, bp, timedCache)

nodeGroupProc.StartCacheUpdate()
valStatsProc.StartCacheUpdate()
nodeStatusProc.StartCacheUpdate()

blockProc, err := process.NewBlockProcessor(bp)
blockProc, err := process.NewBlockProcessor(bp, timedCache)
if err != nil {
return nil, err
}
Expand Down
1 change: 1 addition & 0 deletions config/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ type GeneralSettingsConfig struct {
HeartbeatCacheValidityDurationSec int
ValStatsCacheValidityDurationSec int
EconomicsMetricsCacheValidityDurationSec int
BlockCacheDurationSec int
FaucetValue string
RateLimitWindowDurationSeconds int
BalancedObservers bool
Expand Down
20 changes: 20 additions & 0 deletions data/block.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,16 @@ type BlockApiResponse struct {
Code ReturnCode `json:"code"`
}

// Hash returns internal hash
func (h *BlockApiResponse) Hash() string {
return h.Data.Block.Hash
}

// Nonce returns internal nonce
func (h *BlockApiResponse) Nonce() uint64 {
return h.Data.Block.Nonce
}

// BlockApiResponsePayload wraps a block
type BlockApiResponsePayload struct {
Block api.Block `json:"block"`
Expand All @@ -24,6 +34,16 @@ type HyperblockApiResponse struct {
Code ReturnCode `json:"code"`
}

// Hash returns internal hash
func (h *HyperblockApiResponse) Hash() string {
return h.Data.Hyperblock.Hash
}

// Nonce returns internal nonce
func (h *HyperblockApiResponse) Nonce() uint64 {
return h.Data.Hyperblock.Nonce
}

// NewHyperblockApiResponse creates a HyperblockApiResponse
func NewHyperblockApiResponse(hyperblock api.Hyperblock) *HyperblockApiResponse {
return &HyperblockApiResponse{
Expand Down
13 changes: 9 additions & 4 deletions facade/baseFacade.go
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,11 @@ func (pf *ProxyFacade) GetEnableEpochsMetrics() (*data.GenericAPIResponse, error
return pf.nodeStatusProc.GetEnableEpochsMetrics()
}

// GetEnableEpochsMetricsV2 retrieves the activation epochs
func (pf *ProxyFacade) GetEnableEpochsMetricsV2() (*data.GenericAPIResponse, error) {
return pf.nodeStatusProc.GetEnableEpochsMetricsV2()
}

// GetRatingsConfig retrieves the node's configuration's metrics
func (pf *ProxyFacade) GetRatingsConfig() (*data.GenericAPIResponse, error) {
return pf.nodeStatusProc.GetRatingsConfig()
Expand Down Expand Up @@ -406,8 +411,8 @@ func (pf *ProxyFacade) ValidatorStatistics() (map[string]*data.ValidatorApiRespo
}

// AuctionList will return the auction list
func (epf *ProxyFacade) AuctionList() ([]*data.AuctionListValidatorAPIResponse, error) {
auctionList, err := epf.valStatsProc.GetAuctionList()
func (pf *ProxyFacade) AuctionList() ([]*data.AuctionListValidatorAPIResponse, error) {
auctionList, err := pf.valStatsProc.GetAuctionList()
if err != nil {
return nil, err
}
Expand Down Expand Up @@ -536,8 +541,8 @@ func (pf *ProxyFacade) GetInternalStartOfEpochValidatorsInfo(epoch uint32) (*dat
}

// GetWaitingEpochsLeftForPublicKey returns the number of epochs left for the public key until it becomes eligible
func (epf *ProxyFacade) GetWaitingEpochsLeftForPublicKey(publicKey string) (*data.WaitingEpochsLeftApiResponse, error) {
return epf.nodeGroupProc.GetWaitingEpochsLeftForPublicKey(publicKey)
func (pf *ProxyFacade) GetWaitingEpochsLeftForPublicKey(publicKey string) (*data.WaitingEpochsLeftApiResponse, error) {
return pf.nodeGroupProc.GetWaitingEpochsLeftForPublicKey(publicKey)
}

// IsDataTrieMigrated returns true if the data trie for the given address is migrated
Expand Down
1 change: 1 addition & 0 deletions facade/interface.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ type NodeStatusProcessor interface {
GetLatestFullySynchronizedHyperblockNonce() (uint64, error)
GetAllIssuedESDTs(tokenType string) (*data.GenericAPIResponse, error)
GetEnableEpochsMetrics() (*data.GenericAPIResponse, error)
GetEnableEpochsMetricsV2() (*data.GenericAPIResponse, error)
GetDirectStakedInfo() (*data.GenericAPIResponse, error)
GetDelegatedInfo() (*data.GenericAPIResponse, error)
GetRatingsConfig() (*data.GenericAPIResponse, error)
Expand Down
10 changes: 10 additions & 0 deletions facade/mock/nodeStatusProcessorStub.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ type NodeStatusProcessorStub struct {
GetDirectStakedInfoCalled func() (*data.GenericAPIResponse, error)
GetDelegatedInfoCalled func() (*data.GenericAPIResponse, error)
GetEnableEpochsMetricsCalled func() (*data.GenericAPIResponse, error)
GetEnableEpochsMetricsV2Called func() (*data.GenericAPIResponse, error)
GetRatingsConfigCalled func() (*data.GenericAPIResponse, error)
GetGenesisNodesPubKeysCalled func() (*data.GenericAPIResponse, error)
GetGasConfigsCalled func() (*data.GenericAPIResponse, error)
Expand Down Expand Up @@ -91,6 +92,15 @@ func (stub *NodeStatusProcessorStub) GetEnableEpochsMetrics() (*data.GenericAPIR
return &data.GenericAPIResponse{}, nil
}

// GetEnableEpochsMetricsV2 -
func (stub *NodeStatusProcessorStub) GetEnableEpochsMetricsV2() (*data.GenericAPIResponse, error) {
if stub.GetEnableEpochsMetricsV2Called != nil {
return stub.GetEnableEpochsMetricsV2Called()
}

return &data.GenericAPIResponse{}, nil
}

// GetRatingsConfig -
func (stub *NodeStatusProcessorStub) GetRatingsConfig() (*data.GenericAPIResponse, error) {
if stub.GetRatingsConfigCalled != nil {
Expand Down
Loading
Loading