Skip to content

Commit

Permalink
Merge pull request #153 from NodeFactoryIo/mmuftic/send-all-funds-on-…
Browse files Browse the repository at this point in the history
…payout

Send all funds on payout
  • Loading branch information
mpetrunic authored Dec 22, 2020
2 parents cce3ec7 + fb9dd4b commit 90c80aa
Show file tree
Hide file tree
Showing 15 changed files with 357 additions and 74 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
- Support WS connections [#\132](https://github.com/NodeFactoryIo/vedran/pull/132) ([MakMuftic](https://github.com/MakMuftic))
- Execute payout transactions [\#127](https://github.com/NodeFactoryIo/vedran/pull/127) ([MakMuftic](https://github.com/MakMuftic))
- Sign stats request [\#143](https://github.com/NodeFactoryIo/vedran/pull/143) ([MakMuftic](https://github.com/MakMuftic))
- Send all funds on payout [\#153](https://github.com/NodeFactoryIo/vedran/pull/153) ([MakMuftic](https://github.com/MakMuftic))

### Fix
- Fix payout [\#148](https://github.com/NodeFactoryIo/vedran/pull/148) ([MakMuftic](https://github.com/MakMuftic))
Expand Down
20 changes: 12 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ Start command will start application on 2 ports that need to be exposed to publi
|`--selection`|type of selection that is used for selecting nodes on new request, valid values are `round-robin` and `random`|`round-robin`|
|`--payout-interval`|automatic payout interval specified as number of days, for more details see [payout instructions](#payouts)|-|
|`--payout-reward`|defined reward amount that will be distributed on the payout (amount in Planck), for more details see [payout instructions](#payouts)|-|
|`--lb-payout-address`|address on which load balancer fee will be sent|-|
|`--log-level`|log level (debug, info, warn, error)|error|
|`--log-file`|path to file in which logs will be saved|`stdout`|

Expand All @@ -134,26 +135,29 @@ For Westend's WND tokens, see the faucet [instructions on the Wiki](https://wiki

When starting _vedran loadbalancer_ it is possible to configure automatic payout by providing these flags:

`--private-key` - loadbalancers wallet private key (string representation of hex value prefixed with 0x), used for sending rewards on payout
`--private-key` - loadbalancers wallet private key (string representation of hex value prefixed with 0x), used for sending rewards on the payout

`--payout-interval` - automatic payout interval specified as number of days

`--payout-reward` - defined total reward amount that will be distributed on the payout (amount in Planck)
`--payout-reward` - defined total reward amount that will be distributed on the payout (amount in Planck). If omitted, the entire balance of lb wallet will be used as a total reward, and in this case `--lb-payout-fee-address` must be set

`--lb-payout-address` - address on which load balancer fee will be sent. If omitted, load balancer fee will be left on load balancer wallet after payout. This flag is **required** if `--payout-reward` is not set (or set to -1)

If all flags have been provided, then each {_payout-interval_} days automatic payout will be started.

### Manual payout

It is possible to run payout script at any time by invoking `vedran payout` command trough console.
This command has two required flags:
It is possible to run payout script at any time by invoking `vedran payout` command through the console.

`--private-key` - loadbalancers wallet private key (string representation of hex value prefixed with 0x), used for sending rewards on the payout

`--private-key` - loadbalancers wallet private key (string representation of hex value prefixed with 0x), used for sending founds on payout
`--payout-reward` - defined total reward amount that will be distributed on the payout (amount in Planck). If omitted, the entire balance of lb wallet will be used as a total reward, and in this case `--lb-payout-fee-address` must be set

`--payout-reward` - defined total reward amount that will be distributed on the payout (amount in Planck)
`--lb-payout-fee-address` - address on which load balancer fee will be sent. If omitted, load balancer fee will be left on load balancer wallet after payout. This flag is **required** if `--payout-reward` is not set (or set to -1)

Additionally, it is possible to change url on which payout script will connect with loadbalancer when executing transactions by setting flag (default value will be _http://localhost:80_)
Additionally, it is possible to change URL on which payout script will connect with loadbalancer when executing transactions by setting flag (default value will be _http://localhost:80_)

`--load-balancer-url` - loadbalancer url
`--load-balancer-url` - loadbalancer URL

### Get private key
You can use [subkey](https://substrate.dev/docs/en/knowledgebase/integrate/subkey) tool to get private key for your wallet.
Expand Down
23 changes: 14 additions & 9 deletions cmd/payout.go
Original file line number Diff line number Diff line change
@@ -1,20 +1,19 @@
package cmd

import (
"errors"
"fmt"
"github.com/NodeFactoryIo/vedran/internal/script"
"github.com/NodeFactoryIo/vedran/internal/ui"
log "github.com/sirupsen/logrus"
"github.com/spf13/cobra"
"net/url"
"strconv"
)

var (
privateKey string
totalReward string
rawLoadbalancerUrl string
feeAddress string

loadbalancerURL *url.URL
totalRewardAsFloat64 float64
Expand All @@ -25,11 +24,11 @@ var payoutCmd = &cobra.Command{
Short: "Starts payout script",
Run: payoutCommand,
Args: func(cmd *cobra.Command, args []string) error {
result, err := strconv.ParseFloat(totalReward, 64)
var err error
totalRewardAsFloat64, err = ValidatePayoutFlags(totalReward, feeAddress, true)
if err != nil {
return errors.New("invalid total reward value")
return err
}
totalRewardAsFloat64 = result

loadbalancerURL, err = url.Parse(rawLoadbalancerUrl)
if err != nil {
Expand All @@ -50,25 +49,31 @@ func init() {
payoutCmd.Flags().StringVar(
&totalReward,
"payout-reward",
"",
"-1",
"[REQUIRED] total reward pool in Planck",
)
payoutCmd.Flags().StringVar(
&rawLoadbalancerUrl,
"load-balancer-url",
"http://localhost:80",
"[OPTIONAL] url on which loadbalancer is listening")
"[OPTIONAL] url on which loadbalancer is listening",
)
startCmd.Flags().StringVar(
&feeAddress,
"lb-payout-fee-address",
"",
"[OPTIONAL] Address on which load balancer fee will be sent. If omitted, load balancer fee will be left on load balancer wallet after payout",
)

_ = startCmd.MarkFlagRequired("private-key")
_ = startCmd.MarkFlagRequired("payout-reward")

RootCmd.AddCommand(payoutCmd)
}

func payoutCommand(_ *cobra.Command, _ []string) {
DisplayBanner()
fmt.Println("Payout script running...")
transactions, err := script.ExecutePayout(privateKey, totalRewardAsFloat64, loadbalancerURL)
transactions, err := script.ExecutePayout(privateKey, totalRewardAsFloat64, feeAddress, loadbalancerURL)
if transactions != nil {
// display even if only part of transactions executed
ui.DisplayTransactionsStatus(transactions)
Expand Down
30 changes: 19 additions & 11 deletions cmd/start.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ var (
serverPort int32
publicIP string
// payout related flags
payoutFeeAddress string
payoutPrivateKey string
payoutNumberOfDays int32
payoutTotalReward string
Expand Down Expand Up @@ -110,14 +111,14 @@ var startCmd = &cobra.Command{
return errors.New("only one flag for setting whitelisted nodes should be set")
}

autoPayoutDisabled = payoutNumberOfDays == 0 && payoutTotalReward == ""
autoPayoutDisabled = payoutNumberOfDays == 0
if !autoPayoutDisabled {
if payoutNumberOfDays <= 0 {
return errors.New("invalid payout interval")
}
rewardAsFloat64, err := strconv.ParseFloat(payoutTotalReward, 64)
rewardAsFloat64, err := ValidatePayoutFlags(payoutTotalReward, payoutFeeAddress, false)
if err != nil {
return errors.New("invalid total reward value")
return err
}
payoutTotalRewardAsFloat64 = rewardAsFloat64
}
Expand Down Expand Up @@ -223,22 +224,28 @@ func init() {
&payoutPrivateKey,
"private-key",
"",
"[REQUIRED] Loadbalancers wallet private key, used for sending funds on payout",
"[REQUIRED] Load balancers wallet private key, used for sending funds on payout",
)

startCmd.Flags().StringVar(
&payoutTotalReward,
"payout-reward",
"-1",
"[OPTIONAL] Total reward pool in Planck. If omitted, total balance of load balancer wallet will be considered as payout reward",
)

startCmd.Flags().StringVar(
&payoutFeeAddress,
"lb-payout-address",
"",
"[OPTIONAL] Address on which load balancer fee will be sent. If omitted, load balancer fee will be left on load balancer wallet after payout")

startCmd.Flags().Int32Var(
&payoutNumberOfDays,
"payout-interval",
0,
"[OPTIONAL] Payout interval in days, meaning each X days automatic payout will be executed")

startCmd.Flags().StringVar(
&payoutTotalReward,
"payout-reward",
"",
"[OPTIONAL] Total reward pool in Planck",
)

_ = startCmd.MarkFlagRequired("private-key")

RootCmd.AddCommand(startCmd)
Expand Down Expand Up @@ -280,6 +287,7 @@ func startCommand(_ *cobra.Command, _ []string) {
payoutConfiguration = &schedulepayout.PayoutConfiguration{
PayoutNumberOfDays: int(payoutNumberOfDays),
PayoutTotalReward: payoutTotalRewardAsFloat64,
LbFeeAddress: payoutFeeAddress,
LbURL: lbUrl,
}
}
Expand Down
45 changes: 45 additions & 0 deletions cmd/validation.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package cmd

import (
"errors"
"fmt"
"github.com/NodeFactoryIo/vedran/internal/ui/prompts"
"strconv"
)

func ValidatePayoutFlags(
payoutReward string,
payoutAddress string,
showPrompts bool,
) (float64, error) {
var err error
var rewardAsFloat64 float64

// if total reward is determined as wallet balance
if payoutReward == "-1" {
if payoutAddress == "" {
return 0, errors.New("Unable to set reward amount to entire wallet balance if fee address not provided")
} else {
if showPrompts {
confirmed, err := prompts.ShowConfirmationPrompt(
fmt.Sprintf("You choose that reward amount is defined as entire balance on lb wallet!" +
"On payout entire balance will be distributed as reward and lb fee will be sent to address %s",
payoutAddress),
)
if err != nil {
return 0, err
}
if !confirmed {
return 0, errors.New("Payout configuration canceled")
}
}
}
} else {
rewardAsFloat64, err = strconv.ParseFloat(payoutReward, 64)
if err != nil || rewardAsFloat64 < -1 {
return 0, errors.New("invalid total reward value")
}
}

return rewardAsFloat64, nil
}
49 changes: 49 additions & 0 deletions cmd/validation_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package cmd

import (
"github.com/stretchr/testify/assert"
"testing"
)

func TestValidatePayoutFlags(t *testing.T) {
tests := []struct {
name string
payoutReward string
payoutAddress string
validateReturns float64
validateError bool
}{
{
name: "valid flags",
payoutReward: "1000",
payoutAddress: "",
validateReturns: float64(1000),
validateError: false,
},
{
name: "invalid flags, missing reward address",
payoutReward: "-1",
payoutAddress: "",
validateReturns: float64(0),
validateError: true,
},
{
name: "invalid flags, negative reward",
payoutReward: "-100",
payoutAddress: "",
validateReturns: float64(0),
validateError: true,
},
}
for _, test := range tests {
t.Run(test.name, func(t *testing.T) {
rewAsFloat64, err := ValidatePayoutFlags(test.payoutReward, test.payoutAddress, false)
assert.Equal(t, test.validateReturns, rewAsFloat64)
if test.validateError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
}
})
}
}
1 change: 1 addition & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ require (
github.com/gorilla/websocket v1.4.1
github.com/gosuri/uitable v0.0.4
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b
github.com/manifoldco/promptui v0.8.0
github.com/pkg/errors v0.8.1
github.com/sirupsen/logrus v1.6.0
github.com/spf13/cobra v1.0.0
Expand Down
13 changes: 13 additions & 0 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,10 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
Expand Down Expand Up @@ -176,6 +180,8 @@ github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZ
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
Expand All @@ -194,14 +200,20 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o=
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4=
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
Expand Down Expand Up @@ -362,6 +374,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
Expand Down
18 changes: 18 additions & 0 deletions internal/api/api.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package api

import (
gsrpc "github.com/NodeFactoryIo/go-substrate-rpc-client"
"github.com/NodeFactoryIo/go-substrate-rpc-client/types"
)

func InitializeSubstrateAPI(substrateRPCUrl string) (*gsrpc.SubstrateAPI, error) {
api, err := gsrpc.NewSubstrateAPI(substrateRPCUrl)
if err != nil {
return nil, err
}

opts := types.SerDeOptions{NoPalletIndices: true}
types.SetSerDeOptions(opts)

return api, nil
}
Loading

0 comments on commit 90c80aa

Please sign in to comment.