console: stub endpoints for native token payments

Change-Id: I3f99ab44332eb8c9e2a3834a932eee72f44bd490
This commit is contained in:
Márton Elek 2022-05-11 10:02:58 +02:00 committed by Elek, Márton
parent 460af183a0
commit 55de50eea7
4 changed files with 134 additions and 0 deletions

View File

@ -374,6 +374,78 @@ func (p *Payments) GetCoupon(w http.ResponseWriter, r *http.Request) {
}
}
// GetWallet returns the wallet address (with balance) already assigned to the user.
func (p *Payments) GetWallet(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set("Content-Type", "application/json")
walletInfo, err := p.service.Payments().GetWallet(ctx)
if err != nil {
if console.ErrUnauthorized.Has(err) {
p.serveJSONError(w, http.StatusUnauthorized, err)
return
}
p.serveJSONError(w, http.StatusInternalServerError, err)
return
}
if err = json.NewEncoder(w).Encode(walletInfo); err != nil {
p.log.Error("failed to encode wallet info", zap.Error(ErrPaymentsAPI.Wrap(err)))
}
}
// ClaimWallet will claim a new wallet address. Returns with existing if it's already claimed.
func (p *Payments) ClaimWallet(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set("Content-Type", "application/json")
walletInfo, err := p.service.Payments().ClaimWallet(ctx)
if err != nil {
if console.ErrUnauthorized.Has(err) {
p.serveJSONError(w, http.StatusUnauthorized, err)
return
}
p.serveJSONError(w, http.StatusInternalServerError, err)
return
}
if err = json.NewEncoder(w).Encode(walletInfo); err != nil {
p.log.Error("failed to encode wallet info", zap.Error(ErrPaymentsAPI.Wrap(err)))
}
}
// Transactions returns with the list of storjscan transactions.
func (p *Payments) Transactions(w http.ResponseWriter, r *http.Request) {
ctx := r.Context()
var err error
defer mon.Task()(&ctx)(&err)
w.Header().Set("Content-Type", "application/json")
transactions, err := p.service.Payments().Transactions(ctx)
if err != nil {
if console.ErrUnauthorized.Has(err) {
p.serveJSONError(w, http.StatusUnauthorized, err)
return
}
p.serveJSONError(w, http.StatusInternalServerError, err)
return
}
if err = json.NewEncoder(w).Encode(transactions); err != nil {
p.log.Error("failed to encode transactions", zap.Error(ErrPaymentsAPI.Wrap(err)))
}
}
// serveJSONError writes JSON error to response output stream.
func (p *Payments) serveJSONError(w http.ResponseWriter, status int, err error) {
serveJSONError(p.log, w, status, err)

View File

@ -268,6 +268,9 @@ func NewServer(logger *zap.Logger, config Config, service *console.Service, oidc
paymentsRouter.HandleFunc("/account/charges", paymentController.ProjectsCharges).Methods(http.MethodGet)
paymentsRouter.HandleFunc("/account/balance", paymentController.AccountBalance).Methods(http.MethodGet)
paymentsRouter.HandleFunc("/account", paymentController.SetupAccount).Methods(http.MethodPost)
paymentsRouter.HandleFunc("/wallet", paymentController.GetWallet).Methods(http.MethodGet)
paymentsRouter.HandleFunc("/wallet", paymentController.ClaimWallet).Methods(http.MethodPost)
paymentsRouter.HandleFunc("/transactions", paymentController.Transactions).Methods(http.MethodGet)
paymentsRouter.HandleFunc("/billing-history", paymentController.BillingHistory).Methods(http.MethodGet)
paymentsRouter.HandleFunc("/tokens/deposit", paymentController.TokenDeposit).Methods(http.MethodPost)
paymentsRouter.Handle("/coupon/apply", server.userIDRateLimiter.Limit(http.HandlerFunc(paymentController.ApplyCouponCode))).Methods(http.MethodPatch)

View File

@ -8,6 +8,7 @@ import (
"crypto/subtle"
"fmt"
"math"
"math/big"
"net/http"
"net/mail"
"sort"
@ -27,10 +28,12 @@ import (
"storj.io/common/uuid"
"storj.io/private/cfgstruct"
"storj.io/storj/private/api"
"storj.io/storj/private/blockchain"
"storj.io/storj/satellite/accounting"
"storj.io/storj/satellite/analytics"
"storj.io/storj/satellite/console/consoleauth"
"storj.io/storj/satellite/payments"
"storj.io/storj/satellite/payments/monetary"
"storj.io/storj/satellite/rewards"
)
@ -2466,6 +2469,46 @@ func (s *Service) isProjectMember(ctx context.Context, userID uuid.UUID, project
return isProjectMember{}, ErrNoMembership.New(unauthorizedErrMsg)
}
// WalletInfo contains all the information about a destination wallet assigned to a user.
type WalletInfo struct {
Address blockchain.Address `json:"address"`
Balance *big.Int `json:"balance"`
}
// TokenTransactions represents the list of ERC-20 token payments.
type TokenTransactions struct {
Transactions []TokenTransaction `json:"transactions"`
}
// TokenTransaction contains the data of one single ERC-20 token payment.
type TokenTransaction struct {
Origin blockchain.Address `json:"origin"`
Address blockchain.Address `json:"address"`
TxHash blockchain.Hash `json:"tx_hash"`
Status string `json:"status"`
Date time.Time `json:"date"`
Amount monetary.Amount `json:"amount"`
}
// ErrWalletNotClaimed shows that no address is claimed by the user.
var ErrWalletNotClaimed = errs.Class("wallet is not claimed")
// ClaimWallet requests a new wallet for the users to be used for payments. If wallet is already claimed,
// it will return with the info without error.
func (paymentService PaymentsService) ClaimWallet(ctx context.Context) (WalletInfo, error) {
panic("Not yet implemented")
}
// GetWallet returns with the assigned wallet, or with ErrWalletNotClaimed if not yet claimed.
func (paymentService PaymentsService) GetWallet(ctx context.Context) (WalletInfo, error) {
panic("Not yet implemented")
}
// Transactions returns with all the native blockchain transactions.
func (paymentService PaymentsService) Transactions(ctx context.Context) (TokenTransactions, error) {
panic("Not yet implemented")
}
func findMembershipByProjectID(memberships []ProjectMember, projectID uuid.UUID) (ProjectMember, bool) {
for _, membership := range memberships {
if membership.ProjectID == projectID {

View File

@ -5,7 +5,9 @@ package console_test
import (
"context"
"encoding/json"
"math"
"math/big"
"testing"
"time"
@ -18,6 +20,7 @@ import (
"storj.io/common/testcontext"
"storj.io/common/testrand"
"storj.io/common/uuid"
"storj.io/storj/private/blockchain"
"storj.io/storj/private/testplanet"
"storj.io/storj/satellite"
"storj.io/storj/satellite/console"
@ -866,3 +869,16 @@ func TestLockAccount(t *testing.T) {
require.True(t, lockedUser.LoginLockoutExpiration.After(now))
})
}
func TestWalletJsonMarshall(t *testing.T) {
wi := console.WalletInfo{
Address: blockchain.Address{1, 2, 3},
Balance: big.NewInt(100),
}
out, err := json.Marshal(wi)
require.NoError(t, err)
require.Contains(t, string(out), "\"address\":\"0102030000000000000000000000000000000000\"")
require.Contains(t, string(out), "\"balance\":100")
}