2019-09-20 21:27:40 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"net/http"
|
|
|
|
"os"
|
|
|
|
|
|
|
|
logging "github.com/ipfs/go-log"
|
|
|
|
"golang.org/x/xerrors"
|
|
|
|
"gopkg.in/urfave/cli.v2"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/go-lotus/api"
|
|
|
|
"github.com/filecoin-project/go-lotus/build"
|
|
|
|
"github.com/filecoin-project/go-lotus/chain/address"
|
|
|
|
"github.com/filecoin-project/go-lotus/chain/types"
|
|
|
|
lcli "github.com/filecoin-project/go-lotus/cli"
|
|
|
|
)
|
|
|
|
|
|
|
|
var log = logging.Logger("main")
|
|
|
|
|
2019-09-25 18:40:10 +00:00
|
|
|
var sendPerRequest = types.NewInt(500_000_000)
|
2019-09-20 21:27:40 +00:00
|
|
|
|
|
|
|
func main() {
|
|
|
|
logging.SetLogLevel("*", "INFO")
|
|
|
|
|
|
|
|
log.Info("Starting fountain")
|
|
|
|
|
|
|
|
local := []*cli.Command{
|
|
|
|
runCmd,
|
|
|
|
}
|
|
|
|
|
|
|
|
app := &cli.App{
|
|
|
|
Name: "lotus-fountain",
|
|
|
|
Usage: "Devnet token distribution utility",
|
|
|
|
Version: build.Version,
|
|
|
|
Flags: []cli.Flag{
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "repo",
|
|
|
|
EnvVars: []string{"LOTUS_PATH"},
|
|
|
|
Value: "~/.lotus", // TODO: Consider XDG_DATA_HOME
|
|
|
|
},
|
|
|
|
},
|
|
|
|
|
|
|
|
Commands: local,
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := app.Run(os.Args); err != nil {
|
|
|
|
log.Warn(err)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
var runCmd = &cli.Command{
|
|
|
|
Name: "run",
|
|
|
|
Usage: "Start lotus fountain",
|
|
|
|
Flags: []cli.Flag{
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "front",
|
|
|
|
Value: "127.0.0.1:7777",
|
|
|
|
},
|
|
|
|
&cli.StringFlag{
|
|
|
|
Name: "from",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
Action: func(cctx *cli.Context) error {
|
2019-10-04 22:43:04 +00:00
|
|
|
nodeApi, closer, err := lcli.GetFullNodeAPI(cctx)
|
2019-09-20 21:27:40 +00:00
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
2019-10-04 16:02:25 +00:00
|
|
|
defer closer()
|
2019-09-20 21:27:40 +00:00
|
|
|
ctx := lcli.ReqContext(cctx)
|
|
|
|
|
|
|
|
v, err := nodeApi.Version(ctx)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
|
|
|
|
log.Info("Remote version: %s", v.Version)
|
|
|
|
|
|
|
|
from, err := address.NewFromString(cctx.String("from"))
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("parsing source address (provide correct --from flag!): %w", err)
|
|
|
|
}
|
|
|
|
|
|
|
|
h := &handler{
|
|
|
|
ctx: ctx,
|
|
|
|
api: nodeApi,
|
|
|
|
from: from,
|
|
|
|
}
|
|
|
|
|
|
|
|
http.HandleFunc("/", h.index)
|
|
|
|
http.HandleFunc("/send", h.send)
|
|
|
|
|
|
|
|
fmt.Printf("Open http://%s\n", cctx.String("front"))
|
|
|
|
|
|
|
|
go func() {
|
|
|
|
<-ctx.Done()
|
|
|
|
os.Exit(0)
|
|
|
|
}()
|
|
|
|
|
|
|
|
return http.ListenAndServe(cctx.String("front"), nil)
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
type handler struct {
|
|
|
|
ctx context.Context
|
|
|
|
api api.FullNode
|
|
|
|
|
|
|
|
from address.Address
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *handler) index(w http.ResponseWriter, r *http.Request) {
|
|
|
|
fmt.Fprintf(w, "<!DOCTYPE html>\n<html><head><title>Lotus Fountain</title><style>body {font-family: 'monospace';}</style></head><body>")
|
|
|
|
fmt.Fprintf(w, "<form action='/send' method='get'>Enter destination address: ")
|
|
|
|
fmt.Fprintf(w, "<input type='text' name='address'><br><button type='submit'>Send</button>")
|
|
|
|
fmt.Fprintf(w, "</form></body></html>")
|
|
|
|
}
|
|
|
|
|
|
|
|
func (h *handler) send(w http.ResponseWriter, r *http.Request) {
|
|
|
|
to, err := address.NewFromString(r.FormValue("address"))
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(400)
|
|
|
|
w.Write([]byte(err.Error()))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
smsg, err := h.api.MpoolPushMessage(h.ctx, &types.Message{
|
|
|
|
Value: sendPerRequest,
|
|
|
|
From: h.from,
|
|
|
|
To: to,
|
|
|
|
|
|
|
|
GasPrice: types.NewInt(0),
|
|
|
|
GasLimit: types.NewInt(1000),
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
w.WriteHeader(400)
|
|
|
|
w.Write([]byte(err.Error()))
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
w.Write([]byte(smsg.Cid().String()))
|
|
|
|
}
|