2020-03-10 20:42:11 +00:00
|
|
|
// Copyright (C) 2020 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package compensation
|
|
|
|
|
|
|
|
import (
|
|
|
|
"io"
|
|
|
|
|
|
|
|
"storj.io/common/strictcsv"
|
|
|
|
"storj.io/storj/private/currency"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Invoice holds the calculations for the amount required to pay to a node
|
|
|
|
// for a given pay period.
|
|
|
|
type Invoice struct {
|
2021-01-26 20:28:35 +00:00
|
|
|
Period Period `csv:"period"` // The payment period
|
|
|
|
NodeID NodeID `csv:"node-id"` // The node ID
|
|
|
|
NodeCreatedAt UTCDate `csv:"node-created-at"` // When the node was created
|
|
|
|
NodeDisqualified *UTCDate `csv:"node-disqualified"` // When and if the node was disqualified
|
|
|
|
NodeGracefulExit *UTCDate `csv:"node-gracefulexit"` // When and if the node finished a graceful exit
|
|
|
|
NodeWallet string `csv:"node-wallet"` // The node's wallet address
|
|
|
|
NodeWalletFeatures WalletFeatures `csv:"node-wallet-features"` // The node's wallet features
|
|
|
|
NodeAddress string `csv:"node-address"` // The node's TODO
|
|
|
|
NodeLastIP string `csv:"node-last-ip"` // The last known ip the node had
|
|
|
|
Codes Codes `csv:"codes"` // Any codes providing context to the invoice
|
|
|
|
UsageAtRest float64 `csv:"usage-at-rest"` // Byte-hours provided during the payment period
|
|
|
|
UsageGet int64 `csv:"usage-get"` // Number of bytes served in GET requests
|
|
|
|
UsagePut int64 `csv:"usage-put"` // Number of bytes served in PUT requests
|
|
|
|
UsageGetRepair int64 `csv:"usage-get-repair"` // Number of bytes served in GET_REPAIR requests
|
|
|
|
UsagePutRepair int64 `csv:"usage-put-repair"` // Number of bytes served in PUT_REPAIR requests
|
|
|
|
UsageGetAudit int64 `csv:"usage-get-audit"` // Number of bytes served in GET_AUDIT requests
|
|
|
|
CompAtRest currency.MicroUnit `csv:"comp-at-rest"` // Compensation for usage-at-rest
|
|
|
|
CompGet currency.MicroUnit `csv:"comp-get"` // Compensation for usage-get
|
|
|
|
CompPut currency.MicroUnit `csv:"comp-put"` // Compensation for usage-put
|
|
|
|
CompGetRepair currency.MicroUnit `csv:"comp-get-repair"` // Compensation for usage-get-repair
|
|
|
|
CompPutRepair currency.MicroUnit `csv:"comp-put-repair"` // Compensation for usage-put-repair
|
|
|
|
CompGetAudit currency.MicroUnit `csv:"comp-get-audit"` // Compensation for usage-get-audit
|
|
|
|
SurgePercent int64 `csv:"surge-percent"` // Surge percent used to calculate compensation, or 0 if no surge
|
|
|
|
Owed currency.MicroUnit `csv:"owed"` // Amount we intend to pay to the node (sum(comp-*) - held + disposed)
|
|
|
|
Held currency.MicroUnit `csv:"held"` // Amount held from sum(comp-*) for this period
|
|
|
|
Disposed currency.MicroUnit `csv:"disposed"` // Amount of owed that is due to graceful-exit or held period ending
|
|
|
|
TotalHeld currency.MicroUnit `csv:"total-held"` // Total amount ever held from the node
|
|
|
|
TotalDisposed currency.MicroUnit `csv:"total-disposed"` // Total amount ever disposed to the node
|
|
|
|
TotalPaid currency.MicroUnit `csv:"total-paid"` // Total amount ever paid to the node (but not necessarily dispensed)
|
|
|
|
TotalDistributed currency.MicroUnit `csv:"total-distributed"` // Total amount ever distributed to the node (always less than or equal to paid)
|
2020-03-10 20:42:11 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// MergeNodeInfo updates the fields representing the node information into the invoice.
|
|
|
|
func (invoice *Invoice) MergeNodeInfo(nodeInfo NodeInfo) error {
|
|
|
|
if invoice.NodeID != NodeID(nodeInfo.ID) {
|
|
|
|
return Error.New("node ID mismatch (invoice=%q nodeinfo=%q)", invoice.NodeID, nodeInfo.ID)
|
|
|
|
}
|
|
|
|
invoice.NodeCreatedAt = UTCDate(nodeInfo.CreatedAt)
|
|
|
|
invoice.NodeDisqualified = (*UTCDate)(nodeInfo.Disqualified)
|
|
|
|
invoice.NodeGracefulExit = (*UTCDate)(nodeInfo.GracefulExit)
|
|
|
|
invoice.UsageAtRest = nodeInfo.UsageAtRest
|
|
|
|
invoice.UsageGet = nodeInfo.UsageGet
|
|
|
|
invoice.UsagePut = nodeInfo.UsagePut
|
|
|
|
invoice.UsageGetRepair = nodeInfo.UsageGetRepair
|
|
|
|
invoice.UsagePutRepair = nodeInfo.UsagePutRepair
|
|
|
|
invoice.UsageGetAudit = nodeInfo.UsageGetAudit
|
|
|
|
invoice.TotalHeld = nodeInfo.TotalHeld
|
|
|
|
invoice.TotalDisposed = nodeInfo.TotalDisposed
|
2021-01-27 18:53:16 +00:00
|
|
|
invoice.TotalPaid = nodeInfo.TotalPaid
|
|
|
|
invoice.TotalDistributed = nodeInfo.TotalDistributed
|
2020-03-10 20:42:11 +00:00
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// MergeStatement updates the fields representing the calculation of the payment amounts
|
|
|
|
// into the invoice.
|
|
|
|
func (invoice *Invoice) MergeStatement(statement Statement) error {
|
|
|
|
if invoice.NodeID != NodeID(statement.NodeID) {
|
|
|
|
return Error.New("node ID mismatch (invoice=%q statement=%q)", invoice.NodeID, statement.NodeID)
|
|
|
|
}
|
|
|
|
invoice.Codes = statement.Codes
|
|
|
|
invoice.CompAtRest = statement.AtRest
|
|
|
|
invoice.CompGet = statement.Get
|
|
|
|
invoice.CompPut = statement.Put
|
|
|
|
invoice.CompGetRepair = statement.GetRepair
|
|
|
|
invoice.CompPutRepair = statement.PutRepair
|
|
|
|
invoice.CompGetAudit = statement.GetAudit
|
|
|
|
invoice.SurgePercent = statement.SurgePercent
|
|
|
|
invoice.Owed = statement.Owed
|
|
|
|
invoice.Held = statement.Held
|
|
|
|
invoice.Disposed = statement.Disposed
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// ReadInvoices reads a collection of Invoice values in CSV form.
|
|
|
|
func ReadInvoices(r io.Reader) ([]Invoice, error) {
|
|
|
|
var invoices []Invoice
|
|
|
|
if err := strictcsv.Read(r, &invoices); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
return invoices, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// WriteInvoices writes a collection of Invoice values in CSV form.
|
|
|
|
func WriteInvoices(w io.Writer, invoices []Invoice) error {
|
|
|
|
return strictcsv.Write(w, invoices)
|
|
|
|
}
|