Enable pool closure (#80)
* Enable pool closure. * Move homepage to its own file * Docs and rename status>info
This commit is contained in:
parent
e65a7fdbf3
commit
6a100811f4
@ -29,6 +29,7 @@ var (
|
||||
defaultWalletHost = "127.0.0.1"
|
||||
defaultWebServerDebug = false
|
||||
defaultBackupInterval = time.Minute * 3
|
||||
defaultVspClosed = false
|
||||
)
|
||||
|
||||
// config defines the configuration options for the VSP.
|
||||
@ -51,6 +52,7 @@ type config struct {
|
||||
WebServerDebug bool `long:"webserverdebug" ini-name:"webserverdebug" description:"Enable web server debug mode (verbose logging to terminal and live-reloading templates)."`
|
||||
SupportEmail string `long:"supportemail" ini-name:"supportemail" description:"Email address for users in need of support."`
|
||||
BackupInterval time.Duration `long:"backupinterval" ini-name:"backupinterval" description:"Time period between automatic database backups. Valid time units are {s,m,h}. Minimum 30 seconds."`
|
||||
VspClosed bool `long:"vspclosed" ini-name:"vspclosed" description:"Closed prevents the VSP from accepting new tickets."`
|
||||
|
||||
dbPath string
|
||||
netParams *netParams
|
||||
@ -156,6 +158,7 @@ func loadConfig() (*config, error) {
|
||||
WalletHost: defaultWalletHost,
|
||||
WebServerDebug: defaultWebServerDebug,
|
||||
BackupInterval: defaultBackupInterval,
|
||||
VspClosed: defaultVspClosed,
|
||||
}
|
||||
|
||||
// Pre-parse the command line options to see if an alternative config
|
||||
|
||||
25
docs/api.md
25
docs/api.md
@ -15,13 +15,15 @@
|
||||
|
||||
## Expected usage
|
||||
|
||||
### Get VSP public key
|
||||
### Get VSP info
|
||||
|
||||
Clients should first retrieve the VSP's public key so they can check the
|
||||
signature on later API responses. A VSP should never change their public key so
|
||||
it can be requested once and cached indefinitely.
|
||||
Clients should retrieve the VSP's public key so they can check the signature on
|
||||
future API responses. A VSP should never change their public key so it can be
|
||||
requested once and cached indefinitely. `vspclosed` indicates that the VSP is
|
||||
not currently accepting new tickets. Calling `/feeaddress` when a VSP is closed
|
||||
will result in an error.
|
||||
|
||||
- `GET /api/pubkey`
|
||||
- `GET /api/vspinfo`
|
||||
|
||||
No request body.
|
||||
|
||||
@ -29,8 +31,11 @@ it can be requested once and cached indefinitely.
|
||||
|
||||
```json
|
||||
{
|
||||
"timestamp":1590509065,
|
||||
"pubkey":"bLNwVVcda3LqRLv+m0J5sjd60+twjO/fuhcx8RUErDQ="
|
||||
"timestamp":1590599436,
|
||||
"pubkey":"SjAmrAqH7LScCUwM1qo5O6Cu7aKhrM1ORszgZwD7HmU=",
|
||||
"feepercentage":0.05,
|
||||
"vspclosed":false,
|
||||
"network":"testnet3"
|
||||
}
|
||||
```
|
||||
|
||||
@ -101,11 +106,7 @@ has 6 confirmations.
|
||||
}
|
||||
```
|
||||
|
||||
### Information requests
|
||||
|
||||
Clients can check the status of the server at any time.
|
||||
|
||||
// TODO
|
||||
### Ticket Status
|
||||
|
||||
Clients can check the status of a ticket at any time after calling
|
||||
`/feeaddress`.
|
||||
|
||||
6
main.go
6
main.go
@ -44,6 +44,11 @@ func run(ctx context.Context) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if cfg.VspClosed {
|
||||
log.Warnf("Config --vspclosed is set. This will prevent vspd from " +
|
||||
"accepting new tickets.")
|
||||
}
|
||||
|
||||
// Waitgroup for services to signal when they have shutdown cleanly.
|
||||
var shutdownWg sync.WaitGroup
|
||||
defer log.Info("Shutdown complete")
|
||||
@ -117,6 +122,7 @@ func run(ctx context.Context) error {
|
||||
NetParams: cfg.netParams.Params,
|
||||
FeeAddressExpiration: defaultFeeAddressExpiration,
|
||||
SupportEmail: cfg.SupportEmail,
|
||||
VspClosed: cfg.VspClosed,
|
||||
}
|
||||
err = webapi.Start(ctx, shutdownRequestChannel, &shutdownWg, cfg.Listen, db,
|
||||
dcrdConnect, walletConnect, cfg.WebServerDebug, cfg.FeeXPub, apiCfg)
|
||||
|
||||
@ -69,6 +69,11 @@ func feeAddress(c *gin.Context) {
|
||||
commitmentAddress := c.MustGet("CommitmentAddress").(string)
|
||||
dcrdClient := c.MustGet("DcrdClient").(*rpc.DcrdRPC)
|
||||
|
||||
if cfg.VspClosed {
|
||||
sendErrorResponse("pool is not accepting new tickets", http.StatusBadRequest, c)
|
||||
return
|
||||
}
|
||||
|
||||
var feeAddressRequest FeeAddressRequest
|
||||
if err := binding.JSON.BindBody(rawRequest, &feeAddressRequest); err != nil {
|
||||
log.Warnf("Bad feeaddress request from %s: %v", c.ClientIP(), err)
|
||||
|
||||
44
webapi/homepage.go
Normal file
44
webapi/homepage.go
Normal file
@ -0,0 +1,44 @@
|
||||
package webapi
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"time"
|
||||
|
||||
"github.com/jholdstock/vspd/database"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
type vspStats struct {
|
||||
PubKey []byte
|
||||
TotalTickets int
|
||||
FeePaidTickets int
|
||||
VSPFee float64
|
||||
Network string
|
||||
UpdateTime string
|
||||
SupportEmail string
|
||||
VspClosed bool
|
||||
}
|
||||
|
||||
var stats *vspStats
|
||||
|
||||
func updateVSPStats(db *database.VspDatabase, cfg Config) (*vspStats, error) {
|
||||
total, feePaid, err := db.CountTickets()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &vspStats{
|
||||
PubKey: signPubKey,
|
||||
TotalTickets: total,
|
||||
FeePaidTickets: feePaid,
|
||||
VSPFee: cfg.VSPFee,
|
||||
Network: cfg.NetParams.Name,
|
||||
UpdateTime: time.Now().Format("Mon Jan _2 15:04:05 2006"),
|
||||
SupportEmail: cfg.SupportEmail,
|
||||
VspClosed: cfg.VspClosed,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func homepage(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "homepage.html", stats)
|
||||
}
|
||||
@ -1,23 +0,0 @@
|
||||
package webapi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// pubKey is the handler for "GET /pubkey".
|
||||
func pubKey(c *gin.Context) {
|
||||
sendJSONResponse(pubKeyResponse{
|
||||
Timestamp: time.Now().Unix(),
|
||||
PubKey: signPubKey,
|
||||
}, c)
|
||||
}
|
||||
|
||||
// fee is the handler for "GET /fee".
|
||||
func fee(c *gin.Context) {
|
||||
sendJSONResponse(feeResponse{
|
||||
Timestamp: time.Now().Unix(),
|
||||
FeePercentage: cfg.VSPFee,
|
||||
}, c)
|
||||
}
|
||||
@ -48,6 +48,7 @@
|
||||
<tr><td>Network:</td><td>{{ .Network }}</td></tr>
|
||||
<tr><td>Support:</td><td>{{ .SupportEmail }}</td></tr>
|
||||
<tr><td>Pubkey:</td><td>{{ printf "%x" .PubKey }}</td></tr>
|
||||
<tr><td>VSP closed:</td><td>{{ .VspClosed }}</td></tr>
|
||||
</table>
|
||||
<p>Last updated: {{.UpdateTime}}</p>
|
||||
</body>
|
||||
|
||||
@ -1,13 +1,11 @@
|
||||
package webapi
|
||||
|
||||
type pubKeyResponse struct {
|
||||
Timestamp int64 `json:"timestamp" binding:"required"`
|
||||
PubKey []byte `json:"pubkey" binding:"required"`
|
||||
}
|
||||
|
||||
type feeResponse struct {
|
||||
type vspInfoResponse struct {
|
||||
Timestamp int64 `json:"timestamp" binding:"required"`
|
||||
PubKey []byte `json:"pubkey" binding:"required"`
|
||||
FeePercentage float64 `json:"feepercentage" binding:"required"`
|
||||
VspClosed bool `json:"vspclosed" binding:"required"`
|
||||
Network string `json:"network" binding:"required"`
|
||||
}
|
||||
|
||||
type FeeAddressRequest struct {
|
||||
|
||||
18
webapi/vspstatus.go
Normal file
18
webapi/vspstatus.go
Normal file
@ -0,0 +1,18 @@
|
||||
package webapi
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// vspInfo is the handler for "GET /vspinfo".
|
||||
func vspInfo(c *gin.Context) {
|
||||
sendJSONResponse(vspInfoResponse{
|
||||
Timestamp: time.Now().Unix(),
|
||||
PubKey: signPubKey,
|
||||
FeePercentage: cfg.VSPFee,
|
||||
Network: cfg.NetParams.Name,
|
||||
VspClosed: cfg.VspClosed,
|
||||
}, c)
|
||||
}
|
||||
@ -24,6 +24,7 @@ type Config struct {
|
||||
FeeAccountName string
|
||||
FeeAddressExpiration time.Duration
|
||||
SupportEmail string
|
||||
VspClosed bool
|
||||
}
|
||||
|
||||
const (
|
||||
@ -34,18 +35,6 @@ const (
|
||||
relayFee = 0.0001
|
||||
)
|
||||
|
||||
type vspStats struct {
|
||||
PubKey []byte
|
||||
TotalTickets int
|
||||
FeePaidTickets int
|
||||
VSPFee float64
|
||||
Network string
|
||||
UpdateTime string
|
||||
SupportEmail string
|
||||
}
|
||||
|
||||
var stats *vspStats
|
||||
|
||||
var cfg Config
|
||||
var db *database.VspDatabase
|
||||
var dcrdConnect rpc.Connect
|
||||
@ -185,8 +174,7 @@ func router(debugMode bool) *gin.Engine {
|
||||
|
||||
// These routes have no extra middleware. They can be accessed by anybody.
|
||||
router.GET("/", homepage)
|
||||
router.GET("/api/fee", fee)
|
||||
router.GET("/api/pubkey", pubKey)
|
||||
router.GET("/api/vspinfo", vspInfo)
|
||||
|
||||
// These API routes access dcrd and they need authentication.
|
||||
feeOnly := router.Group("/api").Use(
|
||||
@ -206,26 +194,6 @@ func router(debugMode bool) *gin.Engine {
|
||||
return router
|
||||
}
|
||||
|
||||
func updateVSPStats(db *database.VspDatabase, cfg Config) (*vspStats, error) {
|
||||
total, feePaid, err := db.CountTickets()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &vspStats{
|
||||
PubKey: signPubKey,
|
||||
TotalTickets: total,
|
||||
FeePaidTickets: feePaid,
|
||||
VSPFee: cfg.VSPFee,
|
||||
Network: cfg.NetParams.Name,
|
||||
UpdateTime: time.Now().Format("Mon Jan _2 15:04:05 2006"),
|
||||
SupportEmail: cfg.SupportEmail,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func homepage(c *gin.Context) {
|
||||
c.HTML(http.StatusOK, "homepage.html", stats)
|
||||
}
|
||||
|
||||
func sendJSONResponse(resp interface{}, c *gin.Context) {
|
||||
dec, err := json.Marshal(resp)
|
||||
if err != nil {
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user