2eb2c25e51
able to cover more testing scenarios Currently, its hard to implement test suite for payments because mockpayments is on to high level and we cannot emulate many things e.g. adding credit card. This change is first to be able to add mock for Stripe client and do more granular tests. Change-Id: Ied85d4bd0642debdffe1161657c1e475202e9d23
145 lines
4.0 KiB
Go
145 lines
4.0 KiB
Go
// Copyright (C) 2019 Storj Labs, Inc.
|
|
// See LICENSE for copying information.
|
|
|
|
package stripecoinpayments
|
|
|
|
import (
|
|
"context"
|
|
|
|
"storj.io/common/uuid"
|
|
"storj.io/storj/satellite/payments"
|
|
"storj.io/storj/satellite/payments/coinpayments"
|
|
)
|
|
|
|
// ensure that storjTokens implements payments.StorjTokens.
|
|
var _ payments.StorjTokens = (*storjTokens)(nil)
|
|
|
|
// storjTokens implements payments.StorjTokens.
|
|
//
|
|
// architecture: Service
|
|
type storjTokens struct {
|
|
service *Service
|
|
}
|
|
|
|
// Deposit creates new deposit transaction with the given amount returning
|
|
// ETH wallet address where funds should be sent. There is one
|
|
// hour limit to complete the transaction. Transaction is saved to DB with
|
|
// reference to the user who made the deposit.
|
|
func (tokens *storjTokens) Deposit(ctx context.Context, userID uuid.UUID, amount int64) (_ *payments.Transaction, err error) {
|
|
defer mon.Task()(&ctx, userID, amount)(&err)
|
|
|
|
customerID, err := tokens.service.db.Customers().GetCustomerID(ctx, userID)
|
|
if err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
c, err := tokens.service.stripeClient.Customers().Get(customerID, nil)
|
|
if err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
rate, err := tokens.service.GetRate(ctx, coinpayments.CurrencySTORJ, coinpayments.CurrencyUSD)
|
|
if err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
tokenAmount := convertFromCents(rate, amount).SetPrec(payments.STORJTokenPrecision)
|
|
|
|
tx, err := tokens.service.coinPayments.Transactions().Create(ctx,
|
|
&coinpayments.CreateTX{
|
|
Amount: *tokenAmount,
|
|
CurrencyIn: coinpayments.CurrencySTORJ,
|
|
CurrencyOut: coinpayments.CurrencySTORJ,
|
|
BuyerEmail: c.Email,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
key, err := coinpayments.GetTransacationKeyFromURL(tx.CheckoutURL)
|
|
if err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
if err = tokens.service.db.Transactions().LockRate(ctx, tx.ID, rate); err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
cpTX, err := tokens.service.db.Transactions().Insert(ctx,
|
|
Transaction{
|
|
ID: tx.ID,
|
|
AccountID: userID,
|
|
Address: tx.Address,
|
|
Amount: tx.Amount,
|
|
Status: coinpayments.StatusPending,
|
|
Key: key,
|
|
Timeout: tx.Timeout,
|
|
},
|
|
)
|
|
if err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
return &payments.Transaction{
|
|
ID: payments.TransactionID(tx.ID),
|
|
Amount: *payments.TokenAmountFromBigFloat(&tx.Amount),
|
|
Rate: *rate,
|
|
Address: tx.Address,
|
|
Status: payments.TransactionStatusPending,
|
|
Timeout: tx.Timeout,
|
|
Link: tx.CheckoutURL,
|
|
CreatedAt: cpTX.CreatedAt,
|
|
}, nil
|
|
}
|
|
|
|
// ListTransactionInfos fetches all transactions from the database for specified user, reconstructing checkout link.
|
|
func (tokens *storjTokens) ListTransactionInfos(ctx context.Context, userID uuid.UUID) (_ []payments.TransactionInfo, err error) {
|
|
defer mon.Task()(&ctx, userID)(&err)
|
|
|
|
txs, err := tokens.service.db.Transactions().ListAccount(ctx, userID)
|
|
if err != nil {
|
|
return nil, Error.Wrap(err)
|
|
}
|
|
|
|
var infos []payments.TransactionInfo
|
|
for _, tx := range txs {
|
|
link := coinpayments.GetCheckoutURL(tx.Key, tx.ID)
|
|
|
|
var status payments.TransactionStatus
|
|
switch tx.Status {
|
|
case coinpayments.StatusPending:
|
|
status = payments.TransactionStatusPending
|
|
case coinpayments.StatusReceived:
|
|
status = payments.TransactionStatusPaid
|
|
case coinpayments.StatusCancelled:
|
|
status = payments.TransactionStatusCancelled
|
|
default:
|
|
// unknown
|
|
status = payments.TransactionStatus(tx.Status.String())
|
|
}
|
|
|
|
rate, err := tokens.service.db.Transactions().GetLockedRate(ctx, tx.ID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
infos = append(infos,
|
|
payments.TransactionInfo{
|
|
ID: []byte(tx.ID),
|
|
Amount: *payments.TokenAmountFromBigFloat(&tx.Amount),
|
|
Received: *payments.TokenAmountFromBigFloat(&tx.Received),
|
|
AmountCents: convertToCents(rate, &tx.Amount),
|
|
ReceivedCents: convertToCents(rate, &tx.Received),
|
|
Address: tx.Address,
|
|
Status: status,
|
|
Link: link,
|
|
ExpiresAt: tx.CreatedAt.Add(tx.Timeout),
|
|
CreatedAt: tx.CreatedAt,
|
|
},
|
|
)
|
|
}
|
|
|
|
return infos, nil
|
|
}
|