satellite/payments: token deposit accept cents (#3628)
This commit is contained in:
parent
c72c443564
commit
87c7a2ff42
@ -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 {
|
||||
|
@ -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)
|
||||
|
@ -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"))
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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,
|
||||
|
@ -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}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user