satellite/payments: token deposit accept cents (#3628)

This commit is contained in:
Yaroslav Vorobiov 2019-11-21 16:25:37 +02:00 committed by GitHub
parent c72c443564
commit 87c7a2ff42
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 26 deletions

View File

@ -7,6 +7,7 @@ import (
"encoding/json"
"io/ioutil"
"net/http"
"time"
"github.com/gorilla/mux"
"github.com/zeebo/errs"
@ -14,7 +15,6 @@ import (
monkit "gopkg.in/spacemonkeygo/monkit.v2"
"storj.io/storj/satellite/console"
"storj.io/storj/satellite/payments"
)
var (
@ -241,19 +241,21 @@ func (p *Payments) TokenDeposit(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
var requestData struct {
Amount string `json:"amount"`
Amount int64 `json:"amount"`
}
if err = json.NewDecoder(r.Body).Decode(&requestData); err != nil {
p.serveJSONError(w, http.StatusBadRequest, err)
}
amount, err := payments.ParseTokenAmount(requestData.Amount)
if err != nil {
p.serveJSONError(w, http.StatusBadRequest, err)
if requestData.Amount < 0 {
p.serveJSONError(w, http.StatusBadRequest, errs.New("amount can not be negative"))
}
if requestData.Amount == 0 {
p.serveJSONError(w, http.StatusBadRequest, errs.New("amount should be greater than zero"))
}
tx, err := p.service.Payments().TokenDeposit(ctx, amount)
tx, err := p.service.Payments().TokenDeposit(ctx, requestData.Amount)
if err != nil {
if console.ErrUnauthorized.Has(err) {
p.serveJSONError(w, http.StatusUnauthorized, err)
@ -265,12 +267,20 @@ func (p *Payments) TokenDeposit(w http.ResponseWriter, r *http.Request) {
}
var responseData struct {
Address string `json:"address"`
Amount string `json:"amount"`
Address string `json:"address"`
Amount float64 `json:"amount"`
TokenAmount string `json:"tokenAmount"`
Rate string `json:"rate"`
Status string `json:"status"`
ExpiresAt time.Time `json:"expires"`
}
responseData.Amount = tx.Amount.String()
responseData.Address = tx.Address
responseData.Amount = float64(requestData.Amount) / 100
responseData.TokenAmount = tx.Amount.String()
responseData.Rate = tx.Rate.Text('f', 8)
responseData.Status = tx.Status.String()
responseData.ExpiresAt = tx.CreatedAt.Add(tx.Timeout)
err = json.NewEncoder(w).Encode(responseData)
if err != nil {

View File

@ -257,7 +257,7 @@ func (payments PaymentsService) BillingHistory(ctx context.Context) (billingHist
}
// TokenDeposit creates new deposit transaction for adding STORJ tokens to account balance.
func (payments PaymentsService) TokenDeposit(ctx context.Context, amount *payments.TokenAmount) (_ *payments.Transaction, err error) {
func (payments PaymentsService) TokenDeposit(ctx context.Context, amount int64) (_ *payments.Transaction, err error) {
defer mon.Task()(&ctx)(&err)
auth, err := GetAuth(ctx)

View File

@ -118,7 +118,7 @@ func (invoices *invoices) List(ctx context.Context, userID uuid.UUID) (_ []payme
}
// Deposit creates new deposit transaction.
func (tokens *storjTokens) Deposit(ctx context.Context, userID uuid.UUID, amount *payments.TokenAmount) (_ *payments.Transaction, err error) {
func (tokens *storjTokens) Deposit(ctx context.Context, userID uuid.UUID, amount int64) (_ *payments.Transaction, err error) {
defer mon.Task()(&ctx, userID, amount)(&err)
return nil, Error.Wrap(errs.New("can not make deposit"))

View File

@ -8,8 +8,15 @@ import (
"math/big"
)
// convertToCents convert amount to cents with with given rate.
// convertToCents convert amount to cents with given rate.
func convertToCents(rate, amount *big.Float) int64 {
f, _ := new(big.Float).Mul(amount, rate).Float64()
return int64(math.Floor(f * 100))
return int64(math.Round(f * 100))
}
// convertFromCents convert amount in cents to big.Float with given rate.
func convertFromCents(rate *big.Float, amount int64) *big.Float {
a := new(big.Float).SetInt64(amount)
a = a.Quo(a, new(big.Float).SetInt64(100))
return new(big.Float).Quo(a, rate)
}

View File

@ -24,7 +24,7 @@ type storjTokens struct {
// 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 *payments.TokenAmount) (_ *payments.Transaction, err error) {
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)
@ -42,9 +42,11 @@ func (tokens *storjTokens) Deposit(ctx context.Context, userID uuid.UUID, amount
return nil, Error.Wrap(err)
}
tokenAmount := convertFromCents(rate, amount).SetPrec(payments.STORJTokenPrecision)
tx, err := tokens.service.coinPayments.Transactions().Create(ctx,
&coinpayments.CreateTX{
Amount: *amount.BigFloat(),
Amount: *tokenAmount,
CurrencyIn: coinpayments.CurrencySTORJ,
CurrencyOut: coinpayments.CurrencySTORJ,
BuyerEmail: c.Email,
@ -80,9 +82,8 @@ func (tokens *storjTokens) Deposit(ctx context.Context, userID uuid.UUID, amount
return &payments.Transaction{
ID: payments.TransactionID(tx.ID),
AccountID: userID,
Amount: *payments.TokenAmountFromBigFloat(&tx.Amount),
Received: *payments.NewTokenAmount(),
Rate: *rate,
Address: tx.Address,
Status: payments.TransactionStatusPending,
Timeout: tx.Timeout,

View File

@ -13,8 +13,8 @@ import (
// StorjTokens defines all payments STORJ token related functionality.
type StorjTokens interface {
// Deposit creates deposit transaction for specified amount.
Deposit(ctx context.Context, userID uuid.UUID, amount *TokenAmount) (*Transaction, error)
// Deposit creates deposit transaction for specified amount in cents.
Deposit(ctx context.Context, userID uuid.UUID, amount int64) (*Transaction, error)
// ListTransactionInfos returns all transaction associated with user.
ListTransactionInfos(ctx context.Context, userID uuid.UUID) ([]TransactionInfo, error)
}
@ -49,9 +49,8 @@ func (id TransactionID) String() string {
// accepts user funds on a specific wallet address.
type Transaction struct {
ID TransactionID
AccountID uuid.UUID
Amount TokenAmount
Received TokenAmount
Rate big.Float
Address string
Status TransactionStatus
Timeout time.Duration
@ -81,12 +80,12 @@ type TokenAmount struct {
inner big.Float
}
// precision defines STORJ token precision.
const precision = 32
// STORJTokenPrecision defines STORJ token precision.
const STORJTokenPrecision = 32
// NewTokenAmount creates new zeroed TokenAmount with fixed precision.
func NewTokenAmount() *TokenAmount {
return &TokenAmount{inner: *new(big.Float).SetPrec(precision)}
return &TokenAmount{inner: *new(big.Float).SetPrec(STORJTokenPrecision)}
}
// BigFloat returns inner representation of TokenAmount.
@ -103,7 +102,7 @@ func (amount *TokenAmount) String() string {
// ParseTokenAmount parses string representing floating point and returns
// TokenAmount.
func ParseTokenAmount(s string) (*TokenAmount, error) {
inner, _, err := big.ParseFloat(s, 10, precision, big.ToNearestEven)
inner, _, err := big.ParseFloat(s, 10, STORJTokenPrecision, big.ToNearestEven)
if err != nil {
return nil, err
}
@ -112,6 +111,6 @@ func ParseTokenAmount(s string) (*TokenAmount, error) {
// TokenAmountFromBigFloat converts big.Float to TokenAmount.
func TokenAmountFromBigFloat(f *big.Float) *TokenAmount {
inner := (*f).SetMode(big.ToNearestEven).SetPrec(precision)
inner := (*f).SetMode(big.ToNearestEven).SetPrec(STORJTokenPrecision)
return &TokenAmount{inner: *inner}
}