commit
70e63e3336
1
go.mod
1
go.mod
|
@ -8,6 +8,7 @@ require (
|
|||
github.com/gobuffalo/packr v1.30.1
|
||||
github.com/kelseyhightower/envconfig v1.4.0
|
||||
github.com/lib/pq v1.7.0
|
||||
github.com/muesli/cache2go v0.0.0-20200423001931-a100c5aac93f
|
||||
github.com/onsi/gomega v1.10.1 // indirect
|
||||
github.com/rogpeppe/go-internal v1.6.0 // indirect
|
||||
github.com/ybbus/jsonrpc v2.1.2+incompatible
|
||||
|
|
2
go.sum
2
go.sum
|
@ -48,6 +48,8 @@ github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
|||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/muesli/cache2go v0.0.0-20200423001931-a100c5aac93f h1:dBzTzAKOh89fTvdQ3XlXupMExvLty90V1rrpChTAQAY=
|
||||
github.com/muesli/cache2go v0.0.0-20200423001931-a100c5aac93f/go.mod h1:414R+qZrt4f9S2TO/s6YVQMNAXR2KdwqQ7pW+O4oYzU=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
|
|
84
main.go
84
main.go
|
@ -18,11 +18,13 @@ import (
|
|||
"github.com/gobuffalo/packr"
|
||||
"github.com/kelseyhightower/envconfig"
|
||||
_ "github.com/lib/pq"
|
||||
"github.com/muesli/cache2go"
|
||||
"github.com/ybbus/jsonrpc"
|
||||
)
|
||||
|
||||
const tapAmount = 1.0
|
||||
const tapWaitMinutes = 2
|
||||
const opStatusWaitSeconds = 120
|
||||
|
||||
type TapRequest struct {
|
||||
NetworkAddress string
|
||||
|
@ -69,6 +71,7 @@ type Zfaucet struct {
|
|||
ZcashNetwork string
|
||||
FundingAddress string
|
||||
TapRequests []*TapRequest
|
||||
TapCache *cache2go.CacheTable
|
||||
ZfaucetHTML string
|
||||
}
|
||||
|
||||
|
@ -98,6 +101,27 @@ func (z *Zfaucet) ClearCache() {
|
|||
}
|
||||
}
|
||||
|
||||
func (z *Zfaucet) UpdateZcashInfo() {
|
||||
for {
|
||||
z.UpdatedChainInfo = time.Now()
|
||||
zChainInfo, err := getBlockchainInfo(z.RPCConnetion)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to get blockchaininfo: %s\n", err)
|
||||
} else {
|
||||
z.CurrentHeight = zChainInfo.Blocks
|
||||
z.ZcashNetwork = zChainInfo.Chain
|
||||
}
|
||||
zVersion, err := getInfo(z.RPCConnetion)
|
||||
if err != nil {
|
||||
fmt.Printf("Failed to getinfo: %s\n", err)
|
||||
} else {
|
||||
z.ZcashdVersion = strconv.Itoa(zVersion.Version)
|
||||
}
|
||||
fmt.Println("Updated Zcashd Info")
|
||||
time.Sleep(time.Second * 30)
|
||||
}
|
||||
}
|
||||
|
||||
func (z *Zfaucet) WaitForOperation(opid string) (os OperationStatus, err error) {
|
||||
var opStatus []struct {
|
||||
CreationTime int `json:"creation_time"`
|
||||
|
@ -115,7 +139,7 @@ func (z *Zfaucet) WaitForOperation(opid string) (os OperationStatus, err error)
|
|||
fmt.Printf("opList: %s\n", opList)
|
||||
fmt.Printf("parentList: %s\n", parentList)
|
||||
// Wait for a few seconds for the operational status to become available
|
||||
for i := 0; i < 10; i++ {
|
||||
for i := 0; i < opStatusWaitSeconds; i++ {
|
||||
if err := z.RPCConnetion.CallFor(
|
||||
&opStatus,
|
||||
"z_getoperationresult",
|
||||
|
@ -176,11 +200,13 @@ func (z *Zfaucet) ZSendManyFaucet(remoteAddr string, remoteWallet string) (opSta
|
|||
if opStatus.Status != "success" {
|
||||
return opStatus, fmt.Errorf("Failed to send funds: %s", err)
|
||||
}
|
||||
z.TapRequests = append(z.TapRequests, &TapRequest{
|
||||
tapRequest := &TapRequest{
|
||||
NetworkAddress: remoteAddr,
|
||||
WalletAddress: remoteWallet,
|
||||
RequestedAt: time.Now(),
|
||||
})
|
||||
}
|
||||
z.TapCache.Add(remoteAddr, tapWaitMinutes*60*time.Second, tapRequest)
|
||||
z.TapRequests = append(z.TapRequests, tapRequest)
|
||||
return opStatus, err
|
||||
|
||||
}
|
||||
|
@ -224,6 +250,7 @@ func main() {
|
|||
|
||||
basicAuth := base64.StdEncoding.EncodeToString([]byte(zConfig.RPCUser + ":" + zConfig.RPCPassword))
|
||||
var z Zfaucet
|
||||
z.TapCache = cache2go.Cache("tapRequests")
|
||||
z.FundingAddress = zConfig.FundingAddress
|
||||
z.Operations = make(map[string]OperationStatus)
|
||||
z.RPCConnetion = jsonrpc.NewClientWithOpts("http://"+zConfig.RPCHost+":"+zConfig.RPCPort,
|
||||
|
@ -232,19 +259,8 @@ func main() {
|
|||
"Authorization": "Basic " + basicAuth,
|
||||
}})
|
||||
|
||||
zChainInfo, err := getBlockchainInfo(z.RPCConnetion)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to get blockchaininfo: %s", err)
|
||||
}
|
||||
z.CurrentHeight = zChainInfo.Blocks
|
||||
z.ZcashNetwork = zChainInfo.Chain
|
||||
zVersion, err := getInfo(z.RPCConnetion)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed to getinfo: %s", err)
|
||||
}
|
||||
z.ZcashdVersion = strconv.Itoa(zVersion.Version)
|
||||
|
||||
go z.ClearCache()
|
||||
go z.UpdateZcashInfo()
|
||||
|
||||
box := packr.NewBox("./templates")
|
||||
z.ZfaucetHTML, err = box.FindString("zfaucet.html")
|
||||
|
@ -285,15 +301,13 @@ func (z *Zfaucet) home(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
switch r.Method {
|
||||
case http.MethodPost:
|
||||
for _, n := range z.TapRequests {
|
||||
fmt.Printf("Checking RemoteAddress: '%#v' - '%#v'\n", r.RemoteAddr, n.NetworkAddress)
|
||||
if n.NetworkAddress == r.RemoteAddr {
|
||||
tData.Msg = fmt.Sprintf("You may only tap the faucet every %d minutes\nPlease try again later\n", tapWaitMinutes)
|
||||
break
|
||||
} else {
|
||||
fmt.Printf("It doesn't match... \n")
|
||||
}
|
||||
|
||||
res, err := z.TapCache.Value(r.RemoteAddr)
|
||||
if err == nil {
|
||||
fmt.Println("Found value in cache:", res.Data().(*TapRequest).NetworkAddress)
|
||||
tData.Msg = fmt.Sprintf("You may only tap the faucet every %d minutes\nPlease try again later\n", tapWaitMinutes)
|
||||
break
|
||||
} else {
|
||||
fmt.Println("Error retrieving value from cache:", err)
|
||||
}
|
||||
if err := checkFaucetAddress(r.FormValue("address")); err != nil {
|
||||
tData.Msg = fmt.Sprintf("Invalid address: %s", err)
|
||||
|
@ -304,7 +318,7 @@ func (z *Zfaucet) home(w http.ResponseWriter, r *http.Request) {
|
|||
tData.Msg = fmt.Sprintf("Failed to send funds: %s", err)
|
||||
break
|
||||
}
|
||||
tData.Msg = fmt.Sprintf("Successfully submitted operation: %s", opStatus)
|
||||
tData.Msg = fmt.Sprintf("Successfully submitted operation, transaction: %s", opStatus.TxID)
|
||||
}
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
tmpl, err := template.New("name").Parse(z.ZfaucetHTML)
|
||||
|
@ -340,18 +354,26 @@ func (z *Zfaucet) balance(w http.ResponseWriter, r *http.Request) {
|
|||
|
||||
// opsStatus
|
||||
func (z *Zfaucet) opsStatus(w http.ResponseWriter, r *http.Request) {
|
||||
w.Header().Set("Content-Type", "application/json")
|
||||
var ops *[]string
|
||||
if err := z.RPCConnetion.CallFor(&ops, "z_listoperationids"); err != nil {
|
||||
// tData is the html template data
|
||||
tData := struct {
|
||||
Z *Zfaucet
|
||||
Ops *[]string
|
||||
Type string
|
||||
}{
|
||||
z,
|
||||
nil,
|
||||
"opsStatus",
|
||||
}
|
||||
if err := z.RPCConnetion.CallFor(&tData.Ops, "z_listoperationids"); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
out, err := json.Marshal(ops)
|
||||
w.Header().Set("Content-Type", "text/html")
|
||||
tmpl, err := template.New("name").Parse(z.ZfaucetHTML)
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
return
|
||||
}
|
||||
fmt.Fprintf(w, string(out))
|
||||
tmpl.Execute(w, tData)
|
||||
}
|
||||
|
||||
// addresses
|
||||
|
|
Loading…
Reference in New Issue