storj/satellite/payments/storjscan/service_test.go

357 lines
12 KiB
Go
Raw Normal View History

// Copyright (C) 2022 Storj Labs, Inc.
// See LICENSE for copying information.
package storjscan_test
import (
"testing"
"time"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
"go.uber.org/zap/zaptest"
"storj.io/common/currency"
"storj.io/common/testcontext"
"storj.io/common/testrand"
"storj.io/storj/private/blockchain"
"storj.io/storj/satellite"
"storj.io/storj/satellite/payments"
"storj.io/storj/satellite/payments/storjscan"
"storj.io/storj/satellite/payments/storjscan/blockchaintest"
"storj.io/storj/satellite/satellitedb/satellitedbtest"
)
func TestServicePayments(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
paymentsDB := db.StorjscanPayments()
now := time.Now().Truncate(time.Second).UTC()
wallet1 := blockchaintest.NewAddress()
wallet2 := blockchaintest.NewAddress()
walletPayments := []payments.WalletPayment{
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(100, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 0,
Transaction: blockchaintest.NewHash(),
LogIndex: 0,
Timestamp: now,
},
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(100, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 0,
Transaction: blockchaintest.NewHash(),
LogIndex: 1,
Timestamp: now,
},
{
From: blockchaintest.NewAddress(),
To: wallet2,
TokenValue: currency.AmountFromBaseUnits(100, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 0,
Transaction: blockchaintest.NewHash(),
LogIndex: 2,
Timestamp: now,
},
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(200, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusPending,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 1,
Transaction: blockchaintest.NewHash(),
LogIndex: 0,
Timestamp: now.Add(15 * time.Second),
},
}
var cachedPayments []storjscan.CachedPayment
for _, pmnt := range walletPayments {
cachedPayments = append(cachedPayments, storjscan.CachedPayment{
From: pmnt.From,
To: pmnt.To,
TokenValue: pmnt.TokenValue,
USDValue: pmnt.USDValue,
Status: pmnt.Status,
BlockHash: pmnt.BlockHash,
BlockNumber: pmnt.BlockNumber,
Transaction: pmnt.Transaction,
LogIndex: pmnt.LogIndex,
Timestamp: pmnt.Timestamp,
})
}
err := paymentsDB.InsertBatch(ctx, cachedPayments)
require.NoError(t, err)
service := storjscan.NewService(zaptest.NewLogger(t), db.Wallets(), paymentsDB, nil, 15, 10)
t.Run("wallet 1", func(t *testing.T) {
expected := []payments.WalletPayment{walletPayments[3], walletPayments[1], walletPayments[0]}
actual, err := service.Payments(ctx, wallet1, 5, 0)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("wallet 1 from offset", func(t *testing.T) {
expected := []payments.WalletPayment{walletPayments[1], walletPayments[0]}
actual, err := service.Payments(ctx, wallet1, 5, 1)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("wallet 1 with limit", func(t *testing.T) {
expected := []payments.WalletPayment{walletPayments[3], walletPayments[1]}
actual, err := service.Payments(ctx, wallet1, 2, 0)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
t.Run("wallet 2", func(t *testing.T) {
expected := []payments.WalletPayment{walletPayments[2]}
actual, err := service.Payments(ctx, wallet2, 1, 0)
require.NoError(t, err)
require.Equal(t, expected, actual)
})
})
}
func TestServiceWallets(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
userID1 := testrand.UUID()
userID2 := testrand.UUID()
userID3 := testrand.UUID()
walletAddress1, err := blockchain.BytesToAddress(testrand.Bytes(20))
require.NoError(t, err)
walletAddress2, err := blockchain.BytesToAddress(testrand.Bytes(20))
require.NoError(t, err)
walletAddress3, err := blockchain.BytesToAddress(testrand.Bytes(20))
require.NoError(t, err)
err = db.Wallets().Add(ctx, userID1, walletAddress1)
require.NoError(t, err)
err = db.Wallets().Add(ctx, userID2, walletAddress2)
require.NoError(t, err)
err = db.Wallets().Add(ctx, userID3, walletAddress3)
require.NoError(t, err)
service := storjscan.NewService(zaptest.NewLogger(t), db.Wallets(), db.StorjscanPayments(), nil, 15, 10)
t.Run("get Wallet", func(t *testing.T) {
actual, err := service.Get(ctx, userID1)
require.NoError(t, err)
require.Equal(t, walletAddress1, actual)
actual, err = service.Get(ctx, userID2)
require.NoError(t, err)
require.Equal(t, walletAddress2, actual)
actual, err = service.Get(ctx, userID3)
require.NoError(t, err)
require.Equal(t, walletAddress3, actual)
})
t.Run("claim Wallet already assigned", func(t *testing.T) {
actual, err := service.Get(ctx, userID1)
require.NoError(t, err)
require.Equal(t, walletAddress1, actual)
actual, err = service.Claim(ctx, userID1)
require.NoError(t, err)
require.Equal(t, walletAddress1, actual)
})
})
}
func TestListPayments(t *testing.T) {
satellitedbtest.Run(t, func(ctx *testcontext.Context, t *testing.T, db satellite.DB) {
paymentsDB := db.StorjscanPayments()
now := time.Now().Truncate(time.Second).UTC()
wallet1 := blockchaintest.NewAddress()
walletPaymentsBatch1 := []payments.WalletPayment{
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(100, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 0,
Transaction: blockchaintest.NewHash(),
LogIndex: 1,
Timestamp: now,
},
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(100, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 0,
Transaction: blockchaintest.NewHash(),
LogIndex: 2,
Timestamp: now,
},
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(100, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 0,
Transaction: blockchaintest.NewHash(),
LogIndex: 3,
Timestamp: now,
},
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(200, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 1,
Transaction: blockchaintest.NewHash(),
LogIndex: 0,
Timestamp: now.Add(15 * time.Second),
},
}
var cachedPayments1 []storjscan.CachedPayment
for _, pmnt := range walletPaymentsBatch1 {
cachedPayments1 = append(cachedPayments1, storjscan.CachedPayment{
From: pmnt.From,
To: pmnt.To,
TokenValue: pmnt.TokenValue,
USDValue: pmnt.USDValue,
Status: pmnt.Status,
BlockHash: pmnt.BlockHash,
BlockNumber: pmnt.BlockNumber,
Transaction: pmnt.Transaction,
LogIndex: pmnt.LogIndex,
Timestamp: pmnt.Timestamp,
})
}
err := paymentsDB.InsertBatch(ctx, cachedPayments1)
require.NoError(t, err)
confirmedPayments, err := paymentsDB.ListConfirmed(ctx, 0, 0)
require.NoError(t, err)
require.Equal(t, len(cachedPayments1), len(confirmedPayments))
for _, act := range confirmedPayments {
for _, exp := range cachedPayments1 {
if act.BlockHash == exp.BlockHash && act.LogIndex == exp.LogIndex {
compareTransactions(t, exp, act)
break
}
}
}
// these payments should be picked since it's same block number, but has a higher Log index.
walletPaymentsBatch2 := []payments.WalletPayment{
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(100, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 1,
Transaction: blockchaintest.NewHash(),
LogIndex: 2,
Timestamp: now,
},
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(200, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 1,
Transaction: blockchaintest.NewHash(),
LogIndex: 3,
Timestamp: now.Add(15 * time.Second),
},
{
From: blockchaintest.NewAddress(),
To: wallet1,
TokenValue: currency.AmountFromBaseUnits(200, currency.StorjToken),
USDValue: currency.AmountFromBaseUnits(100, currency.USDollarsMicro),
Status: payments.PaymentStatusConfirmed,
BlockHash: blockchaintest.NewHash(),
BlockNumber: 2,
Transaction: blockchaintest.NewHash(),
LogIndex: 0,
Timestamp: now.Add(15 * time.Second),
},
}
var cachedPayments2 []storjscan.CachedPayment
for _, pmnt := range walletPaymentsBatch2 {
cachedPayments2 = append(cachedPayments2, storjscan.CachedPayment{
From: pmnt.From,
To: pmnt.To,
TokenValue: pmnt.TokenValue,
USDValue: pmnt.USDValue,
Status: pmnt.Status,
BlockHash: pmnt.BlockHash,
BlockNumber: pmnt.BlockNumber,
Transaction: pmnt.Transaction,
LogIndex: pmnt.LogIndex,
Timestamp: pmnt.Timestamp,
})
}
err = paymentsDB.InsertBatch(ctx, cachedPayments2)
require.NoError(t, err)
confirmedPayments, err = paymentsDB.ListConfirmed(ctx, 1, 1)
require.NoError(t, err)
require.Equal(t, len(cachedPayments2), len(confirmedPayments))
for _, act := range confirmedPayments {
for _, exp := range cachedPayments2 {
if act.BlockHash == exp.BlockHash && act.LogIndex == exp.LogIndex {
compareTransactions(t, exp, act)
break
}
}
}
})
}
// compareTransactions is a helper method to compare tx used to create db entry,
// with the tx returned from the db.
func compareTransactions(t *testing.T, exp, act storjscan.CachedPayment) {
assert.Equal(t, exp.From, act.From)
assert.Equal(t, exp.To, act.To)
assert.Equal(t, exp.TokenValue, act.TokenValue)
assert.Equal(t, exp.USDValue, act.USDValue)
assert.Equal(t, exp.Status, act.Status)
assert.Equal(t, exp.BlockHash, act.BlockHash)
assert.Equal(t, exp.BlockNumber, act.BlockNumber)
assert.Equal(t, exp.Transaction, act.Transaction)
assert.Equal(t, exp.LogIndex, act.LogIndex)
assert.WithinDuration(t, exp.Timestamp, act.Timestamp, time.Microsecond) // database timestamps use microsecond precision
}