2022-06-01 22:59:47 +01:00
|
|
|
// Copyright (C) 2022 Storj Labs, Inc.
|
|
|
|
// See LICENSE for copying information.
|
|
|
|
|
|
|
|
package storjscan_test
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
2022-06-17 00:29:31 +01:00
|
|
|
"github.com/stretchr/testify/assert"
|
2022-06-01 22:59:47 +01:00
|
|
|
"github.com/stretchr/testify/require"
|
|
|
|
"go.uber.org/zap/zaptest"
|
|
|
|
|
|
|
|
"storj.io/common/testcontext"
|
2022-08-15 15:41:19 +01:00
|
|
|
"storj.io/common/testrand"
|
|
|
|
"storj.io/storj/private/blockchain"
|
2022-06-01 22:59:47 +01:00
|
|
|
"storj.io/storj/satellite"
|
|
|
|
"storj.io/storj/satellite/payments"
|
|
|
|
"storj.io/storj/satellite/payments/monetary"
|
|
|
|
"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()
|
2022-07-27 12:36:55 +01:00
|
|
|
now := time.Now().Truncate(time.Second).UTC()
|
2022-06-01 22:59:47 +01:00
|
|
|
|
|
|
|
wallet1 := blockchaintest.NewAddress()
|
|
|
|
wallet2 := blockchaintest.NewAddress()
|
|
|
|
|
|
|
|
walletPayments := []payments.WalletPayment{
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet1,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(100, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-01 22:59:47 +01:00
|
|
|
Status: payments.PaymentStatusConfirmed,
|
|
|
|
BlockHash: blockchaintest.NewHash(),
|
|
|
|
BlockNumber: 0,
|
|
|
|
Transaction: blockchaintest.NewHash(),
|
|
|
|
LogIndex: 0,
|
|
|
|
Timestamp: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet1,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(100, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-01 22:59:47 +01:00
|
|
|
Status: payments.PaymentStatusConfirmed,
|
|
|
|
BlockHash: blockchaintest.NewHash(),
|
|
|
|
BlockNumber: 0,
|
|
|
|
Transaction: blockchaintest.NewHash(),
|
|
|
|
LogIndex: 1,
|
|
|
|
Timestamp: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet2,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(100, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-01 22:59:47 +01:00
|
|
|
Status: payments.PaymentStatusConfirmed,
|
|
|
|
BlockHash: blockchaintest.NewHash(),
|
|
|
|
BlockNumber: 0,
|
|
|
|
Transaction: blockchaintest.NewHash(),
|
|
|
|
LogIndex: 2,
|
|
|
|
Timestamp: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet1,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(200, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-01 22:59:47 +01:00
|
|
|
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,
|
2022-06-16 14:26:27 +01:00
|
|
|
USDValue: pmnt.USDValue,
|
2022-06-01 22:59:47 +01:00
|
|
|
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)
|
|
|
|
|
|
|
|
t.Run("wallet 1", func(t *testing.T) {
|
2022-06-16 14:26:27 +01:00
|
|
|
expected := []payments.WalletPayment{walletPayments[3], walletPayments[1], walletPayments[0]}
|
2022-06-01 22:59:47 +01:00
|
|
|
|
|
|
|
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) {
|
2022-06-16 14:26:27 +01:00
|
|
|
expected := []payments.WalletPayment{walletPayments[1], walletPayments[0]}
|
2022-06-01 22:59:47 +01:00
|
|
|
|
|
|
|
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) {
|
2022-06-16 14:26:27 +01:00
|
|
|
expected := []payments.WalletPayment{walletPayments[3], walletPayments[1]}
|
2022-06-01 22:59:47 +01:00
|
|
|
|
|
|
|
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)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
}
|
2022-06-17 00:29:31 +01:00
|
|
|
|
2022-08-15 15:41:19 +01:00
|
|
|
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)
|
|
|
|
|
|
|
|
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)
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-06-17 00:29:31 +01:00
|
|
|
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: monetary.AmountFromBaseUnits(100, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-17 00:29:31 +01:00
|
|
|
Status: payments.PaymentStatusConfirmed,
|
|
|
|
BlockHash: blockchaintest.NewHash(),
|
|
|
|
BlockNumber: 0,
|
|
|
|
Transaction: blockchaintest.NewHash(),
|
|
|
|
LogIndex: 1,
|
|
|
|
Timestamp: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet1,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(100, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-17 00:29:31 +01:00
|
|
|
Status: payments.PaymentStatusConfirmed,
|
|
|
|
BlockHash: blockchaintest.NewHash(),
|
|
|
|
BlockNumber: 0,
|
|
|
|
Transaction: blockchaintest.NewHash(),
|
|
|
|
LogIndex: 2,
|
|
|
|
Timestamp: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet1,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(100, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-17 00:29:31 +01:00
|
|
|
Status: payments.PaymentStatusConfirmed,
|
|
|
|
BlockHash: blockchaintest.NewHash(),
|
|
|
|
BlockNumber: 0,
|
|
|
|
Transaction: blockchaintest.NewHash(),
|
|
|
|
LogIndex: 3,
|
|
|
|
Timestamp: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet1,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(200, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-17 00:29:31 +01:00
|
|
|
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: monetary.AmountFromBaseUnits(100, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-17 00:29:31 +01:00
|
|
|
Status: payments.PaymentStatusConfirmed,
|
|
|
|
BlockHash: blockchaintest.NewHash(),
|
|
|
|
BlockNumber: 1,
|
|
|
|
Transaction: blockchaintest.NewHash(),
|
|
|
|
LogIndex: 2,
|
|
|
|
Timestamp: now,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
From: blockchaintest.NewAddress(),
|
|
|
|
To: wallet1,
|
|
|
|
TokenValue: monetary.AmountFromBaseUnits(200, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-17 00:29:31 +01:00
|
|
|
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: monetary.AmountFromBaseUnits(200, monetary.StorjToken),
|
2022-08-18 15:42:09 +01:00
|
|
|
USDValue: monetary.AmountFromBaseUnits(100, monetary.USDollarsMicro),
|
2022-06-17 00:29:31 +01:00
|
|
|
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
|
|
|
|
}
|