storagenode: heldamount renamed to payouts, renamed some methods and structs to more meaningful names. grouped estimated payout with pathouts

satellite: heldamount renamed to SNOpayouts.

Change-Id: I244b4d2454e0621f4b8e22d3c0d3e602c0bbcb02
This commit is contained in:
Qweder93 2020-09-10 17:08:25 +03:00 committed by Nikolai Siedov
parent 3bbf08917c
commit 8182fdad0b
30 changed files with 640 additions and 648 deletions

View File

@ -36,7 +36,6 @@ import (
"storj.io/storj/satellite/console/consoleweb"
"storj.io/storj/satellite/contact"
"storj.io/storj/satellite/gracefulexit"
"storj.io/storj/satellite/heldamount"
"storj.io/storj/satellite/inspector"
"storj.io/storj/satellite/mailservice"
"storj.io/storj/satellite/mailservice/simulate"
@ -51,6 +50,7 @@ import (
"storj.io/storj/satellite/referrals"
"storj.io/storj/satellite/repair/irreparable"
"storj.io/storj/satellite/rewards"
"storj.io/storj/satellite/snopayout"
)
// API is the satellite API process
@ -150,10 +150,10 @@ type API struct {
Endpoint *nodestats.Endpoint
}
HeldAmount struct {
Endpoint *heldamount.Endpoint
Service *heldamount.Service
DB heldamount.DB
SnoPayout struct {
Endpoint *snopayout.Endpoint
Service *snopayout.Service
DB snopayout.DB
}
GracefulExit struct {
@ -630,17 +630,17 @@ func NewAPI(log *zap.Logger, full *identity.FullIdentity, db DB,
}
}
{ // setup heldamount endpoint
peer.HeldAmount.DB = peer.DB.HeldAmount()
peer.HeldAmount.Service = heldamount.NewService(
peer.Log.Named("heldamount:service"),
peer.HeldAmount.DB)
peer.HeldAmount.Endpoint = heldamount.NewEndpoint(
peer.Log.Named("heldamount:endpoint"),
{ // setup SnoPayout endpoint
peer.SnoPayout.DB = peer.DB.SnoPayout()
peer.SnoPayout.Service = snopayout.NewService(
peer.Log.Named("payout:service"),
peer.SnoPayout.DB)
peer.SnoPayout.Endpoint = snopayout.NewEndpoint(
peer.Log.Named("payout:endpoint"),
peer.DB.StoragenodeAccounting(),
peer.Overlay.DB,
peer.HeldAmount.Service)
if err := pb.DRPCRegisterHeldAmount(peer.Server.DRPC(), peer.HeldAmount.Endpoint); err != nil {
peer.SnoPayout.Service)
if err := pb.DRPCRegisterHeldAmount(peer.Server.DRPC(), peer.SnoPayout.Endpoint); err != nil {
return nil, errs.Combine(err, peer.Close())
}
}

View File

@ -30,7 +30,6 @@ import (
"storj.io/storj/satellite/downtime"
"storj.io/storj/satellite/gc"
"storj.io/storj/satellite/gracefulexit"
"storj.io/storj/satellite/heldamount"
"storj.io/storj/satellite/mailservice"
"storj.io/storj/satellite/marketingweb"
"storj.io/storj/satellite/metainfo"
@ -48,6 +47,7 @@ import (
"storj.io/storj/satellite/repair/repairer"
"storj.io/storj/satellite/revocation"
"storj.io/storj/satellite/rewards"
"storj.io/storj/satellite/snopayout"
)
var mon = monkit.Package()
@ -100,8 +100,8 @@ type DB interface {
StripeCoinPayments() stripecoinpayments.DB
// DowntimeTracking returns database for downtime tracking
DowntimeTracking() downtime.DB
// Heldamount returns database for heldamount.
HeldAmount() heldamount.DB
// SnoPayout returns database for payout.
SnoPayout() snopayout.DB
// Compoensation tracks storage node compensation
Compensation() compensation.DB
// Revocation tracks revoked macaroons

View File

@ -20,7 +20,6 @@ import (
"storj.io/storj/satellite/console"
"storj.io/storj/satellite/downtime"
"storj.io/storj/satellite/gracefulexit"
"storj.io/storj/satellite/heldamount"
"storj.io/storj/satellite/nodeapiversion"
"storj.io/storj/satellite/orders"
"storj.io/storj/satellite/overlay"
@ -30,6 +29,7 @@ import (
"storj.io/storj/satellite/revocation"
"storj.io/storj/satellite/rewards"
"storj.io/storj/satellite/satellitedb/dbx"
"storj.io/storj/satellite/snopayout"
)
var (
@ -197,8 +197,8 @@ func (db *satelliteDB) DowntimeTracking() downtime.DB {
return &downtimeTrackingDB{db: db}
}
// HeldAmount returns database for storagenode payStubs and payments info.
func (db *satelliteDB) HeldAmount() heldamount.DB {
// SnoPayout returns database for storagenode payStubs and payments info.
func (db *satelliteDB) SnoPayout() snopayout.DB {
return &paymentStubs{db: db}
}

View File

@ -11,8 +11,8 @@ import (
"github.com/zeebo/errs"
"storj.io/common/storj"
"storj.io/storj/satellite/heldamount"
"storj.io/storj/satellite/satellitedb/dbx"
"storj.io/storj/satellite/snopayout"
)
// paymentStubs is payment data for specific storagenode for some specific period by working with satellite.
@ -23,7 +23,7 @@ type paymentStubs struct {
}
// GetPaystub returns payStub by nodeID and period.
func (paystubs *paymentStubs) GetPaystub(ctx context.Context, nodeID storj.NodeID, period string) (payStub heldamount.PayStub, err error) {
func (paystubs *paymentStubs) GetPaystub(ctx context.Context, nodeID storj.NodeID, period string) (payStub snopayout.PayStub, err error) {
query := `SELECT * FROM storagenode_paystubs WHERE node_id = $1 AND period = $2;`
row := paystubs.db.QueryRowContext(ctx, query, nodeID, period)
@ -52,22 +52,22 @@ func (paystubs *paymentStubs) GetPaystub(ctx context.Context, nodeID storj.NodeI
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return heldamount.PayStub{}, heldamount.ErrNoDataForPeriod.Wrap(err)
return snopayout.PayStub{}, snopayout.ErrNoDataForPeriod.Wrap(err)
}
return heldamount.PayStub{}, Error.Wrap(err)
return snopayout.PayStub{}, Error.Wrap(err)
}
return payStub, nil
}
// GetAllPaystubs return all payStubs by nodeID.
func (paystubs *paymentStubs) GetAllPaystubs(ctx context.Context, nodeID storj.NodeID) (payStubs []heldamount.PayStub, err error) {
func (paystubs *paymentStubs) GetAllPaystubs(ctx context.Context, nodeID storj.NodeID) (payStubs []snopayout.PayStub, err error) {
query := `SELECT * FROM storagenode_paystubs WHERE node_id = $1;`
rows, err := paystubs.db.QueryContext(ctx, query, nodeID)
if err != nil {
return []heldamount.PayStub{}, Error.Wrap(err)
return []snopayout.PayStub{}, Error.Wrap(err)
}
defer func() {
@ -75,7 +75,7 @@ func (paystubs *paymentStubs) GetAllPaystubs(ctx context.Context, nodeID storj.N
}()
for rows.Next() {
paystub := heldamount.PayStub{}
paystub := snopayout.PayStub{}
err = rows.Scan(
&paystub.Period,
@ -101,7 +101,7 @@ func (paystubs *paymentStubs) GetAllPaystubs(ctx context.Context, nodeID storj.N
&paystub.Paid,
)
if err = rows.Err(); err != nil {
return []heldamount.PayStub{}, Error.Wrap(err)
return []snopayout.PayStub{}, Error.Wrap(err)
}
payStubs = append(payStubs, paystub)
@ -111,7 +111,7 @@ func (paystubs *paymentStubs) GetAllPaystubs(ctx context.Context, nodeID storj.N
}
// CreatePaystub inserts storagenode_paystub into database.
func (paystubs *paymentStubs) CreatePaystub(ctx context.Context, stub heldamount.PayStub) (err error) {
func (paystubs *paymentStubs) CreatePaystub(ctx context.Context, stub snopayout.PayStub) (err error) {
return paystubs.db.CreateNoReturn_StoragenodePaystub(
ctx,
dbx.StoragenodePaystub_Period(stub.Period),
@ -138,7 +138,7 @@ func (paystubs *paymentStubs) CreatePaystub(ctx context.Context, stub heldamount
}
// GetPayment returns payment by nodeID and period.
func (paystubs *paymentStubs) GetPayment(ctx context.Context, nodeID storj.NodeID, period string) (payment heldamount.StoragenodePayment, err error) {
func (paystubs *paymentStubs) GetPayment(ctx context.Context, nodeID storj.NodeID, period string) (payment snopayout.StoragenodePayment, err error) {
query := `SELECT * FROM storagenode_payments WHERE node_id = $1 AND period = $2;`
row := paystubs.db.QueryRowContext(ctx, query, nodeID, period)
@ -153,17 +153,17 @@ func (paystubs *paymentStubs) GetPayment(ctx context.Context, nodeID storj.NodeI
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return heldamount.StoragenodePayment{}, heldamount.ErrNoDataForPeriod.Wrap(err)
return snopayout.StoragenodePayment{}, snopayout.ErrNoDataForPeriod.Wrap(err)
}
return heldamount.StoragenodePayment{}, Error.Wrap(err)
return snopayout.StoragenodePayment{}, Error.Wrap(err)
}
return payment, nil
}
// CreatePayment inserts storagenode_payment into database.
func (paystubs *paymentStubs) CreatePayment(ctx context.Context, payment heldamount.StoragenodePayment) (err error) {
func (paystubs *paymentStubs) CreatePayment(ctx context.Context, payment snopayout.StoragenodePayment) (err error) {
return paystubs.db.CreateNoReturn_StoragenodePayment(
ctx,
dbx.StoragenodePayment_NodeId(payment.NodeID[:]),
@ -177,7 +177,7 @@ func (paystubs *paymentStubs) CreatePayment(ctx context.Context, payment heldamo
}
// GetAllPayments return all payments by nodeID.
func (paystubs *paymentStubs) GetAllPayments(ctx context.Context, nodeID storj.NodeID) (payments []heldamount.StoragenodePayment, err error) {
func (paystubs *paymentStubs) GetAllPayments(ctx context.Context, nodeID storj.NodeID) (payments []snopayout.StoragenodePayment, err error) {
query := `SELECT * FROM storagenode_payments WHERE node_id = $1;`
rows, err := paystubs.db.QueryContext(ctx, query, nodeID)
@ -190,7 +190,7 @@ func (paystubs *paymentStubs) GetAllPayments(ctx context.Context, nodeID storj.N
}()
for rows.Next() {
payment := heldamount.StoragenodePayment{}
payment := snopayout.StoragenodePayment{}
err = rows.Scan(
&payment.ID,

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount
package snopayout
import (
"context"

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount
package snopayout
import (
"context"
@ -13,7 +13,7 @@ import (
"storj.io/common/storj"
)
// DB exposes all needed functionality to manage heldAmount.
// DB exposes all needed functionality to manage payout.
//
// architecture: Service
type DB interface {
@ -31,11 +31,11 @@ type DB interface {
GetAllPayments(ctx context.Context, nodeID storj.NodeID) ([]StoragenodePayment, error)
}
// ErrNoDataForPeriod represents errors from the heldamount database.
// ErrNoDataForPeriod represents errors from the payout database.
var ErrNoDataForPeriod = errs.Class("no payStub/payments for period error")
// Error is the default error class for heldamount package.
var Error = errs.Class("heldamount")
// Error is the default error class for payout package.
var Error = errs.Class("payout db error")
// PayStub is an entity that holds held amount of cash that will be paid to storagenode operator after some period.
type PayStub struct {

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount_test
package snopayout_test
import (
"testing"
@ -11,17 +11,18 @@ import (
"storj.io/common/storj"
"storj.io/common/testcontext"
"storj.io/common/testrand"
"storj.io/storj/satellite"
"storj.io/storj/satellite/heldamount"
"storj.io/storj/satellite/satellitedb/satellitedbtest"
"storj.io/storj/satellite/snopayout"
)
func TestHeldAmountDB(t *testing.T) {
func TestPayoutDB(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
heldAmount := db.HeldAmount()
snoPayout := db.SnoPayout()
NodeID := storj.NodeID{}
period := "2020-01"
paystub := heldamount.PayStub{
paystub := snopayout.PayStub{
Period: "2020-01",
NodeID: NodeID,
Created: time.Now().UTC(),
@ -45,7 +46,7 @@ func TestHeldAmountDB(t *testing.T) {
Paid: 17,
}
paystub2 := heldamount.PayStub{
paystub2 := snopayout.PayStub{
Period: "2020-02",
NodeID: NodeID,
Created: time.Now().UTC(),
@ -69,7 +70,7 @@ func TestHeldAmountDB(t *testing.T) {
Paid: 20,
}
paystub3 := heldamount.PayStub{
paystub3 := snopayout.PayStub{
Period: "2020-03",
NodeID: NodeID,
Created: time.Now().UTC(),
@ -94,16 +95,16 @@ func TestHeldAmountDB(t *testing.T) {
}
t.Run("Test StorePayStub", func(t *testing.T) {
err := heldAmount.CreatePaystub(ctx, paystub)
err := snoPayout.CreatePaystub(ctx, paystub)
assert.NoError(t, err)
err = heldAmount.CreatePaystub(ctx, paystub2)
err = snoPayout.CreatePaystub(ctx, paystub2)
assert.NoError(t, err)
err = heldAmount.CreatePaystub(ctx, paystub3)
err = snoPayout.CreatePaystub(ctx, paystub3)
assert.NoError(t, err)
})
t.Run("Test GetPayStub", func(t *testing.T) {
stub, err := heldAmount.GetPaystub(ctx, NodeID, period)
stub, err := snoPayout.GetPaystub(ctx, NodeID, period)
assert.NoError(t, err)
assert.Equal(t, stub.Period, paystub.Period)
assert.Equal(t, stub.Codes, paystub.Codes)
@ -126,15 +127,15 @@ func TestHeldAmountDB(t *testing.T) {
assert.Equal(t, stub.UsagePut, paystub.UsagePut)
assert.Equal(t, stub.UsagePutRepair, paystub.UsagePutRepair)
stub, err = heldAmount.GetPaystub(ctx, NodeID, "")
stub, err = snoPayout.GetPaystub(ctx, NodeID, "")
assert.Error(t, err)
stub, err = heldAmount.GetPaystub(ctx, storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, period)
stub, err = snoPayout.GetPaystub(ctx, storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, period)
assert.Error(t, err)
})
t.Run("Test GetAllPaystubs", func(t *testing.T) {
stubs, err := heldAmount.GetAllPaystubs(ctx, NodeID)
stubs, err := snoPayout.GetAllPaystubs(ctx, NodeID)
assert.NoError(t, err)
for i := 0; i < len(stubs); i++ {
if stubs[i].Period == "2020-01" {
@ -206,7 +207,7 @@ func TestHeldAmountDB(t *testing.T) {
}
})
payment := heldamount.StoragenodePayment{
payment := snopayout.StoragenodePayment{
ID: 1,
Created: time.Now().UTC(),
NodeID: NodeID,
@ -217,12 +218,12 @@ func TestHeldAmountDB(t *testing.T) {
}
t.Run("Test StorePayment", func(t *testing.T) {
err := heldAmount.CreatePayment(ctx, payment)
err := snoPayout.CreatePayment(ctx, payment)
assert.NoError(t, err)
})
t.Run("Test GetPayment", func(t *testing.T) {
paym, err := heldAmount.GetPayment(ctx, NodeID, period)
paym, err := snoPayout.GetPayment(ctx, NodeID, period)
assert.NoError(t, err)
assert.Equal(t, paym.NodeID, payment.NodeID)
assert.Equal(t, paym.Period, payment.Period)
@ -230,10 +231,10 @@ func TestHeldAmountDB(t *testing.T) {
assert.Equal(t, paym.Notes, payment.Notes)
assert.Equal(t, paym.Receipt, payment.Receipt)
paym, err = heldAmount.GetPayment(ctx, NodeID, "")
paym, err = snoPayout.GetPayment(ctx, NodeID, "")
assert.Error(t, err)
paym, err = heldAmount.GetPayment(ctx, storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, period)
paym, err = snoPayout.GetPayment(ctx, testrand.NodeID(), period)
assert.Error(t, err)
})
})

View File

@ -1,262 +0,0 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package consoleapi
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/zeebo/errs"
"go.uber.org/zap"
"storj.io/common/storj"
"storj.io/storj/storagenode/heldamount"
)
// ErrHeldAmountAPI - console heldAmount api error type.
var ErrHeldAmountAPI = errs.Class("heldAmount console web error")
// HeldAmount is an api controller that exposes all held amount related api.
type HeldAmount struct {
service *heldamount.Service
log *zap.Logger
}
// NewHeldAmount is a constructor for heldAmount controller.
func NewHeldAmount(log *zap.Logger, service *heldamount.Service) *HeldAmount {
return &HeldAmount{
log: log,
service: service,
}
}
// PayStubMonthly returns heldamount, storage holding and prices data for specific month from all satellites or specified satellite by query parameter id.
func (heldAmount *HeldAmount) PayStubMonthly(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
segmentParams := mux.Vars(r)
queryParams := r.URL.Query()
period, ok := segmentParams["period"]
if !ok {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
id := queryParams.Get("id")
if id == "" {
payStubs, err := heldAmount.service.AllPayStubsMonthly(ctx, period)
if err != nil {
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
} else {
satelliteID, err := storj.NodeIDFromString(id)
if err != nil {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrHeldAmountAPI.Wrap(err))
return
}
payStub, err := heldAmount.service.SatellitePayStubMonthly(ctx, satelliteID, period)
if err != nil {
if heldamount.ErrNoPayStubForPeriod.Has(err) {
heldAmount.serveJSONError(w, http.StatusNotFound, ErrHeldAmountAPI.Wrap(err))
return
}
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode([]*heldamount.PayStub{payStub}); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
}
}
// PayStubPeriod retrieves held amount for selected range of months from storagenode database for all satellites or specified satellite by query parameter id.
func (heldAmount *HeldAmount) PayStubPeriod(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
segmentParams := mux.Vars(r)
queryParams := r.URL.Query()
start, ok := segmentParams["start"]
if !ok {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
end, ok := segmentParams["end"]
if !ok {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
id := queryParams.Get("id")
if id == "" {
payStubs, err := heldAmount.service.AllPayStubsPeriod(ctx, start, end)
if err != nil {
if heldamount.ErrBadPeriod.Has(err) {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrHeldAmountAPI.Wrap(err))
return
}
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
} else {
satelliteID, err := storj.NodeIDFromString(id)
if err != nil {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrHeldAmountAPI.Wrap(err))
return
}
payStubs, err := heldAmount.service.SatellitePayStubPeriod(ctx, satelliteID, start, end)
if err != nil {
if heldamount.ErrBadPeriod.Has(err) {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrHeldAmountAPI.Wrap(err))
return
}
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
}
}
// HeldHistory returns held amount for each % period for all satellites.
func (heldAmount *HeldAmount) HeldHistory(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
heldbackHistory, err := heldAmount.service.AllHeldbackHistory(ctx)
if err != nil {
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(heldbackHistory); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
}
// PayoutHistory retrieves paystubs for specific period from all satellites and transaction receipts if exists.
func (heldAmount *HeldAmount) PayoutHistory(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
segmentParams := mux.Vars(r)
period, ok := segmentParams["period"]
if !ok {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
payoutHistory, err := heldAmount.service.PayoutHistoryMonthly(ctx, period)
if err != nil {
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payoutHistory); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
}
// HeldAmountPeriods retrieves all periods in which we have some heldamount data.
// Have optional parameter - satelliteID.
// If satelliteID specified - will retrieve periods only for concrete satellite.
func (heldAmount *HeldAmount) HeldAmountPeriods(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
queryParams := r.URL.Query()
id := queryParams.Get("id")
if id == "" {
payStubs, err := heldAmount.service.AllPeriods(ctx)
if err != nil {
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
} else {
satelliteID, err := storj.NodeIDFromString(id)
if err != nil {
heldAmount.serveJSONError(w, http.StatusBadRequest, ErrHeldAmountAPI.Wrap(err))
return
}
payStubs, err := heldAmount.service.SatellitePeriods(ctx, satelliteID)
if err != nil {
heldAmount.serveJSONError(w, http.StatusInternalServerError, ErrHeldAmountAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
heldAmount.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
}
}
// serveJSONError writes JSON error to response output stream.
func (heldAmount *HeldAmount) serveJSONError(w http.ResponseWriter, status int, err error) {
w.WriteHeader(status)
var response struct {
Error string `json:"error"`
}
response.Error = err.Error()
err = json.NewEncoder(w).Encode(response)
if err != nil {
heldAmount.log.Error("failed to write json error response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
return
}
}

View File

@ -0,0 +1,262 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package consoleapi
import (
"encoding/json"
"net/http"
"github.com/gorilla/mux"
"github.com/zeebo/errs"
"go.uber.org/zap"
"storj.io/common/storj"
"storj.io/storj/storagenode/payout"
)
// ErrPayoutAPI - console payout api error type.
var ErrPayoutAPI = errs.Class("payout console web error")
// Payout is an api controller that exposes all payout related api.
type Payout struct {
service *payout.Service
log *zap.Logger
}
// NewPayout is a constructor for payout controller.
func NewPayout(log *zap.Logger, service *payout.Service) *Payout {
return &Payout{
log: log,
service: service,
}
}
// PayStubMonthly returns payout, storage holding and prices data for specific month from all satellites or specified satellite by query parameter id.
func (payouts *Payout) PayStubMonthly(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
segmentParams := mux.Vars(r)
queryParams := r.URL.Query()
period, ok := segmentParams["period"]
if !ok {
payouts.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
id := queryParams.Get("id")
if id == "" {
payStubs, err := payouts.service.AllPayStubsMonthly(ctx, period)
if err != nil {
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
} else {
satelliteID, err := storj.NodeIDFromString(id)
if err != nil {
payouts.serveJSONError(w, http.StatusBadRequest, ErrPayoutAPI.Wrap(err))
return
}
payStub, err := payouts.service.SatellitePayStubMonthly(ctx, satelliteID, period)
if err != nil {
if payout.ErrNoPayStubForPeriod.Has(err) {
payouts.serveJSONError(w, http.StatusNotFound, ErrPayoutAPI.Wrap(err))
return
}
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode([]*payout.PayStub{payStub}); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
}
}
// PayStubPeriod retrieves paystubs for selected range of months from storagenode database for all satellites or specified satellite by query parameter id.
func (payouts *Payout) PayStubPeriod(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
segmentParams := mux.Vars(r)
queryParams := r.URL.Query()
start, ok := segmentParams["start"]
if !ok {
payouts.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
end, ok := segmentParams["end"]
if !ok {
payouts.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
id := queryParams.Get("id")
if id == "" {
payStubs, err := payouts.service.AllPayStubsPeriod(ctx, start, end)
if err != nil {
if payout.ErrBadPeriod.Has(err) {
payouts.serveJSONError(w, http.StatusBadRequest, ErrPayoutAPI.Wrap(err))
return
}
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
} else {
satelliteID, err := storj.NodeIDFromString(id)
if err != nil {
payouts.serveJSONError(w, http.StatusBadRequest, ErrPayoutAPI.Wrap(err))
return
}
payStubs, err := payouts.service.SatellitePayStubPeriod(ctx, satelliteID, start, end)
if err != nil {
if payout.ErrBadPeriod.Has(err) {
payouts.serveJSONError(w, http.StatusBadRequest, ErrPayoutAPI.Wrap(err))
return
}
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
}
}
// HeldHistory returns held amount for each % period for all satellites.
func (payouts *Payout) HeldHistory(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
heldbackHistory, err := payouts.service.AllHeldbackHistory(ctx)
if err != nil {
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(heldbackHistory); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
}
// PayoutHistory retrieves paystubs for specific period from all satellites and transaction receipts if exists.
func (payouts *Payout) PayoutHistory(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
segmentParams := mux.Vars(r)
period, ok := segmentParams["period"]
if !ok {
payouts.serveJSONError(w, http.StatusBadRequest, ErrNotificationsAPI.Wrap(err))
return
}
payoutHistory, err := payouts.service.AllSatellitesPayoutPeriod(ctx, period)
if err != nil {
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payoutHistory); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
}
// HeldAmountPeriods retrieves all periods in which we have some payout data.
// Have optional parameter - satelliteID.
// If satelliteID specified - will retrieve periods only for concrete satellite.
func (payouts *Payout) HeldAmountPeriods(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set(contentType, applicationJSON)
queryParams := r.URL.Query()
id := queryParams.Get("id")
if id == "" {
payStubs, err := payouts.service.AllPeriods(ctx)
if err != nil {
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
} else {
satelliteID, err := storj.NodeIDFromString(id)
if err != nil {
payouts.serveJSONError(w, http.StatusBadRequest, ErrPayoutAPI.Wrap(err))
return
}
payStubs, err := payouts.service.SatellitePeriods(ctx, satelliteID)
if err != nil {
payouts.serveJSONError(w, http.StatusInternalServerError, ErrPayoutAPI.Wrap(err))
return
}
if err := json.NewEncoder(w).Encode(payStubs); err != nil {
payouts.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
}
}
// serveJSONError writes JSON error to response output stream.
func (payouts *Payout) serveJSONError(w http.ResponseWriter, status int, err error) {
w.WriteHeader(status)
var response struct {
Error string `json:"error"`
}
response.Error = err.Error()
err = json.NewEncoder(w).Encode(response)
if err != nil {
payouts.log.Error("failed to write json error response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
}

View File

@ -16,9 +16,8 @@ import (
"storj.io/common/storj"
"storj.io/common/testcontext"
date2 "storj.io/storj/private/date"
"storj.io/storj/private/testplanet"
"storj.io/storj/storagenode/heldamount"
"storj.io/storj/storagenode/payout"
"storj.io/storj/storagenode/reputation"
)
@ -32,12 +31,12 @@ func TestHeldAmountApi(t *testing.T) {
satellite := planet.Satellites[0]
sno := planet.StorageNodes[0]
console := sno.Console
heldAmountDB := sno.DB.HeldAmount()
payoutsDB := sno.DB.Payout()
reputationDB := sno.DB.Reputation()
baseURL := fmt.Sprintf("http://%s/api/heldamount", console.Listener.Addr())
period := "2020-03"
paystub := heldamount.PayStub{
paystub := payout.PayStub{
SatelliteID: satellite.ID(),
Period: period,
Created: time.Now().UTC(),
@ -60,7 +59,7 @@ func TestHeldAmountApi(t *testing.T) {
Disposed: 16,
Paid: 17,
}
err := heldAmountDB.StorePayStub(ctx, paystub)
err := payoutsDB.StorePayStub(ctx, paystub)
require.NoError(t, err)
t.Run("test SatellitePayStubMonthly", func(t *testing.T) {
@ -73,7 +72,7 @@ func TestHeldAmountApi(t *testing.T) {
paystub.UsageAtRest /= 720
expected, err := json.Marshal([]heldamount.PayStub{paystub})
expected, err := json.Marshal([]payout.PayStub{paystub})
require.NoError(t, err)
defer func() {
@ -99,7 +98,7 @@ func TestHeldAmountApi(t *testing.T) {
body2, err := ioutil.ReadAll(res2.Body)
require.NoError(t, err)
expected = []byte("{\"error\":\"heldAmount console web error: heldamount service error: no payStub for period error: sql: no rows in result set\"}\n")
expected = []byte("{\"error\":\"payout console web error: payout service error: no payStub for period error: sql: no rows in result set\"}\n")
require.Equal(t, expected, body2)
// should return 400 cause of wrong satellite id.
@ -115,7 +114,7 @@ func TestHeldAmountApi(t *testing.T) {
}()
})
paystub2 := heldamount.PayStub{
paystub2 := payout.PayStub{
SatelliteID: storj.NodeID{1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 4, 1, 2, 3, 0},
Period: period,
Created: time.Now().UTC(),
@ -138,7 +137,7 @@ func TestHeldAmountApi(t *testing.T) {
Disposed: 16,
Paid: 17,
}
err = heldAmountDB.StorePayStub(ctx, paystub2)
err = payoutsDB.StorePayStub(ctx, paystub2)
require.NoError(t, err)
t.Run("test AllPayStubsMonthly", func(t *testing.T) {
@ -151,7 +150,7 @@ func TestHeldAmountApi(t *testing.T) {
paystub2.UsageAtRest /= 720
expected, err := json.Marshal([]heldamount.PayStub{paystub2, paystub})
expected, err := json.Marshal([]payout.PayStub{paystub2, paystub})
require.NoError(t, err)
defer func() {
@ -181,7 +180,7 @@ func TestHeldAmountApi(t *testing.T) {
})
period2 := "2020-02"
paystub3 := heldamount.PayStub{
paystub3 := payout.PayStub{
SatelliteID: satellite.ID(),
Period: period2,
Created: time.Now().UTC(),
@ -204,7 +203,7 @@ func TestHeldAmountApi(t *testing.T) {
Disposed: 16,
Paid: 17,
}
err = heldAmountDB.StorePayStub(ctx, paystub3)
err = payoutsDB.StorePayStub(ctx, paystub3)
require.NoError(t, err)
t.Run("test SatellitePayStubPeriod", func(t *testing.T) {
@ -217,7 +216,7 @@ func TestHeldAmountApi(t *testing.T) {
paystub3.UsageAtRest /= 720
expected, err := json.Marshal([]heldamount.PayStub{paystub3, paystub})
expected, err := json.Marshal([]payout.PayStub{paystub3, paystub})
require.NoError(t, err)
defer func() {
@ -235,7 +234,7 @@ func TestHeldAmountApi(t *testing.T) {
require.NotNil(t, res2)
require.Equal(t, http.StatusOK, res2.StatusCode)
expected, err = json.Marshal([]heldamount.PayStub{paystub})
expected, err = json.Marshal([]payout.PayStub{paystub})
require.NoError(t, err)
defer func() {
@ -253,7 +252,7 @@ func TestHeldAmountApi(t *testing.T) {
require.NotNil(t, res3)
require.Equal(t, http.StatusOK, res3.StatusCode)
expected, err = json.Marshal([]heldamount.PayStub{paystub2})
expected, err = json.Marshal([]payout.PayStub{paystub2})
require.NoError(t, err)
defer func() {
@ -292,7 +291,7 @@ func TestHeldAmountApi(t *testing.T) {
body5, err := ioutil.ReadAll(res5.Body)
require.NoError(t, err)
require.Equal(t, "{\"error\":\"heldAmount console web error: wrong period format: period has wrong format\"}\n", string(body5))
require.Equal(t, "{\"error\":\"payout console web error: wrong period format: period has wrong format\"}\n", string(body5))
})
t.Run("test AllPayStubsPeriod", func(t *testing.T) {
@ -303,7 +302,7 @@ func TestHeldAmountApi(t *testing.T) {
require.NotNil(t, res)
require.Equal(t, http.StatusOK, res.StatusCode)
expected, err := json.Marshal([]heldamount.PayStub{paystub3, paystub2, paystub})
expected, err := json.Marshal([]payout.PayStub{paystub3, paystub2, paystub})
require.NoError(t, err)
defer func() {
@ -321,7 +320,7 @@ func TestHeldAmountApi(t *testing.T) {
require.NotNil(t, res2)
require.Equal(t, http.StatusOK, res2.StatusCode)
expected, err = json.Marshal([]heldamount.PayStub{paystub2, paystub})
expected, err = json.Marshal([]payout.PayStub{paystub2, paystub})
require.NoError(t, err)
defer func() {
@ -348,7 +347,7 @@ func TestHeldAmountApi(t *testing.T) {
body5, err := ioutil.ReadAll(res5.Body)
require.NoError(t, err)
require.Equal(t, "{\"error\":\"heldAmount console web error: wrong period format: period has wrong format\"}\n", string(body5))
require.Equal(t, "{\"error\":\"payout console web error: wrong period format: period has wrong format\"}\n", string(body5))
})
t.Run("test HeldbackHistory", func(t *testing.T) {
@ -366,21 +365,18 @@ func TestHeldAmountApi(t *testing.T) {
require.NotNil(t, res)
require.Equal(t, http.StatusOK, res.StatusCode)
age := date2.MonthsCountSince(date)
held := heldamount.HeldHistory{
SatelliteID: satellite.ID(),
SatelliteName: satellite.Addr(),
Age: int64(age),
FirstPeriod: 28,
SecondPeriod: 0,
ThirdPeriod: 0,
TotalHeld: 28,
TotalDisposed: 32,
JoinedAt: date,
held := payout.SatelliteHeldHistory{
SatelliteID: satellite.ID(),
SatelliteName: satellite.Addr(),
HoldForFirstPeriod: 28,
HoldForSecondPeriod: 0,
HoldForThirdPeriod: 0,
TotalHeld: 28,
TotalDisposed: 32,
JoinedAt: date,
}
var periods []heldamount.HeldHistory
var periods []payout.SatelliteHeldHistory
periods = append(periods, held)
expected, err := json.Marshal(periods)

View File

@ -129,13 +129,13 @@ func (dashboard *StorageNode) EstimatedPayout(w http.ResponseWriter, r *http.Req
}
if err := json.NewEncoder(w).Encode(data); err != nil {
dashboard.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
dashboard.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
} else {
satelliteID, err := storj.NodeIDFromString(id)
if err != nil {
dashboard.serveJSONError(w, http.StatusBadRequest, ErrHeldAmountAPI.Wrap(err))
dashboard.serveJSONError(w, http.StatusBadRequest, ErrPayoutAPI.Wrap(err))
return
}
@ -146,7 +146,7 @@ func (dashboard *StorageNode) EstimatedPayout(w http.ResponseWriter, r *http.Req
}
if err := json.NewEncoder(w).Encode(data); err != nil {
dashboard.log.Error("failed to encode json response", zap.Error(ErrHeldAmountAPI.Wrap(err)))
dashboard.log.Error("failed to encode json response", zap.Error(ErrPayoutAPI.Wrap(err)))
return
}
}

View File

@ -19,7 +19,7 @@ import (
"storj.io/common/testcontext"
"storj.io/storj/private/testplanet"
"storj.io/storj/satellite"
"storj.io/storj/storagenode/estimatedpayout"
"storj.io/storj/storagenode/payout/estimatedpayout"
"storj.io/storj/storagenode/pricing"
"storj.io/storj/storagenode/reputation"
"storj.io/storj/storagenode/storageusage"

View File

@ -19,8 +19,8 @@ import (
"storj.io/common/errs2"
"storj.io/storj/storagenode/console"
"storj.io/storj/storagenode/console/consoleapi"
"storj.io/storj/storagenode/heldamount"
"storj.io/storj/storagenode/notifications"
"storj.io/storj/storagenode/payout"
)
var (
@ -43,20 +43,20 @@ type Server struct {
service *console.Service
notifications *notifications.Service
heldAmount *heldamount.Service
payout *payout.Service
listener net.Listener
server http.Server
}
// NewServer creates new instance of storagenode console web server.
func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifications.Service, service *console.Service, heldAmount *heldamount.Service, listener net.Listener) *Server {
func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifications.Service, service *console.Service, payout *payout.Service, listener net.Listener) *Server {
server := Server{
log: logger,
service: service,
listener: listener,
notifications: notifications,
heldAmount: heldAmount,
payout: payout,
}
router := mux.NewRouter()
@ -77,14 +77,14 @@ func NewServer(logger *zap.Logger, assets http.FileSystem, notifications *notifi
notificationRouter.HandleFunc("/{id}/read", notificationController.ReadNotification).Methods(http.MethodPost)
notificationRouter.HandleFunc("/readall", notificationController.ReadAllNotifications).Methods(http.MethodPost)
heldAmountController := consoleapi.NewHeldAmount(server.log, server.heldAmount)
heldAmountRouter := router.PathPrefix("/api/heldamount").Subrouter()
heldAmountRouter.StrictSlash(true)
heldAmountRouter.HandleFunc("/paystubs/{period}", heldAmountController.PayStubMonthly).Methods(http.MethodGet)
heldAmountRouter.HandleFunc("/paystubs/{start}/{end}", heldAmountController.PayStubPeriod).Methods(http.MethodGet)
heldAmountRouter.HandleFunc("/held-history", heldAmountController.HeldHistory).Methods(http.MethodGet)
heldAmountRouter.HandleFunc("/periods", heldAmountController.HeldAmountPeriods).Methods(http.MethodGet)
heldAmountRouter.HandleFunc("/payout-history/{period}", heldAmountController.PayoutHistory).Methods(http.MethodGet)
payoutController := consoleapi.NewPayout(server.log, server.payout)
payoutRouter := router.PathPrefix("/api/heldamount").Subrouter()
payoutRouter.StrictSlash(true)
payoutRouter.HandleFunc("/paystubs/{period}", payoutController.PayStubMonthly).Methods(http.MethodGet)
payoutRouter.HandleFunc("/paystubs/{start}/{end}", payoutController.PayStubPeriod).Methods(http.MethodGet)
payoutRouter.HandleFunc("/held-history", payoutController.HeldHistory).Methods(http.MethodGet)
payoutRouter.HandleFunc("/periods", payoutController.HeldAmountPeriods).Methods(http.MethodGet)
payoutRouter.HandleFunc("/payout-history/{period}", payoutController.PayoutHistory).Methods(http.MethodGet)
if assets != nil {
fs := http.FileServer(assets)

View File

@ -18,7 +18,7 @@ import (
"storj.io/storj/private/version/checker"
"storj.io/storj/storagenode/bandwidth"
"storj.io/storj/storagenode/contact"
"storj.io/storj/storagenode/estimatedpayout"
"storj.io/storj/storagenode/payout/estimatedpayout"
"storj.io/storj/storagenode/pieces"
"storj.io/storj/storagenode/pricing"
"storj.io/storj/storagenode/reputation"

View File

@ -15,7 +15,7 @@ import (
"storj.io/common/storj"
"storj.io/common/sync2"
"storj.io/storj/private/date"
"storj.io/storj/storagenode/heldamount"
"storj.io/storj/storagenode/payout"
"storj.io/storj/storagenode/pricing"
"storj.io/storj/storagenode/reputation"
"storj.io/storj/storagenode/satellites"
@ -34,7 +34,7 @@ type Config struct {
type CacheStorage struct {
Reputation reputation.DB
StorageUsage storageusage.DB
HeldAmount heldamount.DB
Payout payout.DB
Pricing pricing.DB
Satellites satellites.DB
}
@ -46,11 +46,11 @@ type CacheStorage struct {
type Cache struct {
log *zap.Logger
db CacheStorage
service *Service
heldamountEndpoint *heldamount.Endpoint
heldamountService *heldamount.Service
trust *trust.Pool
db CacheStorage
service *Service
payoutEndpoint *payout.Endpoint
payoutService *payout.Service
trust *trust.Pool
maxSleep time.Duration
Reputation *sync2.Cycle
@ -58,17 +58,17 @@ type Cache struct {
}
// NewCache creates new caching service instance.
func NewCache(log *zap.Logger, config Config, db CacheStorage, service *Service, heldamountEndpoint *heldamount.Endpoint, heldamountService *heldamount.Service, trust *trust.Pool) *Cache {
func NewCache(log *zap.Logger, config Config, db CacheStorage, service *Service, heldamountEndpoint *payout.Endpoint, heldamountService *payout.Service, trust *trust.Pool) *Cache {
return &Cache{
log: log,
db: db,
service: service,
heldamountEndpoint: heldamountEndpoint,
heldamountService: heldamountService,
trust: trust,
maxSleep: config.MaxSleep,
Reputation: sync2.NewCycle(config.ReputationSync),
Storage: sync2.NewCycle(config.StorageSync),
log: log,
db: db,
service: service,
payoutEndpoint: heldamountEndpoint,
payoutService: heldamountService,
trust: trust,
maxSleep: config.MaxSleep,
Reputation: sync2.NewCycle(config.ReputationSync),
Storage: sync2.NewCycle(config.StorageSync),
}
}
@ -77,25 +77,25 @@ func (cache *Cache) Run(ctx context.Context) error {
var group errgroup.Group
err := cache.satelliteLoop(ctx, func(satelliteID storj.NodeID) error {
stubHistory, err := cache.heldamountEndpoint.GetAllPaystubs(ctx, satelliteID)
stubHistory, err := cache.payoutEndpoint.GetAllPaystubs(ctx, satelliteID)
if err != nil {
return err
}
for i := 0; i < len(stubHistory); i++ {
err := cache.db.HeldAmount.StorePayStub(ctx, stubHistory[i])
err := cache.db.Payout.StorePayStub(ctx, stubHistory[i])
if err != nil {
return err
}
}
paymentHistory, err := cache.heldamountEndpoint.GetAllPayments(ctx, satelliteID)
paymentHistory, err := cache.payoutEndpoint.GetAllPayments(ctx, satelliteID)
if err != nil {
return err
}
for j := 0; j < len(paymentHistory); j++ {
err := cache.db.HeldAmount.StorePayment(ctx, paymentHistory[j])
err := cache.db.Payout.StorePayment(ctx, paymentHistory[j])
if err != nil {
return err
}
@ -199,29 +199,29 @@ func (cache *Cache) CacheHeldAmount(ctx context.Context) (err error) {
}
previousMonth := yearAndMonth.AddDate(0, -1, 0).String()
payStub, err := cache.heldamountEndpoint.GetPaystub(ctx, satellite, previousMonth)
payStub, err := cache.payoutEndpoint.GetPaystub(ctx, satellite, previousMonth)
if err != nil {
if heldamount.ErrNoPayStubForPeriod.Has(err) {
if payout.ErrNoPayStubForPeriod.Has(err) {
return nil
}
cache.log.Error("heldamount err", zap.String("satellite", satellite.String()))
cache.log.Error("payout err", zap.String("satellite", satellite.String()))
return err
}
if payStub != nil {
if err = cache.db.HeldAmount.StorePayStub(ctx, *payStub); err != nil {
if err = cache.db.Payout.StorePayStub(ctx, *payStub); err != nil {
return err
}
}
payment, err := cache.heldamountEndpoint.GetPayment(ctx, satellite, previousMonth)
payment, err := cache.payoutEndpoint.GetPayment(ctx, satellite, previousMonth)
if err != nil {
return err
}
if payment != nil {
if err = cache.db.HeldAmount.StorePayment(ctx, *payment); err != nil {
if err = cache.db.Payout.StorePayment(ctx, *payment); err != nil {
return err
}
}

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount_test
package payout_test
import (
"fmt"
@ -14,16 +14,16 @@ import (
"storj.io/common/storj"
"storj.io/common/testcontext"
"storj.io/storj/storagenode"
"storj.io/storj/storagenode/heldamount"
"storj.io/storj/storagenode/payout"
"storj.io/storj/storagenode/storagenodedb/storagenodedbtest"
)
func TestHeldAmountDB(t *testing.T) {
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
heldAmount := db.HeldAmount()
payouts := db.Payout()
satelliteID := storj.NodeID{}
period := "2020-01"
paystub := heldamount.PayStub{
paystub := payout.PayStub{
SatelliteID: satelliteID,
Period: "2020-01",
Created: time.Now().UTC(),
@ -50,23 +50,23 @@ func TestHeldAmountDB(t *testing.T) {
paystub2.Created = paystub.Created.Add(time.Hour * 24 * 30)
t.Run("Test StorePayStub", func(t *testing.T) {
err := heldAmount.StorePayStub(ctx, paystub)
err := payouts.StorePayStub(ctx, paystub)
assert.NoError(t, err)
})
payment := heldamount.Payment{
payment := payout.Payment{
SatelliteID: satelliteID,
Period: period,
Receipt: "test",
}
t.Run("Test GetPayStub", func(t *testing.T) {
err := heldAmount.StorePayment(ctx, payment)
err := payouts.StorePayment(ctx, payment)
assert.NoError(t, err)
stub, err := heldAmount.GetPayStub(ctx, satelliteID, period)
stub, err := payouts.GetPayStub(ctx, satelliteID, period)
assert.NoError(t, err)
receipt, err := heldAmount.GetReceipt(ctx, satelliteID, period)
receipt, err := payouts.GetReceipt(ctx, satelliteID, period)
assert.NoError(t, err)
assert.Equal(t, stub.Period, paystub.Period)
assert.Equal(t, stub.Created, paystub.Created)
@ -91,24 +91,24 @@ func TestHeldAmountDB(t *testing.T) {
assert.Equal(t, stub.UsagePutRepair, paystub.UsagePutRepair)
assert.Equal(t, receipt, payment.Receipt)
stub, err = heldAmount.GetPayStub(ctx, satelliteID, "")
stub, err = payouts.GetPayStub(ctx, satelliteID, "")
assert.Error(t, err)
assert.Equal(t, true, heldamount.ErrNoPayStubForPeriod.Has(err))
assert.Equal(t, true, payout.ErrNoPayStubForPeriod.Has(err))
assert.Nil(t, stub)
assert.NotNil(t, receipt)
receipt, err = heldAmount.GetReceipt(ctx, satelliteID, "")
receipt, err = payouts.GetReceipt(ctx, satelliteID, "")
assert.Error(t, err)
assert.Equal(t, true, heldamount.ErrNoPayStubForPeriod.Has(err))
assert.Equal(t, true, payout.ErrNoPayStubForPeriod.Has(err))
stub, err = heldAmount.GetPayStub(ctx, storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, period)
stub, err = payouts.GetPayStub(ctx, storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1}, period)
assert.Error(t, err)
assert.Equal(t, true, heldamount.ErrNoPayStubForPeriod.Has(err))
assert.Equal(t, true, payout.ErrNoPayStubForPeriod.Has(err))
assert.Nil(t, stub)
assert.NotNil(t, receipt)
})
t.Run("Test AllPayStubs", func(t *testing.T) {
stubs, err := heldAmount.AllPayStubs(ctx, period)
stubs, err := payouts.AllPayStubs(ctx, period)
assert.NoError(t, err)
assert.NotNil(t, stubs)
assert.Equal(t, 1, len(stubs))
@ -134,12 +134,12 @@ func TestHeldAmountDB(t *testing.T) {
assert.Equal(t, stubs[0].UsagePut, paystub.UsagePut)
assert.Equal(t, stubs[0].UsagePutRepair, paystub.UsagePutRepair)
stubs, err = heldAmount.AllPayStubs(ctx, "")
stubs, err = payouts.AllPayStubs(ctx, "")
assert.Equal(t, len(stubs), 0)
assert.NoError(t, err)
})
payment = heldamount.Payment{
payment = payout.Payment{
ID: 1,
Created: time.Now().UTC(),
SatelliteID: satelliteID,
@ -150,28 +150,28 @@ func TestHeldAmountDB(t *testing.T) {
}
t.Run("Test StorePayment", func(t *testing.T) {
err := heldAmount.StorePayment(ctx, payment)
err := payouts.StorePayment(ctx, payment)
assert.NoError(t, err)
})
t.Run("Test SatellitesHeldbackHistory", func(t *testing.T) {
heldback, err := heldAmount.SatellitesHeldbackHistory(ctx, satelliteID)
heldback, err := payouts.SatellitesHeldbackHistory(ctx, satelliteID)
assert.NoError(t, err)
assert.Equal(t, heldback[0].Held, paystub.Held)
assert.Equal(t, heldback[0].Amount, paystub.Held)
assert.Equal(t, heldback[0].Period, paystub.Period)
})
t.Run("Test SatellitePeriods", func(t *testing.T) {
periods, err := heldAmount.SatellitePeriods(ctx, paystub.SatelliteID)
periods, err := payouts.SatellitePeriods(ctx, paystub.SatelliteID)
assert.NoError(t, err)
assert.NotNil(t, periods)
assert.Equal(t, 1, len(periods))
assert.Equal(t, paystub.Period, periods[0])
err = heldAmount.StorePayStub(ctx, paystub2)
err = payouts.StorePayStub(ctx, paystub2)
require.NoError(t, err)
periods, err = heldAmount.SatellitePeriods(ctx, paystub.SatelliteID)
periods, err = payouts.SatellitePeriods(ctx, paystub.SatelliteID)
assert.NoError(t, err)
assert.NotNil(t, periods)
assert.Equal(t, 2, len(periods))
@ -180,7 +180,7 @@ func TestHeldAmountDB(t *testing.T) {
})
t.Run("Test AllPeriods", func(t *testing.T) {
periods, err := heldAmount.AllPeriods(ctx)
periods, err := payouts.AllPeriods(ctx)
assert.NoError(t, err)
assert.NotNil(t, periods)
assert.Equal(t, 2, len(periods))
@ -192,10 +192,10 @@ func TestHeldAmountDB(t *testing.T) {
paystub3.Period = "2020-03"
paystub3.Created = paystub2.Created.Add(time.Hour * 24 * 30)
err = heldAmount.StorePayStub(ctx, paystub3)
err = payouts.StorePayStub(ctx, paystub3)
require.NoError(t, err)
periods, err = heldAmount.AllPeriods(ctx)
periods, err = payouts.AllPeriods(ctx)
assert.NoError(t, err)
assert.NotNil(t, periods)
assert.Equal(t, 3, len(periods))
@ -208,12 +208,12 @@ func TestHeldAmountDB(t *testing.T) {
func TestSatellitePayStubPeriodCached(t *testing.T) {
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
heldAmountDB := db.HeldAmount()
heldAmountDB := db.Payout()
reputationDB := db.Reputation()
satellitesDB := db.Satellites()
service := heldamount.NewService(nil, heldAmountDB, reputationDB, satellitesDB, nil)
service := payout.NewService(nil, heldAmountDB, reputationDB, satellitesDB, nil)
payStub := heldamount.PayStub{
payStub := payout.PayStub{
SatelliteID: storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
Created: time.Now().UTC(),
Codes: "code",
@ -258,12 +258,12 @@ func TestSatellitePayStubPeriodCached(t *testing.T) {
func TestAllPayStubPeriodCached(t *testing.T) {
storagenodedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db storagenode.DB) {
heldAmountDB := db.HeldAmount()
heldAmountDB := db.Payout()
reputationDB := db.Reputation()
satellitesDB := db.Satellites()
service := heldamount.NewService(nil, heldAmountDB, reputationDB, satellitesDB, nil)
service := payout.NewService(nil, heldAmountDB, reputationDB, satellitesDB, nil)
payStub := heldamount.PayStub{
payStub := payout.PayStub{
SatelliteID: storj.NodeID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1},
Created: time.Now().UTC(),
Codes: "code",

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount
package payout
import (
"context"
@ -55,13 +55,13 @@ func (endpoint *Endpoint) GetPaystub(ctx context.Context, satelliteID storj.Node
client, err := endpoint.dial(ctx, satelliteID)
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
defer func() { err = errs.Combine(err, client.Close()) }()
requestedPeriod, err := date.PeriodToTime(period)
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
resp, err := client.GetPayStub(ctx, &pb.GetHeldAmountRequest{Period: requestedPeriod})
@ -70,7 +70,7 @@ func (endpoint *Endpoint) GetPaystub(ctx context.Context, satelliteID storj.Node
return nil, ErrNoPayStubForPeriod.Wrap(err)
}
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
return &PayStub{
@ -104,13 +104,13 @@ func (endpoint *Endpoint) GetAllPaystubs(ctx context.Context, satelliteID storj.
client, err := endpoint.dial(ctx, satelliteID)
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
defer func() { err = errs.Combine(err, client.Close()) }()
resp, err := client.GetAllPaystubs(ctx, &pb.GetAllPaystubsRequest{})
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
var payStubs []PayStub
@ -152,13 +152,13 @@ func (endpoint *Endpoint) GetPayment(ctx context.Context, satelliteID storj.Node
client, err := endpoint.dial(ctx, satelliteID)
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
defer func() { err = errs.Combine(err, client.Close()) }()
requestedPeriod, err := date.PeriodToTime(period)
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
resp, err := client.GetPayment(ctx, &pb.GetPaymentRequest{Period: requestedPeriod})
@ -167,7 +167,7 @@ func (endpoint *Endpoint) GetPayment(ctx context.Context, satelliteID storj.Node
return nil, nil
}
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
return &Payment{
@ -187,13 +187,13 @@ func (endpoint *Endpoint) GetAllPayments(ctx context.Context, satelliteID storj.
client, err := endpoint.dial(ctx, satelliteID)
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
defer func() { err = errs.Combine(err, client.Close()) }()
resp, err := client.GetAllPayments(ctx, &pb.GetAllPaymentsRequest{})
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
var payments []Payment
@ -215,7 +215,7 @@ func (endpoint *Endpoint) GetAllPayments(ctx context.Context, satelliteID storj.
return payments, nil
}
// dial dials the HeldAmount client for the satellite by id.
// dial dials the SnoPayout client for the satellite by id.
func (endpoint *Endpoint) dial(ctx context.Context, satelliteID storj.NodeID) (_ *Client, err error) {
defer mon.Task()(&ctx)(&err)

View File

@ -13,6 +13,7 @@ import (
"storj.io/common/storj"
"storj.io/storj/private/date"
"storj.io/storj/storagenode/bandwidth"
payout2 "storj.io/storj/storagenode/payout"
"storj.io/storj/storagenode/pricing"
"storj.io/storj/storagenode/reputation"
"storj.io/storj/storagenode/satellites"
@ -122,7 +123,7 @@ func (s *Service) estimatedPayout(ctx context.Context, satelliteID storj.NodeID)
func (s *Service) estimationUsagePeriod(ctx context.Context, period time.Time, joinedAt time.Time, priceModel *pricing.Pricing) (payout PayoutMonthly, err error) {
var from, to time.Time
heldRate := getHeldRate(joinedAt, period)
heldRate := payout2.GetHeldRate(joinedAt, period)
payout.HeldRate = heldRate
from, to = date.MonthBoundary(period)
@ -155,20 +156,3 @@ func (s *Service) estimationUsagePeriod(ctx context.Context, period time.Time, j
return payout, EstimationServiceErr.Wrap(err)
}
// getHeldRate returns held rate for specific period from join date of node.
func getHeldRate(joinTime time.Time, requestTime time.Time) (heldRate int64) {
monthsSinceJoin := date.MonthsBetweenDates(joinTime, requestTime)
switch monthsSinceJoin {
case 0, 1, 2:
heldRate = 75
case 3, 4, 5:
heldRate = 50
case 6, 7, 8:
heldRate = 25
default:
heldRate = 0
}
return heldRate
}

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount
package payout
import (
"context"
@ -12,7 +12,7 @@ import (
"storj.io/common/storj"
)
// DB works with heldamount database
// DB works with payout database
//
// architecture: Database
type DB interface {
@ -23,12 +23,12 @@ type DB interface {
// AllPayStubs retrieves paystubs from all satellites in specific period from DB.
AllPayStubs(ctx context.Context, period string) ([]PayStub, error)
// SatellitesHeldbackHistory retrieves heldback history for specific satellite from DB.
SatellitesHeldbackHistory(ctx context.Context, satelliteID storj.NodeID) ([]AmountPeriod, error)
SatellitesHeldbackHistory(ctx context.Context, satelliteID storj.NodeID) ([]HoldForPeriod, error)
// SatellitesDisposedHistory returns all disposed amount for specific satellite from DB.
SatellitesDisposedHistory(ctx context.Context, satelliteID storj.NodeID) (int64, error)
// SatellitePeriods retrieves all periods for concrete satellite in which we have some heldamount data.
// SatellitePeriods retrieves all periods for concrete satellite in which we have some payout data.
SatellitePeriods(ctx context.Context, satelliteID storj.NodeID) ([]string, error)
// AllPeriods retrieves all periods in which we have some heldamount data.
// AllPeriods retrieves all periods in which we have some payout data.
AllPeriods(ctx context.Context) ([]string, error)
// StorePayment inserts or updates payment into the DB
StorePayment(ctx context.Context, payment Payment) error
@ -36,10 +36,10 @@ type DB interface {
GetReceipt(ctx context.Context, satelliteID storj.NodeID, period string) (string, error)
}
// ErrNoPayStubForPeriod represents errors from the heldamount database.
// ErrNoPayStubForPeriod represents errors from the payout database.
var ErrNoPayStubForPeriod = errs.Class("no payStub for period error")
// PayStub is node heldamount data for satellite by specific period.
// PayStub is node payout data for satellite by specific period.
type PayStub struct {
SatelliteID storj.NodeID `json:"satelliteId"`
Period string `json:"period"`
@ -64,10 +64,10 @@ type PayStub struct {
Paid int64 `json:"paid"`
}
// AmountPeriod is node's held amount for period.
type AmountPeriod struct {
// HoldForPeriod is node's held amount for period.
type HoldForPeriod struct {
Period string `json:"period"`
Held int64 `json:"held"`
Amount int64 `json:"amount"`
}
// Payment is node payment data for specific period.
@ -81,6 +81,43 @@ type Payment struct {
Notes string `json:"notes"`
}
// SatelliteHeldHistory amount of held for specific satellite for all time since join.
type SatelliteHeldHistory struct {
SatelliteID storj.NodeID `json:"satelliteID"`
SatelliteName string `json:"satelliteName"`
HoldForFirstPeriod int64 `json:"holdForFirstPeriod"`
HoldForSecondPeriod int64 `json:"holdForSecondPeriod"`
HoldForThirdPeriod int64 `json:"holdForThirdPeriod"`
TotalHeld int64 `json:"totalHeld"`
TotalDisposed int64 `json:"totalDisposed"`
JoinedAt time.Time `json:"joinedAt"`
}
// SatellitePayoutForPeriod contains payout information for specific period for specific satellite.
type SatellitePayoutForPeriod struct {
SatelliteID string `json:"satelliteID"`
SatelliteURL string `json:"satelliteURL"`
Age int64 `json:"age"`
Earned int64 `json:"earned"`
Surge int64 `json:"surge"`
SurgePercent int64 `json:"surgePercent"`
Held int64 `json:"held"`
HeldPercent int64 `json:"heldPercent"`
AfterHeld int64 `json:"afterHeld"`
Disposed int64 `json:"disposed"`
Paid int64 `json:"paid"`
Receipt string `json:"receipt"`
IsExitComplete bool `json:"isExitComplete"`
}
// Period is a string that represents paystub period type in format yyyy-mm.
type Period string
// Time returns period in time.Time type from string.
func (p Period) Time() (time.Time, error) {
return time.Parse("2006-01", string(p))
}
// GetEarnedWithSurge returns paystub's total earned and surge.
func (paystub *PayStub) GetEarnedWithSurge() (earned int64, surge int64) {
earned = paystub.CompGetAudit + paystub.CompGet + paystub.CompGetRepair + paystub.CompAtRest

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount
package payout
import (
"context"
@ -24,8 +24,8 @@ import (
)
var (
// ErrHeldAmountService defines held amount service error.
ErrHeldAmountService = errs.Class("heldamount service error")
// ErrPayoutService defines held amount service error.
ErrPayoutService = errs.Class("payout service error")
// ErrBadPeriod defines that period has wrong format.
ErrBadPeriod = errs.Class("wrong period format")
@ -62,7 +62,7 @@ func (service *Service) SatellitePayStubMonthly(ctx context.Context, satelliteID
payStub, err = service.db.GetPayStub(ctx, satelliteID, period)
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
payStub.UsageAtRestTbM()
@ -76,7 +76,7 @@ func (service *Service) AllPayStubsMonthly(ctx context.Context, period string) (
payStubs, err = service.db.AllPayStubs(ctx, period)
if err != nil {
return payStubs, ErrHeldAmountService.Wrap(err)
return payStubs, ErrPayoutService.Wrap(err)
}
for i := 0; i < len(payStubs); i++ {
@ -102,7 +102,7 @@ func (service *Service) SatellitePayStubPeriod(ctx context.Context, satelliteID
continue
}
return []PayStub{}, ErrHeldAmountService.Wrap(err)
return []PayStub{}, ErrPayoutService.Wrap(err)
}
payStubs = append(payStubs, *payStub)
@ -131,7 +131,7 @@ func (service *Service) AllPayStubsPeriod(ctx context.Context, periodStart, peri
continue
}
return []PayStub{}, ErrHeldAmountService.Wrap(err)
return []PayStub{}, ErrPayoutService.Wrap(err)
}
payStubs = append(payStubs, payStub...)
@ -144,62 +144,49 @@ func (service *Service) AllPayStubsPeriod(ctx context.Context, periodStart, peri
return payStubs, nil
}
// SatellitePeriods retrieves all periods for concrete satellite in which we have some heldamount data.
// SatellitePeriods retrieves all periods for concrete satellite in which we have some payout data.
func (service *Service) SatellitePeriods(ctx context.Context, satelliteID storj.NodeID) (_ []string, err error) {
defer mon.Task()(&ctx)(&err)
return service.db.SatellitePeriods(ctx, satelliteID)
}
// AllPeriods retrieves all periods in which we have some heldamount data.
// AllPeriods retrieves all periods in which we have some payout data.
func (service *Service) AllPeriods(ctx context.Context) (_ []string, err error) {
defer mon.Task()(&ctx)(&err)
return service.db.AllPeriods(ctx)
}
// HeldHistory amount of held for specific percent rate period.
type HeldHistory struct {
SatelliteID storj.NodeID `json:"satelliteID"`
SatelliteName string `json:"satelliteName"`
Age int64 `json:"age"`
FirstPeriod int64 `json:"firstPeriod"`
SecondPeriod int64 `json:"secondPeriod"`
ThirdPeriod int64 `json:"thirdPeriod"`
TotalHeld int64 `json:"totalHeld"`
TotalDisposed int64 `json:"totalDisposed"`
JoinedAt time.Time `json:"joinedAt"`
}
// AllHeldbackHistory retrieves heldback history for all satellites from storagenode database.
func (service *Service) AllHeldbackHistory(ctx context.Context) (result []HeldHistory, err error) {
func (service *Service) AllHeldbackHistory(ctx context.Context) (result []SatelliteHeldHistory, err error) {
defer mon.Task()(&ctx)(&err)
satellites := service.trust.GetSatellites(ctx)
for i := 0; i < len(satellites); i++ {
var history HeldHistory
var history SatelliteHeldHistory
heldback, err := service.db.SatellitesHeldbackHistory(ctx, satellites[i])
helds, err := service.db.SatellitesHeldbackHistory(ctx, satellites[i])
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
disposed, err := service.db.SatellitesDisposedHistory(ctx, satellites[i])
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
for i, t := range heldback {
for i, amountPeriod := range helds {
switch i {
case 0, 1, 2:
history.FirstPeriod += t.Held
history.TotalHeld += t.Held
history.HoldForFirstPeriod += amountPeriod.Amount
history.TotalHeld += amountPeriod.Amount
case 3, 4, 5:
history.SecondPeriod += t.Held
history.TotalHeld += t.Held
history.HoldForSecondPeriod += amountPeriod.Amount
history.TotalHeld += amountPeriod.Amount
case 6, 7, 8:
history.ThirdPeriod += t.Held
history.TotalHeld += t.Held
history.HoldForThirdPeriod += amountPeriod.Amount
history.TotalHeld += amountPeriod.Amount
default:
}
}
@ -208,15 +195,14 @@ func (service *Service) AllHeldbackHistory(ctx context.Context) (result []HeldHi
history.SatelliteID = satellites[i]
url, err := service.trust.GetNodeURL(ctx, satellites[i])
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
stats, err := service.reputationDB.Get(ctx, satellites[i])
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
history.Age = int64(date.MonthsCountSince(stats.JoinedAt))
history.SatelliteName = url.Address
history.JoinedAt = stats.JoinedAt
@ -226,67 +212,50 @@ func (service *Service) AllHeldbackHistory(ctx context.Context) (result []HeldHi
return result, nil
}
// PayoutHistory contains payout information for specific period for specific satellite.
type PayoutHistory struct {
SatelliteID string `json:"satelliteID"`
SatelliteURL string `json:"satelliteURL"`
Age int64 `json:"age"`
Earned int64 `json:"earned"`
Surge int64 `json:"surge"`
SurgePercent int64 `json:"surgePercent"`
Held int64 `json:"held"`
HeldPercent int64 `json:"heldPercent"`
AfterHeld int64 `json:"afterHeld"`
Disposed int64 `json:"disposed"`
Paid int64 `json:"paid"`
Receipt string `json:"receipt"`
IsExitComplete bool `json:"isExitComplete"`
}
// PayoutHistoryMonthly retrieves paystub and payment receipt for specific month from all satellites.
func (service *Service) PayoutHistoryMonthly(ctx context.Context, period string) (result []PayoutHistory, err error) {
// AllSatellitesPayoutPeriod retrieves paystub and payment receipt for specific month from all satellites.
func (service *Service) AllSatellitesPayoutPeriod(ctx context.Context, period string) (result []SatellitePayoutForPeriod, err error) {
defer mon.Task()(&ctx)(&err)
satelliteIDs := service.trust.GetSatellites(ctx)
for i := 0; i < len(satelliteIDs); i++ {
var payoutHistory PayoutHistory
var payoutForPeriod SatellitePayoutForPeriod
paystub, err := service.db.GetPayStub(ctx, satelliteIDs[i], period)
if err != nil {
if ErrNoPayStubForPeriod.Has(err) {
continue
}
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
receipt, err := service.db.GetReceipt(ctx, satelliteIDs[i], period)
if err != nil {
if !ErrNoPayStubForPeriod.Has(err) {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
receipt = "no receipt for this period"
}
stats, err := service.reputationDB.Get(ctx, satelliteIDs[i])
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
satellite, err := service.satellitesDB.GetSatellite(ctx, satelliteIDs[i])
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
payoutHistory.IsExitComplete = false
payoutForPeriod.IsExitComplete = false
}
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
url, err := service.trust.GetNodeURL(ctx, satelliteIDs[i])
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
if satellite.Status == satellites.ExitSucceeded {
payoutHistory.IsExitComplete = true
payoutForPeriod.IsExitComplete = true
}
if paystub.SurgePercent == 0 {
@ -295,25 +264,28 @@ func (service *Service) PayoutHistoryMonthly(ctx context.Context, period string)
earned, surge := paystub.GetEarnedWithSurge()
heldPercent, err := service.getHeldRate(stats.JoinedAt, paystub.Period)
periodTime := Period(paystub.Period)
heldPeriod, err := periodTime.Time()
if err != nil {
return nil, ErrHeldAmountService.Wrap(err)
return nil, ErrPayoutService.Wrap(err)
}
payoutHistory.Held = paystub.Held
payoutHistory.Receipt = receipt
payoutHistory.Surge = surge
payoutHistory.AfterHeld = payoutHistory.Surge - paystub.Held
payoutHistory.Age = int64(date.MonthsCountSince(stats.JoinedAt))
payoutHistory.Disposed = paystub.Disposed
payoutHistory.Earned = earned
payoutHistory.SatelliteID = satelliteIDs[i].String()
payoutHistory.SurgePercent = paystub.SurgePercent
payoutHistory.SatelliteURL = url.Address
payoutHistory.Paid = paystub.Paid
payoutHistory.HeldPercent = heldPercent
heldPercent := GetHeldRate(stats.JoinedAt, heldPeriod)
payoutForPeriod.Held = paystub.Held
payoutForPeriod.Receipt = receipt
payoutForPeriod.Surge = surge
payoutForPeriod.AfterHeld = surge - paystub.Held
payoutForPeriod.Age = int64(date.MonthsCountSince(stats.JoinedAt))
payoutForPeriod.Disposed = paystub.Disposed
payoutForPeriod.Earned = earned
payoutForPeriod.SatelliteID = satelliteIDs[i].String()
payoutForPeriod.SurgePercent = paystub.SurgePercent
payoutForPeriod.SatelliteURL = url.Address
payoutForPeriod.Paid = paystub.Paid
payoutForPeriod.HeldPercent = heldPercent
result = append(result, payoutHistory)
result = append(result, payoutForPeriod)
}
return result, nil
@ -374,15 +346,10 @@ func parsePeriodRange(periodStart, periodEnd string) (periods []string, err erro
return periods, nil
}
func (service *Service) getHeldRate(joinedAt time.Time, period string) (heldRate int64, err error) {
layout := "2006-01-02T15:04:05.000Z"
periodTime, err := time.Parse(layout, period+"-12T11:45:26.371Z")
if err != nil {
return 0, err
}
months := date.MonthsBetweenDates(joinedAt, periodTime)
switch months {
// GetHeldRate returns held rate for specific period from join date of node.
func GetHeldRate(joinTime time.Time, requestTime time.Time) (heldRate int64) {
monthsSinceJoin := date.MonthsBetweenDates(joinTime, requestTime)
switch monthsSinceJoin {
case 0, 1, 2:
heldRate = 75
case 3, 4, 5:
@ -393,5 +360,5 @@ func (service *Service) getHeldRate(joinedAt time.Time, period string) (heldRate
heldRate = 0
}
return heldRate, nil
return heldRate
}

View File

@ -1,7 +1,7 @@
// Copyright (C) 2020 Storj Labs, Inc.
// See LICENSE for copying information.
package heldamount
package payout
import (
"testing"

View File

@ -37,14 +37,14 @@ import (
"storj.io/storj/storagenode/console/consoleassets"
"storj.io/storj/storagenode/console/consoleserver"
"storj.io/storj/storagenode/contact"
"storj.io/storj/storagenode/estimatedpayout"
"storj.io/storj/storagenode/gracefulexit"
"storj.io/storj/storagenode/heldamount"
"storj.io/storj/storagenode/inspector"
"storj.io/storj/storagenode/monitor"
"storj.io/storj/storagenode/nodestats"
"storj.io/storj/storagenode/notifications"
"storj.io/storj/storagenode/orders"
"storj.io/storj/storagenode/payout"
"storj.io/storj/storagenode/payout/estimatedpayout"
"storj.io/storj/storagenode/pieces"
"storj.io/storj/storagenode/piecestore"
"storj.io/storj/storagenode/piecestore/usedserials"
@ -83,7 +83,7 @@ type DB interface {
StorageUsage() storageusage.DB
Satellites() satellites.DB
Notifications() notifications.DB
HeldAmount() heldamount.DB
Payout() payout.DB
Pricing() pricing.DB
Preflight(ctx context.Context) error
@ -262,9 +262,9 @@ type Peer struct {
Service *notifications.Service
}
Heldamount struct {
Service *heldamount.Service
Endpoint *heldamount.Endpoint
Payout struct {
Service *payout.Service
Endpoint *payout.Endpoint
}
Bandwidth *bandwidth.Service
@ -543,16 +543,16 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
debug.Cycle("Orders Cleanup", peer.Storage2.Orders.Cleanup))
}
{ // setup heldamount service.
peer.Heldamount.Service = heldamount.NewService(
peer.Log.Named("heldamount:service"),
peer.DB.HeldAmount(),
{ // setup payout service.
peer.Payout.Service = payout.NewService(
peer.Log.Named("payout:service"),
peer.DB.Payout(),
peer.DB.Reputation(),
peer.DB.Satellites(),
peer.Storage2.Trust,
)
peer.Heldamount.Endpoint = heldamount.NewEndpoint(
peer.Log.Named("heldamount:endpoint"),
peer.Payout.Endpoint = payout.NewEndpoint(
peer.Log.Named("payout:endpoint"),
peer.Dialer,
peer.Storage2.Trust,
)
@ -571,13 +571,13 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
nodestats.CacheStorage{
Reputation: peer.DB.Reputation(),
StorageUsage: peer.DB.StorageUsage(),
HeldAmount: peer.DB.HeldAmount(),
Payout: peer.DB.Payout(),
Pricing: peer.DB.Pricing(),
Satellites: peer.DB.Satellites(),
},
peer.NodeStats.Service,
peer.Heldamount.Endpoint,
peer.Heldamount.Service,
peer.Payout.Endpoint,
peer.Payout.Service,
peer.Storage2.Trust,
)
peer.Services.Add(lifecycle.Item{
@ -640,7 +640,7 @@ func New(log *zap.Logger, full *identity.FullIdentity, db DB, revocationDB exten
assets,
peer.Notifications.Service,
peer.Console.Service,
peer.Heldamount.Service,
peer.Payout.Service,
peer.Console.Listener,
)
peer.Services.Add(lifecycle.Item{

View File

@ -26,9 +26,9 @@ import (
"storj.io/storj/storage"
"storj.io/storj/storage/filestore"
"storj.io/storj/storagenode/bandwidth"
"storj.io/storj/storagenode/heldamount"
"storj.io/storj/storagenode/notifications"
"storj.io/storj/storagenode/orders"
"storj.io/storj/storagenode/payout"
"storj.io/storj/storagenode/pieces"
"storj.io/storj/storagenode/pricing"
"storj.io/storj/storagenode/reputation"
@ -104,7 +104,7 @@ type DB struct {
usedSerialsDB *usedSerialsDB
satellitesDB *satellitesDB
notificationsDB *notificationDB
heldamountDB *heldamountDB
payoutDB *payoutDB
pricingDB *pricingDB
SQLDBs map[string]DBContainer
@ -130,7 +130,7 @@ func New(log *zap.Logger, config Config) (*DB, error) {
usedSerialsDB := &usedSerialsDB{}
satellitesDB := &satellitesDB{}
notificationsDB := &notificationDB{}
heldamountDB := &heldamountDB{}
payoutDB := &payoutDB{}
pricingDB := &pricingDB{}
db := &DB{
@ -152,7 +152,7 @@ func New(log *zap.Logger, config Config) (*DB, error) {
usedSerialsDB: usedSerialsDB,
satellitesDB: satellitesDB,
notificationsDB: notificationsDB,
heldamountDB: heldamountDB,
payoutDB: payoutDB,
pricingDB: pricingDB,
SQLDBs: map[string]DBContainer{
@ -167,7 +167,7 @@ func New(log *zap.Logger, config Config) (*DB, error) {
UsedSerialsDBName: usedSerialsDB,
SatellitesDBName: satellitesDB,
NotificationsDBName: notificationsDB,
HeldAmountDBName: heldamountDB,
HeldAmountDBName: payoutDB,
PricingDBName: pricingDB,
},
}
@ -200,7 +200,7 @@ func Open(log *zap.Logger, config Config) (*DB, error) {
usedSerialsDB := &usedSerialsDB{}
satellitesDB := &satellitesDB{}
notificationsDB := &notificationDB{}
heldamountDB := &heldamountDB{}
payoutDB := &payoutDB{}
pricingDB := &pricingDB{}
db := &DB{
@ -222,7 +222,7 @@ func Open(log *zap.Logger, config Config) (*DB, error) {
usedSerialsDB: usedSerialsDB,
satellitesDB: satellitesDB,
notificationsDB: notificationsDB,
heldamountDB: heldamountDB,
payoutDB: payoutDB,
pricingDB: pricingDB,
SQLDBs: map[string]DBContainer{
@ -237,7 +237,7 @@ func Open(log *zap.Logger, config Config) (*DB, error) {
UsedSerialsDBName: usedSerialsDB,
SatellitesDBName: satellitesDB,
NotificationsDBName: notificationsDB,
HeldAmountDBName: heldamountDB,
HeldAmountDBName: payoutDB,
PricingDBName: pricingDB,
},
}
@ -565,9 +565,9 @@ func (db *DB) Notifications() notifications.DB {
return db.notificationsDB
}
// HeldAmount returns instance of the HeldAmount database.
func (db *DB) HeldAmount() heldamount.DB {
return db.heldamountDB
// Payout returns instance of the SnoPayout database.
func (db *DB) Payout() payout.DB {
return db.payoutDB
}
// Pricing returns instance of the Pricing database.
@ -1193,7 +1193,7 @@ func (db *DB) Migration(ctx context.Context) *migrate.Migration {
},
},
{
DB: db.heldamountDB,
DB: db.payoutDB,
Description: "Create paystubs table and payments table",
Version: 32,
Action: migrate.SQL{
@ -1234,7 +1234,7 @@ func (db *DB) Migration(ctx context.Context) *migrate.Migration {
},
},
{
DB: db.heldamountDB,
DB: db.payoutDB,
Description: "Remove time zone from created_at in paystubs and payments",
Version: 33,
Action: migrate.SQL{
@ -1308,7 +1308,7 @@ func (db *DB) Migration(ctx context.Context) *migrate.Migration {
},
},
{
DB: db.heldamountDB,
DB: db.payoutDB,
Description: "Drop payments table as unused",
Version: 37,
Action: migrate.SQL{
@ -1579,7 +1579,7 @@ func (db *DB) Migration(ctx context.Context) *migrate.Migration {
}),
},
{
DB: db.heldamountDB,
DB: db.payoutDB,
Description: "Add table payments",
Version: 43,
Action: migrate.SQL{

View File

@ -11,25 +11,25 @@ import (
"github.com/zeebo/errs"
"storj.io/common/storj"
"storj.io/storj/storagenode/heldamount"
"storj.io/storj/storagenode/payout"
)
// ensures that heldamountDB implements heldamount.DB interface.
var _ heldamount.DB = (*heldamountDB)(nil)
// ensures that payoutDB implements payout.DB interface.
var _ payout.DB = (*payoutDB)(nil)
// ErrHeldAmount represents errors from the heldamount database.
var ErrHeldAmount = errs.Class("heldamount error")
// ErrPayout represents errors from the payouts database.
var ErrPayout = errs.Class("payout error")
// HeldAmountDBName represents the database name.
const HeldAmountDBName = "heldamount"
// heldamountDB works with node heldamount DB.
type heldamountDB struct {
// payoutDB works with node payouts DB.
type payoutDB struct {
dbContainerImpl
}
// StorePayStub inserts or updates paystub data into the db.
func (db *heldamountDB) StorePayStub(ctx context.Context, paystub heldamount.PayStub) (err error) {
func (db *payoutDB) StorePayStub(ctx context.Context, paystub payout.PayStub) (err error) {
defer mon.Task()(&ctx)(&err)
query := `INSERT OR REPLACE INTO paystubs (
@ -80,14 +80,14 @@ func (db *heldamountDB) StorePayStub(ctx context.Context, paystub heldamount.Pay
paystub.Paid,
)
return ErrHeldAmount.Wrap(err)
return ErrPayout.Wrap(err)
}
// GetPayStub retrieves paystub data for a specific satellite and period.
func (db *heldamountDB) GetPayStub(ctx context.Context, satelliteID storj.NodeID, period string) (_ *heldamount.PayStub, err error) {
func (db *payoutDB) GetPayStub(ctx context.Context, satelliteID storj.NodeID, period string) (_ *payout.PayStub, err error) {
defer mon.Task()(&ctx)(&err)
result := heldamount.PayStub{
result := payout.PayStub{
SatelliteID: satelliteID,
Period: period,
}
@ -139,16 +139,16 @@ func (db *heldamountDB) GetPayStub(ctx context.Context, satelliteID storj.NodeID
)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return nil, heldamount.ErrNoPayStubForPeriod.Wrap(err)
return nil, payout.ErrNoPayStubForPeriod.Wrap(err)
}
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
return &result, nil
}
// AllPayStubs retrieves all paystub stats from DB for specific period.
func (db *heldamountDB) AllPayStubs(ctx context.Context, period string) (_ []heldamount.PayStub, err error) {
func (db *payoutDB) AllPayStubs(ctx context.Context, period string) (_ []payout.PayStub, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT
@ -181,9 +181,9 @@ func (db *heldamountDB) AllPayStubs(ctx context.Context, period string) (_ []hel
defer func() { err = errs.Combine(err, rows.Close()) }()
var paystubList []heldamount.PayStub
var paystubList []payout.PayStub
for rows.Next() {
var paystub heldamount.PayStub
var paystub payout.PayStub
paystub.Period = period
err := rows.Scan(&paystub.SatelliteID,
@ -208,20 +208,20 @@ func (db *heldamountDB) AllPayStubs(ctx context.Context, period string) (_ []hel
&paystub.Paid,
)
if err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
paystubList = append(paystubList, paystub)
}
if err = rows.Err(); err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
return paystubList, nil
}
// SatellitesHeldbackHistory retrieves heldback history for specific satellite.
func (db *heldamountDB) SatellitesHeldbackHistory(ctx context.Context, id storj.NodeID) (_ []heldamount.AmountPeriod, err error) {
func (db *payoutDB) SatellitesHeldbackHistory(ctx context.Context, id storj.NodeID) (_ []payout.HoldForPeriod, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT
@ -236,33 +236,33 @@ func (db *heldamountDB) SatellitesHeldbackHistory(ctx context.Context, id storj.
defer func() { err = errs.Combine(err, rows.Close()) }()
var heldback []heldamount.AmountPeriod
var heldback []payout.HoldForPeriod
for rows.Next() {
var held heldamount.AmountPeriod
var held payout.HoldForPeriod
err := rows.Scan(&held.Period, &held.Held)
err := rows.Scan(&held.Period, &held.Amount)
if err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
heldback = append(heldback, held)
}
if err = rows.Err(); err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
return heldback, nil
}
// SatellitePeriods retrieves all periods for concrete satellite in which we have some heldamount data.
func (db *heldamountDB) SatellitePeriods(ctx context.Context, satelliteID storj.NodeID) (_ []string, err error) {
// SatellitePeriods retrieves all periods for concrete satellite in which we have some payouts data.
func (db *payoutDB) SatellitePeriods(ctx context.Context, satelliteID storj.NodeID) (_ []string, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT distinct period FROM paystubs WHERE satellite_id = ? ORDER BY created_at`
rows, err := db.QueryContext(ctx, query, satelliteID[:])
if err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
defer func() { err = errs.Combine(err, rows.Close()) }()
@ -272,20 +272,20 @@ func (db *heldamountDB) SatellitePeriods(ctx context.Context, satelliteID storj.
var period string
err := rows.Scan(&period)
if err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
periodList = append(periodList, period)
}
if err = rows.Err(); err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
return periodList, nil
}
// AllPeriods retrieves all periods in which we have some heldamount data.
func (db *heldamountDB) AllPeriods(ctx context.Context) (_ []string, err error) {
// AllPeriods retrieves all periods in which we have some payouts data.
func (db *payoutDB) AllPeriods(ctx context.Context) (_ []string, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT distinct period FROM paystubs ORDER BY created_at`
@ -302,20 +302,20 @@ func (db *heldamountDB) AllPeriods(ctx context.Context) (_ []string, err error)
var period string
err := rows.Scan(&period)
if err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
periodList = append(periodList, period)
}
if err = rows.Err(); err != nil {
return nil, ErrHeldAmount.Wrap(err)
return nil, ErrPayout.Wrap(err)
}
return periodList, nil
}
// StorePayment inserts or updates payment data into the db.
func (db *heldamountDB) StorePayment(ctx context.Context, payment heldamount.Payment) (err error) {
func (db *payoutDB) StorePayment(ctx context.Context, payment payout.Payment) (err error) {
defer mon.Task()(&ctx)(&err)
query := `INSERT OR REPLACE INTO payments (
@ -338,11 +338,11 @@ func (db *heldamountDB) StorePayment(ctx context.Context, payment heldamount.Pay
payment.Notes,
)
return ErrHeldAmount.Wrap(err)
return ErrPayout.Wrap(err)
}
// SatellitesDisposedHistory returns all disposed amount for specific satellite from DB.
func (db *heldamountDB) SatellitesDisposedHistory(ctx context.Context, satelliteID storj.NodeID) (_ int64, err error) {
func (db *payoutDB) SatellitesDisposedHistory(ctx context.Context, satelliteID storj.NodeID) (_ int64, err error) {
defer mon.Task()(&ctx)(&err)
query := `SELECT
@ -362,20 +362,20 @@ func (db *heldamountDB) SatellitesDisposedHistory(ctx context.Context, satellite
err := rows.Scan(&disposed)
if err != nil {
return 0, ErrHeldAmount.Wrap(err)
return 0, ErrPayout.Wrap(err)
}
totalDisposed += disposed
}
if err = rows.Err(); err != nil {
return 0, ErrHeldAmount.Wrap(err)
return 0, ErrPayout.Wrap(err)
}
return totalDisposed, nil
}
// GetReceipt retrieves receipt data for a specific satellite and period.
func (db *heldamountDB) GetReceipt(ctx context.Context, satelliteID storj.NodeID, period string) (receipt string, err error) {
func (db *payoutDB) GetReceipt(ctx context.Context, satelliteID storj.NodeID, period string) (receipt string, err error) {
defer mon.Task()(&ctx)(&err)
rowPayment := db.QueryRowContext(ctx,
@ -386,9 +386,9 @@ func (db *heldamountDB) GetReceipt(ctx context.Context, satelliteID storj.NodeID
err = rowPayment.Scan(&receipt)
if err != nil {
if errors.Is(err, sql.ErrNoRows) {
return "", heldamount.ErrNoPayStubForPeriod.Wrap(err)
return "", payout.ErrNoPayStubForPeriod.Wrap(err)
}
return "", ErrHeldAmount.Wrap(err)
return "", ErrPayout.Wrap(err)
}
return receipt, nil

View File

@ -24,13 +24,16 @@
<p class="held-history-table-container--large__info-area__months">{{ item.monthsWithNode }} month</p>
</div>
<div class="column justify-end column-2">
<p class="held-history-table-container--large__info-area__text">{{ item.firstPeriod | centsToDollars }}</p>
<p class="held-history-table-container--large__info-area__text">{{ item.holdForFirstPeriod |
centsToDollars }}</p>
</div>
<div class="column justify-end column-3">
<p class="held-history-table-container--large__info-area__text">{{ item.secondPeriod | centsToDollars }}</p>
<p class="held-history-table-container--large__info-area__text">{{ item.holdForSecondPeriod |
centsToDollars }}</p>
</div>
<div class="column justify-end column-4">
<p class="held-history-table-container--large__info-area__text">{{ item.thirdPeriod | centsToDollars }}</p>
<p class="held-history-table-container--large__info-area__text">{{ item.holdForThirdPeriod |
centsToDollars }}</p>
</div>
</div>
</div>

View File

@ -21,15 +21,18 @@
<div class="held-history-table-container--small__item__held-info" v-if="isExpanded">
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 1-3</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.firstPeriod | centsToDollars }}</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{
heldHistoryItem.holdForFirstPeriod | centsToDollars }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 4-6</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.secondPeriod | centsToDollars }}</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{
heldHistoryItem.holdForSecondPeriod | centsToDollars }}</p>
</div>
<div class="held-history-table-container--small__item__held-info__item">
<p class="held-history-table-container--small__item__held-info__item__label">Month 7-9</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{ heldHistoryItem.thirdPeriod | centsToDollars }}</p>
<p class="held-history-table-container--small__item__held-info__item__value">{{
heldHistoryItem.holdForThirdPeriod | centsToDollars }}</p>
</div>
</div>
</transition>

View File

@ -154,9 +154,9 @@ export class PayoutHttpApi implements PayoutApi {
return new SatelliteHeldHistory(
historyItem.satelliteID,
historyItem.satelliteName,
historyItem.firstPeriod,
historyItem.secondPeriod,
historyItem.thirdPeriod,
historyItem.holdForFirstPeriod,
historyItem.holdForSecondPeriod,
historyItem.holdForThirdPeriod,
historyItem.totalHeld,
historyItem.totalDisposed,
new Date(historyItem.joinedAt),

View File

@ -200,18 +200,18 @@ export class SatelliteHeldHistory {
public constructor(
public satelliteID: string = '',
public satelliteName: string = '',
public firstPeriod: number = 0,
public secondPeriod: number = 0,
public thirdPeriod: number = 0,
public holdForFirstPeriod: number = 0,
public holdForSecondPeriod: number = 0,
public holdForThirdPeriod: number = 0,
public totalHeld: number = 0,
public totalDisposed: number = 0,
public joinedAt: Date = new Date(),
) {
this.totalHeld = this.totalHeld / PRICE_DIVIDER;
this.totalDisposed = this.totalDisposed / PRICE_DIVIDER;
this.firstPeriod = this.firstPeriod / PRICE_DIVIDER;
this.secondPeriod = this.secondPeriod / PRICE_DIVIDER;
this.thirdPeriod = this.thirdPeriod / PRICE_DIVIDER;
this.holdForFirstPeriod = this.holdForFirstPeriod / PRICE_DIVIDER;
this.holdForSecondPeriod = this.holdForSecondPeriod / PRICE_DIVIDER;
this.holdForThirdPeriod = this.holdForThirdPeriod / PRICE_DIVIDER;
}
public get monthsWithNode(): number {

View File

@ -101,6 +101,7 @@ describe('mutations', (): void => {
expect(state.payoutModule.heldHistory.length).toBe(testHeldHistory.length);
expect(state.payoutModule.heldHistory[1].satelliteName).toBe(testHeldHistory[1].satelliteName);
expect(state.payoutModule.heldHistory[1].holdForFirstPeriod).toBe(testHeldHistory[1].holdForFirstPeriod);
expect(state.payoutModule.heldHistory[0].joinedAt).toBe(testJoinAt);
expect(state.payoutModule.heldHistory[2].totalHeld).toBe(785.2235);
});