satellite/console: add STORJ bonus to transactions
This change includes STORJ bonuses to the list of transactions returned by the /wallet/payments endpoint. Issue: https://github.com/storj/storj/issues/5755 Change-Id: Icc95c2cb9dd9fc5ee7a373e68c1cf8a991e1aa58
This commit is contained in:
parent
c48bd81e5f
commit
4791a6422d
@ -4,8 +4,10 @@
|
||||
package console
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"math"
|
||||
@ -3082,6 +3084,10 @@ func (payment Payments) WalletPayments(ctx context.Context) (_ WalletPayments, e
|
||||
if err != nil {
|
||||
return WalletPayments{}, Error.Wrap(err)
|
||||
}
|
||||
txns, err := payment.service.billing.ListSource(ctx, user.ID, billing.StorjScanBonusSource)
|
||||
if err != nil {
|
||||
return WalletPayments{}, Error.Wrap(err)
|
||||
}
|
||||
|
||||
var paymentInfos []PaymentInfo
|
||||
for _, walletPayment := range walletPayments {
|
||||
@ -3107,6 +3113,25 @@ func (payment Payments) WalletPayments(ctx context.Context) (_ WalletPayments, e
|
||||
Timestamp: txInfo.CreatedAt.UTC(),
|
||||
})
|
||||
}
|
||||
for _, txn := range txns {
|
||||
var meta struct {
|
||||
ReferenceID string
|
||||
LogIndex int
|
||||
}
|
||||
err = json.NewDecoder(bytes.NewReader(txn.Metadata)).Decode(&meta)
|
||||
if err != nil {
|
||||
return WalletPayments{}, Error.Wrap(err)
|
||||
}
|
||||
paymentInfos = append(paymentInfos, PaymentInfo{
|
||||
ID: fmt.Sprintf("%s#%d", meta.ReferenceID, meta.LogIndex),
|
||||
Type: txn.Source,
|
||||
Wallet: address.Hex(),
|
||||
Amount: txn.Amount,
|
||||
Status: string(txn.Status),
|
||||
Link: EtherscanURL(meta.ReferenceID),
|
||||
Timestamp: txn.Timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
return WalletPayments{
|
||||
Payments: paymentInfos,
|
||||
|
@ -4,6 +4,7 @@
|
||||
package console_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"database/sql"
|
||||
"encoding/json"
|
||||
@ -30,6 +31,7 @@ import (
|
||||
"storj.io/storj/satellite/buckets"
|
||||
"storj.io/storj/satellite/console"
|
||||
"storj.io/storj/satellite/payments"
|
||||
"storj.io/storj/satellite/payments/billing"
|
||||
"storj.io/storj/satellite/payments/coinpayments"
|
||||
"storj.io/storj/satellite/payments/storjscan"
|
||||
"storj.io/storj/satellite/payments/storjscan/blockchaintest"
|
||||
@ -1485,6 +1487,12 @@ func TestDeleteAllSessionsByUserIDExcept(t *testing.T) {
|
||||
func TestPaymentsWalletPayments(t *testing.T) {
|
||||
testplanet.Run(t, testplanet.Config{
|
||||
SatelliteCount: 1, StorageNodeCount: 0, UplinkCount: 0,
|
||||
Reconfigure: testplanet.Reconfigure{
|
||||
Satellite: func(log *zap.Logger, index int, config *satellite.Config) {
|
||||
config.Payments.BillingConfig.DisableLoop = false
|
||||
config.Payments.BonusRate = 10
|
||||
},
|
||||
},
|
||||
}, func(t *testing.T, ctx *testcontext.Context, planet *testplanet.Planet) {
|
||||
sat := planet.Satellites[0]
|
||||
now := time.Now().Truncate(time.Second).UTC()
|
||||
@ -1574,6 +1582,37 @@ func TestPaymentsWalletPayments(t *testing.T) {
|
||||
})
|
||||
}
|
||||
|
||||
// get billing chore to insert bonuses for transactions.
|
||||
sat.Core.Payments.BillingChore.TransactionCycle.TriggerWait()
|
||||
|
||||
txns, err := sat.DB.Billing().ListSource(ctx, user.ID, billing.StorjScanBonusSource)
|
||||
require.NoError(t, err)
|
||||
require.NotEmpty(t, txns)
|
||||
|
||||
for _, txn := range txns {
|
||||
if txn.Source != billing.StorjScanBonusSource {
|
||||
continue
|
||||
}
|
||||
var meta struct {
|
||||
ReferenceID string
|
||||
Wallet string
|
||||
LogIndex int
|
||||
}
|
||||
err = json.NewDecoder(bytes.NewReader(txn.Metadata)).Decode(&meta)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
expected = append(expected, console.PaymentInfo{
|
||||
ID: fmt.Sprintf("%s#%d", meta.ReferenceID, meta.LogIndex),
|
||||
Type: txn.Source,
|
||||
Wallet: meta.Wallet,
|
||||
Amount: txn.Amount,
|
||||
Status: string(txn.Status),
|
||||
Link: console.EtherscanURL(meta.ReferenceID),
|
||||
Timestamp: txn.Timestamp,
|
||||
})
|
||||
}
|
||||
|
||||
walletPayments, err := sat.API.Console.Service.Payments().WalletPayments(reqCtx)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expected, walletPayments.Payments)
|
||||
|
@ -65,6 +65,8 @@ type TransactionsDB interface {
|
||||
LastTransaction(ctx context.Context, txSource string, txType TransactionType) (time.Time, []byte, error)
|
||||
// List returns all transactions for the specified user.
|
||||
List(ctx context.Context, userID uuid.UUID) ([]Transaction, error)
|
||||
// ListSource returns all transactions for the specified user and source.
|
||||
ListSource(ctx context.Context, userID uuid.UUID, txSource string) ([]Transaction, error)
|
||||
// GetBalance returns the current usable balance for the specified user.
|
||||
GetBalance(ctx context.Context, userID uuid.UUID) (currency.Amount, error)
|
||||
}
|
||||
|
@ -235,6 +235,25 @@ func (db billingDB) List(ctx context.Context, userID uuid.UUID) (txs []billing.T
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
func (db billingDB) ListSource(ctx context.Context, userID uuid.UUID, txSource string) (txs []billing.Transaction, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
dbxTXs, err := db.db.All_BillingTransaction_By_UserId_And_Source_OrderBy_Desc_Timestamp(ctx,
|
||||
dbx.BillingTransaction_UserId(userID[:]), dbx.BillingTransaction_Source(txSource))
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
|
||||
for _, dbxTX := range dbxTXs {
|
||||
tx, err := fromDBXBillingTransaction(dbxTX)
|
||||
if err != nil {
|
||||
return nil, Error.Wrap(err)
|
||||
}
|
||||
txs = append(txs, *tx)
|
||||
}
|
||||
|
||||
return txs, nil
|
||||
}
|
||||
|
||||
func (db billingDB) GetBalance(ctx context.Context, userID uuid.UUID) (_ currency.Amount, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
dbxBilling, err := db.db.Get_BillingBalance_Balance_By_UserId(ctx,
|
||||
|
@ -110,6 +110,13 @@ read all (
|
||||
orderby desc billing_transaction.timestamp
|
||||
)
|
||||
|
||||
read all (
|
||||
select billing_transaction
|
||||
where billing_transaction.user_id = ?
|
||||
where billing_transaction.source = ?
|
||||
orderby desc billing_transaction.timestamp
|
||||
)
|
||||
|
||||
read first (
|
||||
select billing_transaction
|
||||
where billing_transaction.source = ?
|
||||
|
@ -14005,6 +14005,52 @@ func (obj *pgxImpl) All_BillingTransaction_By_UserId_OrderBy_Desc_Timestamp(ctx
|
||||
|
||||
}
|
||||
|
||||
func (obj *pgxImpl) All_BillingTransaction_By_UserId_And_Source_OrderBy_Desc_Timestamp(ctx context.Context,
|
||||
billing_transaction_user_id BillingTransaction_UserId_Field,
|
||||
billing_transaction_source BillingTransaction_Source_Field) (
|
||||
rows []*BillingTransaction, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("SELECT billing_transactions.id, billing_transactions.user_id, billing_transactions.amount, billing_transactions.currency, billing_transactions.description, billing_transactions.source, billing_transactions.status, billing_transactions.type, billing_transactions.metadata, billing_transactions.timestamp, billing_transactions.created_at FROM billing_transactions WHERE billing_transactions.user_id = ? AND billing_transactions.source = ? ORDER BY billing_transactions.timestamp DESC")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, billing_transaction_user_id.value(), billing_transaction_source.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
for {
|
||||
rows, err = func() (rows []*BillingTransaction, err error) {
|
||||
__rows, err := obj.driver.QueryContext(ctx, __stmt, __values...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer __rows.Close()
|
||||
|
||||
for __rows.Next() {
|
||||
billing_transaction := &BillingTransaction{}
|
||||
err = __rows.Scan(&billing_transaction.Id, &billing_transaction.UserId, &billing_transaction.Amount, &billing_transaction.Currency, &billing_transaction.Description, &billing_transaction.Source, &billing_transaction.Status, &billing_transaction.Type, &billing_transaction.Metadata, &billing_transaction.Timestamp, &billing_transaction.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows = append(rows, billing_transaction)
|
||||
}
|
||||
if err := __rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}()
|
||||
if err != nil {
|
||||
if obj.shouldRetry(err) {
|
||||
continue
|
||||
}
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (obj *pgxImpl) First_BillingTransaction_By_Source_And_Type_OrderBy_Desc_CreatedAt(ctx context.Context,
|
||||
billing_transaction_source BillingTransaction_Source_Field,
|
||||
billing_transaction_type BillingTransaction_Type_Field) (
|
||||
@ -21818,6 +21864,52 @@ func (obj *pgxcockroachImpl) All_BillingTransaction_By_UserId_OrderBy_Desc_Times
|
||||
|
||||
}
|
||||
|
||||
func (obj *pgxcockroachImpl) All_BillingTransaction_By_UserId_And_Source_OrderBy_Desc_Timestamp(ctx context.Context,
|
||||
billing_transaction_user_id BillingTransaction_UserId_Field,
|
||||
billing_transaction_source BillingTransaction_Source_Field) (
|
||||
rows []*BillingTransaction, err error) {
|
||||
defer mon.Task()(&ctx)(&err)
|
||||
|
||||
var __embed_stmt = __sqlbundle_Literal("SELECT billing_transactions.id, billing_transactions.user_id, billing_transactions.amount, billing_transactions.currency, billing_transactions.description, billing_transactions.source, billing_transactions.status, billing_transactions.type, billing_transactions.metadata, billing_transactions.timestamp, billing_transactions.created_at FROM billing_transactions WHERE billing_transactions.user_id = ? AND billing_transactions.source = ? ORDER BY billing_transactions.timestamp DESC")
|
||||
|
||||
var __values []interface{}
|
||||
__values = append(__values, billing_transaction_user_id.value(), billing_transaction_source.value())
|
||||
|
||||
var __stmt = __sqlbundle_Render(obj.dialect, __embed_stmt)
|
||||
obj.logStmt(__stmt, __values...)
|
||||
|
||||
for {
|
||||
rows, err = func() (rows []*BillingTransaction, err error) {
|
||||
__rows, err := obj.driver.QueryContext(ctx, __stmt, __values...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer __rows.Close()
|
||||
|
||||
for __rows.Next() {
|
||||
billing_transaction := &BillingTransaction{}
|
||||
err = __rows.Scan(&billing_transaction.Id, &billing_transaction.UserId, &billing_transaction.Amount, &billing_transaction.Currency, &billing_transaction.Description, &billing_transaction.Source, &billing_transaction.Status, &billing_transaction.Type, &billing_transaction.Metadata, &billing_transaction.Timestamp, &billing_transaction.CreatedAt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
rows = append(rows, billing_transaction)
|
||||
}
|
||||
if err := __rows.Err(); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return rows, nil
|
||||
}()
|
||||
if err != nil {
|
||||
if obj.shouldRetry(err) {
|
||||
continue
|
||||
}
|
||||
return nil, obj.makeErr(err)
|
||||
}
|
||||
return rows, nil
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (obj *pgxcockroachImpl) First_BillingTransaction_By_Source_And_Type_OrderBy_Desc_CreatedAt(ctx context.Context,
|
||||
billing_transaction_source BillingTransaction_Source_Field,
|
||||
billing_transaction_type BillingTransaction_Type_Field) (
|
||||
@ -27473,6 +27565,17 @@ func (rx *Rx) All_AccountFreezeEvent_By_UserId(ctx context.Context,
|
||||
return tx.All_AccountFreezeEvent_By_UserId(ctx, account_freeze_event_user_id)
|
||||
}
|
||||
|
||||
func (rx *Rx) All_BillingTransaction_By_UserId_And_Source_OrderBy_Desc_Timestamp(ctx context.Context,
|
||||
billing_transaction_user_id BillingTransaction_UserId_Field,
|
||||
billing_transaction_source BillingTransaction_Source_Field) (
|
||||
rows []*BillingTransaction, err error) {
|
||||
var tx *Tx
|
||||
if tx, err = rx.getTx(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
return tx.All_BillingTransaction_By_UserId_And_Source_OrderBy_Desc_Timestamp(ctx, billing_transaction_user_id, billing_transaction_source)
|
||||
}
|
||||
|
||||
func (rx *Rx) All_BillingTransaction_By_UserId_OrderBy_Desc_Timestamp(ctx context.Context,
|
||||
billing_transaction_user_id BillingTransaction_UserId_Field) (
|
||||
rows []*BillingTransaction, err error) {
|
||||
@ -29467,6 +29570,11 @@ type Methods interface {
|
||||
account_freeze_event_user_id AccountFreezeEvent_UserId_Field) (
|
||||
rows []*AccountFreezeEvent, err error)
|
||||
|
||||
All_BillingTransaction_By_UserId_And_Source_OrderBy_Desc_Timestamp(ctx context.Context,
|
||||
billing_transaction_user_id BillingTransaction_UserId_Field,
|
||||
billing_transaction_source BillingTransaction_Source_Field) (
|
||||
rows []*BillingTransaction, err error)
|
||||
|
||||
All_BillingTransaction_By_UserId_OrderBy_Desc_Timestamp(ctx context.Context,
|
||||
billing_transaction_user_id BillingTransaction_UserId_Field) (
|
||||
rows []*BillingTransaction, err error)
|
||||
|
Loading…
Reference in New Issue
Block a user