Skip to content

Commit 90c80aa

Browse files
authored
Merge pull request #153 from NodeFactoryIo/mmuftic/send-all-funds-on-payout
Send all funds on payout
2 parents cce3ec7 + fb9dd4b commit 90c80aa

15 files changed

Lines changed: 357 additions & 74 deletions

File tree

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
- Support WS connections [#\132](https://github.com/NodeFactoryIo/vedran/pull/132) ([MakMuftic](https://github.com/MakMuftic))
2929
- Execute payout transactions [\#127](https://github.com/NodeFactoryIo/vedran/pull/127) ([MakMuftic](https://github.com/MakMuftic))
3030
- Sign stats request [\#143](https://github.com/NodeFactoryIo/vedran/pull/143) ([MakMuftic](https://github.com/MakMuftic))
31+
- Send all funds on payout [\#153](https://github.com/NodeFactoryIo/vedran/pull/153) ([MakMuftic](https://github.com/MakMuftic))
3132

3233
### Fix
3334
- Fix payout [\#148](https://github.com/NodeFactoryIo/vedran/pull/148) ([MakMuftic](https://github.com/MakMuftic))

README.md

Lines changed: 12 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ Start command will start application on 2 ports that need to be exposed to publi
119119
|`--selection`|type of selection that is used for selecting nodes on new request, valid values are `round-robin` and `random`|`round-robin`|
120120
|`--payout-interval`|automatic payout interval specified as number of days, for more details see [payout instructions](#payouts)|-|
121121
|`--payout-reward`|defined reward amount that will be distributed on the payout (amount in Planck), for more details see [payout instructions](#payouts)|-|
122+
|`--lb-payout-address`|address on which load balancer fee will be sent|-|
122123
|`--log-level`|log level (debug, info, warn, error)|error|
123124
|`--log-file`|path to file in which logs will be saved|`stdout`|
124125

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

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

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

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

141-
`--payout-reward` - defined total reward amount that will be distributed on the payout (amount in Planck)
142+
`--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
143+
144+
`--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)
142145

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

145148
### Manual payout
146149

147-
It is possible to run payout script at any time by invoking `vedran payout` command trough console.
148-
This command has two required flags:
150+
It is possible to run payout script at any time by invoking `vedran payout` command through the console.
151+
152+
`--private-key` - loadbalancers wallet private key (string representation of hex value prefixed with 0x), used for sending rewards on the payout
149153

150-
`--private-key` - loadbalancers wallet private key (string representation of hex value prefixed with 0x), used for sending founds on payout
154+
`--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
151155

152-
`--payout-reward` - defined total reward amount that will be distributed on the payout (amount in Planck)
156+
`--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)
153157

154-
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_)
158+
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_)
155159

156-
`--load-balancer-url` - loadbalancer url
160+
`--load-balancer-url` - loadbalancer URL
157161

158162
### Get private key
159163
You can use [subkey](https://substrate.dev/docs/en/knowledgebase/integrate/subkey) tool to get private key for your wallet.

cmd/payout.go

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
package cmd
22

33
import (
4-
"errors"
54
"fmt"
65
"github.com/NodeFactoryIo/vedran/internal/script"
76
"github.com/NodeFactoryIo/vedran/internal/ui"
87
log "github.com/sirupsen/logrus"
98
"github.com/spf13/cobra"
109
"net/url"
11-
"strconv"
1210
)
1311

1412
var (
1513
privateKey string
1614
totalReward string
1715
rawLoadbalancerUrl string
16+
feeAddress string
1817

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

3433
loadbalancerURL, err = url.Parse(rawLoadbalancerUrl)
3534
if err != nil {
@@ -50,25 +49,31 @@ func init() {
5049
payoutCmd.Flags().StringVar(
5150
&totalReward,
5251
"payout-reward",
53-
"",
52+
"-1",
5453
"[REQUIRED] total reward pool in Planck",
5554
)
5655
payoutCmd.Flags().StringVar(
5756
&rawLoadbalancerUrl,
5857
"load-balancer-url",
5958
"http://localhost:80",
60-
"[OPTIONAL] url on which loadbalancer is listening")
59+
"[OPTIONAL] url on which loadbalancer is listening",
60+
)
61+
startCmd.Flags().StringVar(
62+
&feeAddress,
63+
"lb-payout-fee-address",
64+
"",
65+
"[OPTIONAL] Address on which load balancer fee will be sent. If omitted, load balancer fee will be left on load balancer wallet after payout",
66+
)
6167

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

6570
RootCmd.AddCommand(payoutCmd)
6671
}
6772

6873
func payoutCommand(_ *cobra.Command, _ []string) {
6974
DisplayBanner()
7075
fmt.Println("Payout script running...")
71-
transactions, err := script.ExecutePayout(privateKey, totalRewardAsFloat64, loadbalancerURL)
76+
transactions, err := script.ExecutePayout(privateKey, totalRewardAsFloat64, feeAddress, loadbalancerURL)
7277
if transactions != nil {
7378
// display even if only part of transactions executed
7479
ui.DisplayTransactionsStatus(transactions)

cmd/start.go

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ var (
3636
serverPort int32
3737
publicIP string
3838
// payout related flags
39+
payoutFeeAddress string
3940
payoutPrivateKey string
4041
payoutNumberOfDays int32
4142
payoutTotalReward string
@@ -110,14 +111,14 @@ var startCmd = &cobra.Command{
110111
return errors.New("only one flag for setting whitelisted nodes should be set")
111112
}
112113

113-
autoPayoutDisabled = payoutNumberOfDays == 0 && payoutTotalReward == ""
114+
autoPayoutDisabled = payoutNumberOfDays == 0
114115
if !autoPayoutDisabled {
115116
if payoutNumberOfDays <= 0 {
116117
return errors.New("invalid payout interval")
117118
}
118-
rewardAsFloat64, err := strconv.ParseFloat(payoutTotalReward, 64)
119+
rewardAsFloat64, err := ValidatePayoutFlags(payoutTotalReward, payoutFeeAddress, false)
119120
if err != nil {
120-
return errors.New("invalid total reward value")
121+
return err
121122
}
122123
payoutTotalRewardAsFloat64 = rewardAsFloat64
123124
}
@@ -223,22 +224,28 @@ func init() {
223224
&payoutPrivateKey,
224225
"private-key",
225226
"",
226-
"[REQUIRED] Loadbalancers wallet private key, used for sending funds on payout",
227+
"[REQUIRED] Load balancers wallet private key, used for sending funds on payout",
227228
)
228229

230+
startCmd.Flags().StringVar(
231+
&payoutTotalReward,
232+
"payout-reward",
233+
"-1",
234+
"[OPTIONAL] Total reward pool in Planck. If omitted, total balance of load balancer wallet will be considered as payout reward",
235+
)
236+
237+
startCmd.Flags().StringVar(
238+
&payoutFeeAddress,
239+
"lb-payout-address",
240+
"",
241+
"[OPTIONAL] Address on which load balancer fee will be sent. If omitted, load balancer fee will be left on load balancer wallet after payout")
242+
229243
startCmd.Flags().Int32Var(
230244
&payoutNumberOfDays,
231245
"payout-interval",
232246
0,
233247
"[OPTIONAL] Payout interval in days, meaning each X days automatic payout will be executed")
234248

235-
startCmd.Flags().StringVar(
236-
&payoutTotalReward,
237-
"payout-reward",
238-
"",
239-
"[OPTIONAL] Total reward pool in Planck",
240-
)
241-
242249
_ = startCmd.MarkFlagRequired("private-key")
243250

244251
RootCmd.AddCommand(startCmd)
@@ -280,6 +287,7 @@ func startCommand(_ *cobra.Command, _ []string) {
280287
payoutConfiguration = &schedulepayout.PayoutConfiguration{
281288
PayoutNumberOfDays: int(payoutNumberOfDays),
282289
PayoutTotalReward: payoutTotalRewardAsFloat64,
290+
LbFeeAddress: payoutFeeAddress,
283291
LbURL: lbUrl,
284292
}
285293
}

cmd/validation.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package cmd
2+
3+
import (
4+
"errors"
5+
"fmt"
6+
"github.com/NodeFactoryIo/vedran/internal/ui/prompts"
7+
"strconv"
8+
)
9+
10+
func ValidatePayoutFlags(
11+
payoutReward string,
12+
payoutAddress string,
13+
showPrompts bool,
14+
) (float64, error) {
15+
var err error
16+
var rewardAsFloat64 float64
17+
18+
// if total reward is determined as wallet balance
19+
if payoutReward == "-1" {
20+
if payoutAddress == "" {
21+
return 0, errors.New("Unable to set reward amount to entire wallet balance if fee address not provided")
22+
} else {
23+
if showPrompts {
24+
confirmed, err := prompts.ShowConfirmationPrompt(
25+
fmt.Sprintf("You choose that reward amount is defined as entire balance on lb wallet!" +
26+
"On payout entire balance will be distributed as reward and lb fee will be sent to address %s",
27+
payoutAddress),
28+
)
29+
if err != nil {
30+
return 0, err
31+
}
32+
if !confirmed {
33+
return 0, errors.New("Payout configuration canceled")
34+
}
35+
}
36+
}
37+
} else {
38+
rewardAsFloat64, err = strconv.ParseFloat(payoutReward, 64)
39+
if err != nil || rewardAsFloat64 < -1 {
40+
return 0, errors.New("invalid total reward value")
41+
}
42+
}
43+
44+
return rewardAsFloat64, nil
45+
}

cmd/validation_test.go

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
package cmd
2+
3+
import (
4+
"github.com/stretchr/testify/assert"
5+
"testing"
6+
)
7+
8+
func TestValidatePayoutFlags(t *testing.T) {
9+
tests := []struct {
10+
name string
11+
payoutReward string
12+
payoutAddress string
13+
validateReturns float64
14+
validateError bool
15+
}{
16+
{
17+
name: "valid flags",
18+
payoutReward: "1000",
19+
payoutAddress: "",
20+
validateReturns: float64(1000),
21+
validateError: false,
22+
},
23+
{
24+
name: "invalid flags, missing reward address",
25+
payoutReward: "-1",
26+
payoutAddress: "",
27+
validateReturns: float64(0),
28+
validateError: true,
29+
},
30+
{
31+
name: "invalid flags, negative reward",
32+
payoutReward: "-100",
33+
payoutAddress: "",
34+
validateReturns: float64(0),
35+
validateError: true,
36+
},
37+
}
38+
for _, test := range tests {
39+
t.Run(test.name, func(t *testing.T) {
40+
rewAsFloat64, err := ValidatePayoutFlags(test.payoutReward, test.payoutAddress, false)
41+
assert.Equal(t, test.validateReturns, rewAsFloat64)
42+
if test.validateError {
43+
assert.Error(t, err)
44+
} else {
45+
assert.NoError(t, err)
46+
}
47+
})
48+
}
49+
}

go.mod

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ require (
1515
github.com/gorilla/websocket v1.4.1
1616
github.com/gosuri/uitable v0.0.4
1717
github.com/inconshreveable/go-vhost v0.0.0-20160627193104-06d84117953b
18+
github.com/manifoldco/promptui v0.8.0
1819
github.com/pkg/errors v0.8.1
1920
github.com/sirupsen/logrus v1.6.0
2021
github.com/spf13/cobra v1.0.0

go.sum

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QH
4949
github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s=
5050
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
5151
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
52+
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
53+
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e h1:fY5BOSpyZCqRo5OhCuC+XN+r/bBCmeuuJtjz+bCNIf8=
54+
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
55+
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
5256
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
5357
github.com/cloudflare/cloudflare-go v0.10.2-0.20190916151808-a80f83b9add9/go.mod h1:1MxXX1Ux4x6mqPmjkUgTP1CdXIBXKX7T+Jk9Gxrmx+U=
5458
github.com/coreos/bbolt v1.3.2/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
@@ -176,6 +180,8 @@ github.com/influxdata/influxdb v1.2.3-0.20180221223340-01288bdb0883/go.mod h1:qZ
176180
github.com/jackpal/go-nat-pmp v1.0.2-0.20160603034137-1fa385a6f458/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
177181
github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
178182
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
183+
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a h1:FaWFmfWdAUKbSCtOU2QjDaorUexogfaMgbipgYATUMU=
184+
github.com/juju/ansiterm v0.0.0-20180109212912-720a0952cc2a/go.mod h1:UJSiEoRfvx3hP73CvoARgeLjaIOjybY9vj8PUPPFGeU=
179185
github.com/julienschmidt/httprouter v1.1.1-0.20170430222011-975b5c4c7c21/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
180186
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
181187
github.com/karalabe/usb v0.0.0-20190919080040-51dc0efba356/go.mod h1:Od972xHfMJowv7NGVDiWVxk2zxnWgjLlJzE+F4F7AGU=
@@ -194,14 +200,20 @@ github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
194200
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
195201
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
196202
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
203+
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a h1:weJVJJRzAJBFRlAiJQROKQs8oC9vOxvm4rZmBBk0ONw=
204+
github.com/lunixbochs/vtclean v0.0.0-20180621232353-2d01aacdc34a/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
197205
github.com/magiconair/properties v1.7.4-0.20170902060319-8d7837e64d3c/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
198206
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
207+
github.com/manifoldco/promptui v0.8.0 h1:R95mMF+McvXZQ7j1g8ucVZE1gLP3Sv6j9vlF9kyRqQo=
208+
github.com/manifoldco/promptui v0.8.0/go.mod h1:n4zTdgP0vr0S3w7/O/g98U+e0gwLScEXGwov2nIKuGQ=
209+
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
199210
github.com/mattn/go-colorable v0.0.10-0.20170816031813-ad5389df28cd/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
200211
github.com/mattn/go-colorable v0.1.0 h1:v2XXALHHh6zHfYTJ+cSkwtyffnaOyR1MXaA91mTrb8o=
201212
github.com/mattn/go-colorable v0.1.0/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
202213
github.com/mattn/go-ieproxy v0.0.0-20190610004146-91bb50d98149/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
203214
github.com/mattn/go-ieproxy v0.0.0-20190702010315-6dee0af9227d/go.mod h1:31jz6HNzdxOmlERGGEc4v/dMssOfmp2p5bT/okiKFFc=
204215
github.com/mattn/go-isatty v0.0.2/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
216+
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
205217
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035 h1:USWjF42jDCSEeikX/G1g40ZWnsPXN5WkZ4jMHZWyBK4=
206218
github.com/mattn/go-isatty v0.0.5-0.20180830101745-3fb116b82035/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
207219
github.com/mattn/go-runewidth v0.0.3/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU=
@@ -362,6 +374,7 @@ golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5h
362374
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
363375
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
364376
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
377+
golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
365378
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
366379
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
367380
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=

internal/api/api.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
package api
2+
3+
import (
4+
gsrpc "github.com/NodeFactoryIo/go-substrate-rpc-client"
5+
"github.com/NodeFactoryIo/go-substrate-rpc-client/types"
6+
)
7+
8+
func InitializeSubstrateAPI(substrateRPCUrl string) (*gsrpc.SubstrateAPI, error) {
9+
api, err := gsrpc.NewSubstrateAPI(substrateRPCUrl)
10+
if err != nil {
11+
return nil, err
12+
}
13+
14+
opts := types.SerDeOptions{NoPalletIndices: true}
15+
types.SetSerDeOptions(opts)
16+
17+
return api, nil
18+
}

0 commit comments

Comments
 (0)