feat: implement node rewards calculation and API endpoint#64
feat: implement node rewards calculation and API endpoint#640oM4R wants to merge 45 commits intodevelopmentfrom
Conversation
… uptime percentage
10c4a79 to
6646f65
Compare
|
|
||
| // Use precise floating point comparison | ||
| const delta = 1e-9 // Very small acceptable difference | ||
| assert.InDelta(t, expected.FarmerReward, got.FarmerReward, delta) |
There was a problem hiding this comment.
all this values are rounded no?
…v4-sdk-go into development_rewards
…ed value checks in rewards tests
| assert.Equal(t, expected.FarmerReward, got.FarmerReward) | ||
| assert.Equal(t, expected.TfReward, got.TfReward) | ||
| assert.Equal(t, expected.FpReward, got.FpReward) | ||
| assert.Equal(t, expected.Total, got.Total) | ||
| assert.Equal(t, expected.UpTimePercentage, got.UpTimePercentage) |
There was a problem hiding this comment.
why not just use assert.Equal(t, expected, got)
There was a problem hiding this comment.
why not just use
assert.Equal(t, expected, got)
Is that enough, or should we use something like deep equal?
There was a problem hiding this comment.
assert.Equal does the same job
…o into development_rewards
| } | ||
|
|
||
| // calculateCapacityReward calculates the reward for a node based on its capacity and uptime, during a specific period. | ||
| func CalculateCapacityReward(capacity db.Resources, reports []db.UptimeReport, periodStart, periodEnd time.Time) (Reward, error) { |
There was a problem hiding this comment.
this function is not used outside the server pkg, so no need to be exported
| assert.Equal(t, expected.FarmerReward, got.FarmerReward) | ||
| assert.Equal(t, expected.TfReward, got.TfReward) | ||
| assert.Equal(t, expected.FpReward, got.FpReward) | ||
| assert.Equal(t, expected.Total, got.Total) | ||
| assert.Equal(t, expected.UpTimePercentage, got.UpTimePercentage) |
There was a problem hiding this comment.
assert.Equal does the same job
| return Reward{}, ErrReportsNotInAscOrder | ||
| } | ||
|
|
||
| upTimePercentage := calculatePercentage(periodEnd.Sub(periodStart), downtimeSinceLastReportTimestamp(reports[len(reports)-1].Timestamp, periodEnd)) |
|
|
||
| upTimePercentage := calculatePercentage(periodEnd.Sub(periodStart), downtimeSinceLastReportTimestamp(reports[len(reports)-1].Timestamp, periodEnd)) | ||
|
|
||
| return computeCapacityRewardWithUptime(capacity, upTimePercentage) |
There was a problem hiding this comment.
calculate instead of compute
| // calculateBaseCapacityReward calculates the base reward from node capacity without applying uptime. | ||
| func calculateBaseCapacityReward(capacity db.Resources) float64 { | ||
| mruReward := bytesToGB(capacity.MRU) * MemoryRewardPerGB | ||
| sruReward := bytesToTB(capacity.SRU) * SsdRewardPerTB | ||
| hruReward := bytesToTB(capacity.HRU) * HddRewardPerTB | ||
|
|
||
| return mruReward + sruReward + hruReward | ||
| } | ||
|
|
||
| // calculateTotalReward calculates the total reward based on node capacity and uptime percentage. | ||
| // It first calculates the base capacity reward and then applies the uptime percentage. | ||
| func calculateTotalReward(capacity db.Resources, upTimePercentage float64) float64 { | ||
| baseReward := calculateBaseCapacityReward(capacity) | ||
| return baseReward * (upTimePercentage / 100) | ||
| } |
There was a problem hiding this comment.
I don't think we need two functions for this, the logic of calculateBaseCapacityReward can be moved to calculate totalReward instead
| FirstPeriodStartTimestamp int64 = 1522501000 | ||
|
|
||
| // Uptime events are supposed to happen every 40 minutes. | ||
| // Here we set this to one hour (3600 sec) to allow some room. | ||
| UptimeEventsInterval = 3600 | ||
|
|
||
| // The duration of a standard period, as used by the minting payouts, in seconds. | ||
| // Calculated as: 24 hours * 60 minutes * 60 seconds * (365*3 + 366*2) / 60 periods | ||
| StandardPeriodDuration int64 = 24 * 60 * 60 * (365*3 + 366*2) / 60 |
There was a problem hiding this comment.
are we using those consts outside the pkg? if no we should not export them
| periodStart := referenceTime.Unix() - periodOffset | ||
| return time.Unix(periodStart, 0) |
There was a problem hiding this comment.
you can use referenceTime.Add(-time.Duration(periodOffset)) instead
Description
This PR introduces a new API endpoint to calculate real-time node rewards based on node resources and uptime reports.
Please note that the network usage is not included
And please consider those concerns, comment
Changes
New Endpoint:
GET /nodes/{node_id}/rewards
Returns: Rewards
New Handler:
getNodeRewardsHandler – handles input validation and response logic.
New Reward Logic:
Added a pkg/server/rewards.go file with the logic to:
- Get uptime reports for the current month
- Calculate uptime percentage
- Apply reward formula
- Return reward values (or zeroes if uptime is too low)
Swagger Update:
API documentation updated with the new endpoint and response schema.
Tests
Add unit tests, create a fake node, and submit some reports

Related Issues
Checklist