Add faucet command (#93)

* added faucet command

* chopsticks ports imported from env

* changed order of assignments

* test: sleep after start nigiri

* sleep after each strat and each stop

* small changes on faucet

* added check for txId

* json err control

* correcting json err control

* small fixes

* fixes on faucet command

* http.StatusOK

* try with 0.0.0.0 interface

* try with 127.0.0.1 interface

* fixes in travis

Co-authored-by: Marco Argentieri <3596602+tiero@users.noreply.github.com>
This commit is contained in:
Francis
2020-09-11 19:13:43 +01:00
committed by GitHub
parent 7305077cff
commit 88fca5db00
5 changed files with 202 additions and 1 deletions

View File

@@ -9,4 +9,4 @@ script:
- if [ -n "$(gofmt -l .)" ]; then echo "Go code is not formatted"; exit 1; fi
- bash scripts/install
- sudo chmod -R 777 .
- go test -v ./...
- go test -short -v ./...

109
cli/cmd/faucet.go Normal file
View File

@@ -0,0 +1,109 @@
package cmd
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"io/ioutil"
"net/http"
"strconv"
"github.com/spf13/cobra"
"github.com/vulpemventures/nigiri/cli/constants"
"github.com/vulpemventures/nigiri/cli/controller"
)
var FaucetCmd = &cobra.Command{
Args: func(cmd *cobra.Command, args []string) error {
if len(args) != 1 {
return errors.New("Insert receiving address")
}
return nil
},
Use: "faucet <address>",
Short: "Generate and send bitcoin to given address",
RunE: faucet,
PreRunE: faucetChecks,
}
func faucetChecks(cmd *cobra.Command, args []string) error {
datadir, _ := cmd.Flags().GetString("datadir")
isLiquidService, _ := cmd.Flags().GetBool("liquid")
ctl, err := controller.NewController()
if err != nil {
return err
}
if err := ctl.ParseDatadir(datadir); err != nil {
return err
}
if len(args) != 1 {
return constants.ErrInvalidArgs
}
if isRunning, err := ctl.IsNigiriRunning(); err != nil {
return err
} else if !isRunning {
return constants.ErrNigiriNotRunning
}
if err := ctl.ReadConfigFile(datadir); err != nil {
return err
}
if isLiquidService && isLiquidService != ctl.GetConfigBoolField(constants.AttachLiquid) {
return constants.ErrNigiriLiquidNotEnabled
}
return nil
}
func faucet(cmd *cobra.Command, address []string) error {
isLiquidService, err := cmd.Flags().GetBool("liquid")
datadir, _ := cmd.Flags().GetString("datadir")
if err != nil {
return err
}
request := map[string]string{
"address": address[0],
}
ctl, err := controller.NewController()
if err != nil {
return err
}
envPath := ctl.GetResourcePath(datadir, "env")
env, _ := ctl.ReadComposeEnvironment(envPath)
envPorts := env["ports"].(map[string]map[string]int)
requestPort := envPorts["bitcoin"]["chopsticks"]
if isLiquidService {
requestPort = envPorts["liquid"]["chopsticks"]
}
payload, err := json.Marshal(request)
if err != nil {
return err
}
res, err := http.Post("http://127.0.0.1:"+strconv.Itoa(requestPort)+"/faucet", "application/json", bytes.NewBuffer(payload))
if err != nil {
return err
}
data, err := ioutil.ReadAll(res.Body)
if err != nil {
return err
}
if res.StatusCode != http.StatusOK {
return errors.New(string(data))
}
var dat map[string]string
if err := json.Unmarshal([]byte(data), &dat); err != nil {
return errors.New("Internal error. Try again.")
}
if dat["txId"] == "" {
return errors.New("Not Successful")
}
fmt.Println("txId: " + dat["txId"])
return nil
}

81
cli/cmd/faucet_test.go Normal file
View File

@@ -0,0 +1,81 @@
package cmd
import (
"testing"
"github.com/vulpemventures/nigiri/cli/constants"
)
const (
btcAddress = "mpSGWQvbAiRt2UNLST1CdWUufoPVsVwLyK"
liquidAddress = "CTEsqL1x9ooWWG9HBaHUpvS2DGJJ4haYdkTQPKj9U8CCdwT5vcudhbYUT8oQwwoS11aYtdznobfgT8rj"
)
func TestFaucetBitcoinServices(t *testing.T) {
if testing.Short() {
t.Skip("skipping testing in short mode")
}
testStart(t, bitcoin)
if err := testCommand("faucet", btcAddress, bitcoin); err != nil {
t.Fatal(err)
}
testDelete(t)
}
func TestFaucetLiquidServices(t *testing.T) {
if testing.Short() {
t.Skip("skipping testing in short mode")
}
testStart(t, liquid)
if err := testCommand("faucet", liquidAddress, liquid); err != nil {
t.Fatal(err)
}
testDelete(t)
}
func TestFaucetShouldFail(t *testing.T) {
if testing.Short() {
t.Skip("skipping testing in short mode")
}
expectedError := constants.ErrNigiriNotRunning.Error()
err := testCommand("faucet", btcAddress, bitcoin)
if err == nil {
t.Fatal("Should return error when Nigiri is stopped")
}
if err.Error() != expectedError {
t.Fatalf("Expected error: %s, got: %s", expectedError, err)
}
err = testCommand("faucet", liquidAddress, liquid)
if err == nil {
t.Fatal("Should return error when Nigiri is stopped")
}
if err.Error() != expectedError {
t.Fatalf("Expected error: %s, got: %s", expectedError, err)
}
}
func TestStartBitcoinAndFaucetNigiriServicesShouldFail(t *testing.T) {
if testing.Short() {
t.Skip("skipping testing in short mode")
}
testStart(t, bitcoin)
expectedError := constants.ErrNigiriLiquidNotEnabled.Error()
err := testCommand("faucet", liquidAddress, liquid)
if err == nil {
t.Fatal("Should return error when trying logging liquid services if not running")
}
if err.Error() != expectedError {
t.Fatalf("Expected error: %s, got: %s", expectedError, err)
}
testDelete(t)
}

View File

@@ -38,10 +38,12 @@ func init() {
StartCmd.PersistentFlags().StringVar(&flagEnv, "env", string(defaultJSON), "Set compose env in JSON format")
StopCmd.PersistentFlags().BoolVar(&flagDelete, "delete", false, "Stop and delete nigiri")
LogsCmd.PersistentFlags().BoolVar(&flagLiquidService, "liquid", false, "Set to see logs of a liquid service")
FaucetCmd.PersistentFlags().BoolVar(&flagLiquidService, "liquid", false, "Set to donate liquid btc")
RootCmd.AddCommand(StartCmd)
RootCmd.AddCommand(StopCmd)
RootCmd.AddCommand(LogsCmd)
RootCmd.AddCommand(FaucetCmd)
viper.BindPFlag(constants.Datadir, RootCmd.PersistentFlags().Lookup("datadir"))
viper.BindPFlag(constants.Network, StartCmd.PersistentFlags().Lookup("network"))

View File

@@ -3,6 +3,7 @@ package cmd
import (
"fmt"
"testing"
"time"
"github.com/vulpemventures/nigiri/cli/constants"
"github.com/vulpemventures/nigiri/cli/controller"
@@ -96,6 +97,8 @@ func testStart(t *testing.T, flag bool) {
if err := testCommand("start", "", flag); err != nil {
t.Fatal(err)
}
//Give some time to nigiri to be ready before calling
time.Sleep(5 * time.Second)
if isRunning, err := ctl.IsNigiriRunning(); err != nil {
t.Fatal(err)
} else if !isRunning {
@@ -111,6 +114,8 @@ func testStop(t *testing.T) {
if err := testCommand("stop", "", !delete); err != nil {
t.Fatal(err)
}
//Give some time to nigiri to be ready before calling
time.Sleep(5 * time.Second)
if isStopped, err := ctl.IsNigiriStopped(); err != nil {
t.Fatal(err)
} else if !isStopped {
@@ -150,6 +155,10 @@ func testCommand(command, arg string, flag bool) error {
logsCmd := []string{command, arg, fmt.Sprintf("--liquid=%t", flag)}
cmd.SetArgs(logsCmd)
}
if command == "faucet" {
faucetCmd := []string{command, arg, fmt.Sprintf("--liquid=%t", flag)}
cmd.SetArgs(faucetCmd)
}
if err := cmd.Execute(); err != nil {
return err