diff --git a/satellite/api.go b/satellite/api.go index e6d3c614f..a776b302c 100644 --- a/satellite/api.go +++ b/satellite/api.go @@ -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()) } } diff --git a/satellite/peer.go b/satellite/peer.go index 05e192aeb..85784879b 100644 --- a/satellite/peer.go +++ b/satellite/peer.go @@ -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 diff --git a/satellite/satellitedb/database.go b/satellite/satellitedb/database.go index 1cb2137ec..9fa278246 100644 --- a/satellite/satellitedb/database.go +++ b/satellite/satellitedb/database.go @@ -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} } diff --git a/satellite/satellitedb/heldamount.go b/satellite/satellitedb/payout.go similarity index 85% rename from satellite/satellitedb/heldamount.go rename to satellite/satellitedb/payout.go index 39e5cd5fd..24c3fa140 100644 --- a/satellite/satellitedb/heldamount.go +++ b/satellite/satellitedb/payout.go @@ -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, diff --git a/satellite/heldamount/endpoint.go b/satellite/snopayout/endpoint.go similarity index 99% rename from satellite/heldamount/endpoint.go rename to satellite/snopayout/endpoint.go index eb8dc1f35..a6829a6bd 100644 --- a/satellite/heldamount/endpoint.go +++ b/satellite/snopayout/endpoint.go @@ -1,7 +1,7 @@ // Copyright (C) 2020 Storj Labs, Inc. // See LICENSE for copying information. -package heldamount +package snopayout import ( "context" diff --git a/satellite/heldamount/heldamount.go b/satellite/snopayout/payout.go similarity index 94% rename from satellite/heldamount/heldamount.go rename to satellite/snopayout/payout.go index 7b9de5977..5073cfb11 100644 --- a/satellite/heldamount/heldamount.go +++ b/satellite/snopayout/payout.go @@ -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 { diff --git a/satellite/heldamount/heldamount_test.go b/satellite/snopayout/payout_test.go similarity index 87% rename from satellite/heldamount/heldamount_test.go rename to satellite/snopayout/payout_test.go index 290f04702..c5b2c8485 100644 --- a/satellite/heldamount/heldamount_test.go +++ b/satellite/snopayout/payout_test.go @@ -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) }) }) diff --git a/storagenode/console/consoleapi/heldamount.go b/storagenode/console/consoleapi/heldamount.go deleted file mode 100644 index 6939321f2..000000000 --- a/storagenode/console/consoleapi/heldamount.go +++ /dev/null @@ -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 - } -} diff --git a/storagenode/console/consoleapi/payout.go b/storagenode/console/consoleapi/payout.go new file mode 100644 index 000000000..7a69e3c95 --- /dev/null +++ b/storagenode/console/consoleapi/payout.go @@ -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 + } +} diff --git a/storagenode/console/consoleapi/heldamount_test.go b/storagenode/console/consoleapi/payout_test.go similarity index 86% rename from storagenode/console/consoleapi/heldamount_test.go rename to storagenode/console/consoleapi/payout_test.go index 96c537c13..83270ab85 100644 --- a/storagenode/console/consoleapi/heldamount_test.go +++ b/storagenode/console/consoleapi/payout_test.go @@ -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) diff --git a/storagenode/console/consoleapi/storagenode.go b/storagenode/console/consoleapi/storagenode.go index a877de5f9..def98930a 100644 --- a/storagenode/console/consoleapi/storagenode.go +++ b/storagenode/console/consoleapi/storagenode.go @@ -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 } } diff --git a/storagenode/console/consoleapi/storagenode_test.go b/storagenode/console/consoleapi/storagenode_test.go index c4cd94fd8..33248bbac 100644 --- a/storagenode/console/consoleapi/storagenode_test.go +++ b/storagenode/console/consoleapi/storagenode_test.go @@ -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" diff --git a/storagenode/console/consoleserver/server.go b/storagenode/console/consoleserver/server.go index 8981c70c3..580908b99 100644 --- a/storagenode/console/consoleserver/server.go +++ b/storagenode/console/consoleserver/server.go @@ -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) diff --git a/storagenode/console/service.go b/storagenode/console/service.go index ffa88284b..13fff45d7 100644 --- a/storagenode/console/service.go +++ b/storagenode/console/service.go @@ -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" diff --git a/storagenode/nodestats/cache.go b/storagenode/nodestats/cache.go index cb6d5fed8..d3d4731ac 100644 --- a/storagenode/nodestats/cache.go +++ b/storagenode/nodestats/cache.go @@ -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 } } diff --git a/storagenode/heldamount/db_test.go b/storagenode/payout/db_test.go similarity index 83% rename from storagenode/heldamount/db_test.go rename to storagenode/payout/db_test.go index 1e6716832..2416ce460 100644 --- a/storagenode/heldamount/db_test.go +++ b/storagenode/payout/db_test.go @@ -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", diff --git a/storagenode/heldamount/endpoint.go b/storagenode/payout/endpoint.go similarity index 92% rename from storagenode/heldamount/endpoint.go rename to storagenode/payout/endpoint.go index b6b292c31..d8d10a017 100644 --- a/storagenode/heldamount/endpoint.go +++ b/storagenode/payout/endpoint.go @@ -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) diff --git a/storagenode/estimatedpayout/estimatedpayout.go b/storagenode/payout/estimatedpayout/estimatedpayout.go similarity index 100% rename from storagenode/estimatedpayout/estimatedpayout.go rename to storagenode/payout/estimatedpayout/estimatedpayout.go diff --git a/storagenode/estimatedpayout/service.go b/storagenode/payout/estimatedpayout/service.go similarity index 92% rename from storagenode/estimatedpayout/service.go rename to storagenode/payout/estimatedpayout/service.go index 50ad35f2c..d5f1c500e 100644 --- a/storagenode/estimatedpayout/service.go +++ b/storagenode/payout/estimatedpayout/service.go @@ -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 -} diff --git a/storagenode/heldamount/heldamount.go b/storagenode/payout/payout.go similarity index 63% rename from storagenode/heldamount/heldamount.go rename to storagenode/payout/payout.go index 96cc990c6..886bf22f2 100644 --- a/storagenode/heldamount/heldamount.go +++ b/storagenode/payout/payout.go @@ -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 diff --git a/storagenode/heldamount/service.go b/storagenode/payout/service.go similarity index 66% rename from storagenode/heldamount/service.go rename to storagenode/payout/service.go index 150f388e7..386bb58ab 100644 --- a/storagenode/heldamount/service.go +++ b/storagenode/payout/service.go @@ -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 } diff --git a/storagenode/heldamount/service_test.go b/storagenode/payout/service_test.go similarity index 98% rename from storagenode/heldamount/service_test.go rename to storagenode/payout/service_test.go index d9929280d..211a66369 100644 --- a/storagenode/heldamount/service_test.go +++ b/storagenode/payout/service_test.go @@ -1,7 +1,7 @@ // Copyright (C) 2020 Storj Labs, Inc. // See LICENSE for copying information. -package heldamount +package payout import ( "testing" diff --git a/storagenode/peer.go b/storagenode/peer.go index db1f81f65..14aeab7f8 100644 --- a/storagenode/peer.go +++ b/storagenode/peer.go @@ -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{ diff --git a/storagenode/storagenodedb/database.go b/storagenode/storagenodedb/database.go index 767b5522a..825071722 100644 --- a/storagenode/storagenodedb/database.go +++ b/storagenode/storagenodedb/database.go @@ -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 := ¬ificationDB{} - 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 := ¬ificationDB{} - 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{ diff --git a/storagenode/storagenodedb/heldamount.go b/storagenode/storagenodedb/payout.go similarity index 73% rename from storagenode/storagenodedb/heldamount.go rename to storagenode/storagenodedb/payout.go index 71362b264..f30d3abb5 100644 --- a/storagenode/storagenodedb/heldamount.go +++ b/storagenode/storagenodedb/payout.go @@ -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 diff --git a/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTable.vue b/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTable.vue index e81c88e60..8d9c3ab4d 100644 --- a/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTable.vue +++ b/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTable.vue @@ -24,13 +24,16 @@

{{ item.monthsWithNode }} month

-

{{ item.firstPeriod | centsToDollars }}

+

{{ item.holdForFirstPeriod | + centsToDollars }}

-

{{ item.secondPeriod | centsToDollars }}

+

{{ item.holdForSecondPeriod | + centsToDollars }}

-

{{ item.thirdPeriod | centsToDollars }}

+

{{ item.holdForThirdPeriod | + centsToDollars }}

diff --git a/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTableItemSmall.vue b/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTableItemSmall.vue index 41413b526..830f907d7 100644 --- a/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTableItemSmall.vue +++ b/web/storagenode/src/app/components/payments/HeldHistoryMonthlyBreakdownTableItemSmall.vue @@ -21,15 +21,18 @@

Month 1-3

-

{{ heldHistoryItem.firstPeriod | centsToDollars }}

+

{{ + heldHistoryItem.holdForFirstPeriod | centsToDollars }}

Month 4-6

-

{{ heldHistoryItem.secondPeriod | centsToDollars }}

+

{{ + heldHistoryItem.holdForSecondPeriod | centsToDollars }}

Month 7-9

-

{{ heldHistoryItem.thirdPeriod | centsToDollars }}

+

{{ + heldHistoryItem.holdForThirdPeriod | centsToDollars }}

diff --git a/web/storagenode/src/storagenode/api/payout.ts b/web/storagenode/src/storagenode/api/payout.ts index 54fcea460..c7bc8c182 100644 --- a/web/storagenode/src/storagenode/api/payout.ts +++ b/web/storagenode/src/storagenode/api/payout.ts @@ -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), diff --git a/web/storagenode/src/storagenode/payouts/payouts.ts b/web/storagenode/src/storagenode/payouts/payouts.ts index e8f2374c5..798a6e3e5 100644 --- a/web/storagenode/src/storagenode/payouts/payouts.ts +++ b/web/storagenode/src/storagenode/payouts/payouts.ts @@ -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 { diff --git a/web/storagenode/tests/unit/store/payout.spec.ts b/web/storagenode/tests/unit/store/payout.spec.ts index 8a172e8a9..a537aef0e 100644 --- a/web/storagenode/tests/unit/store/payout.spec.ts +++ b/web/storagenode/tests/unit/store/payout.spec.ts @@ -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); });