mirror of https://github.com/certusone/santa.git
Merge pull request #1 from terra-project/develop
go version automatic feegiver
This commit is contained in:
commit
4dea694f47
|
@ -1,144 +1,24 @@
|
|||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
## Taken from https://github.com/github/gitignore/blob/master/Go.gitignore
|
||||
# Binaries for programs and plugins
|
||||
*.exe
|
||||
*.exe~
|
||||
*.dll
|
||||
*.so
|
||||
*.dylib
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
.DS_Store
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
# Test binary, build with `go test -c`
|
||||
*.test
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
# Output of the go coverage tool, specifically when used with LiteIDE
|
||||
*.out
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
# Ignore build directory
|
||||
build
|
||||
|
||||
# Grunt intermediate storage (http://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
# Ignore vendor directory
|
||||
vendor
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# TypeScript v1 declaration files
|
||||
typings/
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variables file
|
||||
.env
|
||||
|
||||
# next.js build output
|
||||
.next
|
||||
|
||||
node_modules/
|
||||
.node_modules/
|
||||
built/*
|
||||
tests/cases/rwc/*
|
||||
tests/cases/test262/*
|
||||
tests/cases/perf/*
|
||||
!tests/cases/webharness/compilerToString.js
|
||||
test-args.txt
|
||||
~*.docx
|
||||
\#*\#
|
||||
.\#*
|
||||
tests/baselines/local/*
|
||||
tests/baselines/local.old/*
|
||||
tests/services/baselines/local/*
|
||||
tests/baselines/prototyping/local/*
|
||||
tests/baselines/rwc/*
|
||||
tests/baselines/test262/*
|
||||
tests/baselines/reference/projectOutput/*
|
||||
tests/baselines/local/projectOutput/*
|
||||
tests/baselines/reference/testresults.tap
|
||||
tests/services/baselines/prototyping/local/*
|
||||
tests/services/browser/typescriptServices.js
|
||||
src/harness/*.js
|
||||
src/compiler/diagnosticInformationMap.generated.ts
|
||||
src/compiler/diagnosticMessages.generated.json
|
||||
src/parser/diagnosticInformationMap.generated.ts
|
||||
src/parser/diagnosticMessages.generated.json
|
||||
rwc-report.html
|
||||
*.swp
|
||||
build.json
|
||||
*.actual
|
||||
tests/webTestServer.js
|
||||
tests/webTestServer.js.map
|
||||
tests/webhost/*.d.ts
|
||||
tests/webhost/webtsc.js
|
||||
tests/cases/**/*.js
|
||||
tests/cases/**/*.js.map
|
||||
*.config
|
||||
scripts/debug.bat
|
||||
scripts/run.bat
|
||||
scripts/word2md.js
|
||||
scripts/buildProtocol.js
|
||||
scripts/ior.js
|
||||
scripts/authors.js
|
||||
scripts/configurePrerelease.js
|
||||
scripts/open-user-pr.js
|
||||
scripts/open-cherry-pick-pr.js
|
||||
scripts/processDiagnosticMessages.d.ts
|
||||
scripts/processDiagnosticMessages.js
|
||||
scripts/produceLKG.js
|
||||
scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js
|
||||
scripts/generateLocalizedDiagnosticMessages.js
|
||||
scripts/*.js.map
|
||||
scripts/typings/
|
||||
coverage/
|
||||
internal/
|
||||
**/.DS_Store
|
||||
.settings
|
||||
**/.vs
|
||||
**/.vscode
|
||||
!**/.vscode/tasks.json
|
||||
!tests/cases/projects/projectOption/**/node_modules
|
||||
!tests/cases/projects/NodeModulesSearch/**/*
|
||||
!tests/baselines/reference/project/nodeModules*/**/*
|
||||
.idea
|
||||
yarn.lock
|
||||
yarn-error.log
|
||||
.parallelperf.*
|
||||
tests/cases/user/*/package-lock.json
|
||||
tests/cases/user/*/node_modules/
|
||||
tests/cases/user/*/**/*.js
|
||||
tests/cases/user/*/**/*.js.map
|
||||
tests/cases/user/*/**/*.d.ts
|
||||
!tests/cases/user/zone.js/
|
||||
!tests/cases/user/bignumber.js/
|
||||
!tests/cases/user/discord.js/
|
||||
tests/baselines/reference/dt
|
||||
.failed-tests
|
||||
TEST-results.xml
|
||||
package-lock.json
|
||||
|
||||
unsignedTx.json
|
||||
# Ignore testing directory
|
||||
test_data
|
||||
|
|
|
@ -0,0 +1,42 @@
|
|||
BINARY = feegiver
|
||||
GITHUB_USERNAME = terra-project
|
||||
VERSION = v0.1.0
|
||||
GOARCH = amd64
|
||||
ARTIFACT_DIR = build
|
||||
|
||||
COMMIT=$(shell git rev-parse HEAD)
|
||||
BRANCH=$(shell git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
# Symlink into GOPATH
|
||||
FLAG_PATH=github.com/${GITHUB_USERNAME}/${BINARY}/cmd
|
||||
|
||||
# Setup the -ldflags option for go build here, interpolate the variable values
|
||||
LDFLAGS = -ldflags "-X ${FLAG_PATH}.Version=${VERSION} -X ${FLAG_PATH}.Commit=${COMMIT} -X ${FLAG_PATH}.Branch=${BRANCH}"
|
||||
|
||||
# Build the project
|
||||
all: clean linux darwin windows
|
||||
|
||||
# Build and Install project into GOPATH using current OS setup
|
||||
install:
|
||||
go install ${LDFLAGS} ./...
|
||||
|
||||
test:
|
||||
go test -v ./utils/...
|
||||
|
||||
# Build binary for Linux
|
||||
linux: clean
|
||||
GOOS=linux GOARCH=${GOARCH} go build ${LDFLAGS} -o ${ARTIFACT_DIR}/${BINARY}-linux-${GOARCH} . ;
|
||||
|
||||
# Build binary for MacOS
|
||||
darwin:
|
||||
GOOS=darwin GOARCH=${GOARCH} go build ${LDFLAGS} -o ${ARTIFACT_DIR}/${BINARY}-darwin-${GOARCH} . ;
|
||||
|
||||
# Build binary for Windows
|
||||
windows:
|
||||
GOOS=windows GOARCH=${GOARCH} go build ${LDFLAGS} -o ${ARTIFACT_DIR}/${BINARY}-windows-${GOARCH}.exe . ;
|
||||
|
||||
# Remove all the built binaries
|
||||
clean:
|
||||
rm -rf ${ARTIFACT_DIR}/*
|
||||
|
||||
.PHONY: all install test linux darwin windows clean
|
67
README.md
67
README.md
|
@ -1,35 +1,54 @@
|
|||
# Reward Distributor
|
||||
TERRA Foundation Reward Distributor
|
||||
|
||||
This repository is built to distribute all foundation rewards to validator and delegators on terra network.
|
||||
|
||||
## Usage
|
||||
# Build & Install
|
||||
```
|
||||
npm run build
|
||||
npm start
|
||||
```
|
||||
or
|
||||
```
|
||||
npm start -- lcd=https://lcd.terra.dev log=prod output=./unsigned.json
|
||||
$ git clone https://github.com/terra-project/feegiver.git
|
||||
$ git checkout master
|
||||
```
|
||||
|
||||
It requires active lcd url to get reward information.
|
||||
|
||||
It will make unsigned transaction output file (default `./unsignedTx.json`)
|
||||
|
||||
|
||||
## Instructions
|
||||
### For Both
|
||||
## Install
|
||||
```
|
||||
terracli tx distr set-withdraw-addr --withdraw-to terra1437zllxmq9gag8acyt56rk7dkyrd2zvk9ts02p --from {both} --chain-id columbus-2 --gas-prices 0.015uluna --gas 18000
|
||||
$ make install
|
||||
```
|
||||
## make config
|
||||
```
|
||||
$ feegiver config
|
||||
```
|
||||
## change config
|
||||
```
|
||||
$ vim ~/.feegiver/config.yaml
|
||||
```
|
||||
|
||||
### For Foundation Validator
|
||||
## Add Key
|
||||
```
|
||||
terracli tx distr withdraw-rewards --validator {validator} --from {validator} --commission
|
||||
$ feegiver keys add yun
|
||||
Enter a passphrase to encrypt your key to disk:
|
||||
Repeat the passphrase:
|
||||
{"name":"yun","type":"local","address":"terra1a26sc2vqs20hfx239kejhd88v6cl87yfswvk0t","pubkey":"terrapub1addwnpepqwspkmsl724h9azfvgqgs8jkyuyyr3d6eme432afvlvulk3al0mwwnxwlxv","mnemonic":"decade urge pond sustain unit film milk sunny wash accuse profit staff what black problem treat velvet metal leg review math history juice soccer"}
|
||||
```
|
||||
|
||||
### For Foundation Delegator
|
||||
## Recover Key
|
||||
```
|
||||
terracli tx distr terracli tx distr withdraw-all-rewards --from {validator}
|
||||
$ feegiver keys add yun --recover
|
||||
Enter a passphrase to encrypt your key to disk:
|
||||
Repeat the passphrase:
|
||||
> Enter your bip39 mnemonic
|
||||
theory fat merge under hungry utility toss much trend turkey degree glare bread connect trend grain silk toe pupil crouch innocent pause zero shove
|
||||
|
||||
{"name":"yun","type":"local","address":"terra1gn37dh0jl4zu4fp48d8y4c0hqs9cel83x7st7v","pubkey":"terrapub1addwnpepqfukqlgu8chxwwqns6adgjxvfny6y6tcvqmqkkn2xk6e6kefdaggvh4j7f0","mnemonic":"spatial fantasy weekend romance entire million celery final moon solid route theory way hockey north trigger advice balcony melody fabric alter bullet twice push"}
|
||||
```
|
||||
|
||||
## Add Key with Old HD Path
|
||||
```
|
||||
$ feegiver keys add yun --recover --old-hd-path
|
||||
Enter a passphrase to encrypt your key to disk:
|
||||
Repeat the passphrase:
|
||||
> Enter your bip39 mnemonic
|
||||
flash until glimpse chase cradle adjust brick view uncover analyst test pact sponsor example item victory memory attract visual hover pink meadow mosquito torch
|
||||
|
||||
{"name":"yun","type":"local","address":"terra1gn37dh0jl4zu4fp48d8y4c0hqs9cel83x7st7v","pubkey":"terrapub1addwnpepqfukqlgu8chxwwqns6adgjxvfny6y6tcvqmqkkn2xk6e6kefdaggvh4j7f0","mnemonic":"spatial fantasy weekend romance entire million celery final moon solid route theory way hockey north trigger advice balcony melody fabric alter bullet twice push"}
|
||||
```
|
||||
|
||||
## Start Server
|
||||
```
|
||||
$ feegiver start yun
|
||||
Enter the passphrase:
|
||||
```
|
||||
|
|
|
@ -0,0 +1,62 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/terra-project/feegiver/utils"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command
|
||||
var configCmd = &cobra.Command{
|
||||
Use: "config",
|
||||
Short: "Sets a default config file",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
fmt.Println("Error finding homedir:", err)
|
||||
return
|
||||
}
|
||||
|
||||
g := utils.Generator{
|
||||
KeyDir: fmt.Sprintf("%s/.feegiver", home),
|
||||
Node: "http://localhost:26657",
|
||||
|
||||
TriggerInterval: "5",
|
||||
FeeAmount: "1000000uluna",
|
||||
}
|
||||
|
||||
if _, err := os.Stat(g.KeyDir); os.IsNotExist(err) {
|
||||
err := os.MkdirAll(g.KeyDir, 0777)
|
||||
if err != nil {
|
||||
fmt.Println("Error creating directory:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
conf := fmt.Sprintf("%s/config.yaml", g.KeyDir)
|
||||
if _, err := os.Stat(conf); os.IsNotExist(err) {
|
||||
out, err := yaml.Marshal(g)
|
||||
if err != nil {
|
||||
fmt.Println("Error marshaling config:", err)
|
||||
return
|
||||
}
|
||||
file, err := os.Create(conf)
|
||||
if err != nil {
|
||||
fmt.Println("Error creating config file:", err)
|
||||
return
|
||||
}
|
||||
defer file.Close()
|
||||
fmt.Fprintf(file, string(out))
|
||||
} else {
|
||||
fmt.Println("Config file already exists, skipping...")
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(configCmd)
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
bip39 "github.com/bartekn/go-bip39"
|
||||
input "github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
const (
|
||||
flagRecover = "recover"
|
||||
flagOldHdPath = "old-hd-path"
|
||||
flagBech = "bech"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command
|
||||
var keysCmd = &cobra.Command{
|
||||
Use: "keys",
|
||||
Short: "Runs keys calls",
|
||||
}
|
||||
|
||||
// get keys list
|
||||
var keysList = &cobra.Command{
|
||||
Use: "list",
|
||||
Short: "Fetch all keys managed by the server",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
out, err := generator.GetKeys()
|
||||
if err != nil {
|
||||
log.Fatalf("Failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
},
|
||||
}
|
||||
|
||||
// keys add
|
||||
var keysAdd = &cobra.Command{
|
||||
Use: "add [name]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Add a new key to the keyserver, optionally pass a mnemonic to restore the key",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
|
||||
password, err := input.GetCheckPassword(
|
||||
"Enter a passphrase to encrypt your key to disk:",
|
||||
"Repeat the passphrase:", reader)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("failed reading password: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
var mnemonic string
|
||||
oldHdPath := false
|
||||
if viper.GetBool(flagRecover) {
|
||||
bip39Message := "Enter your bip39 mnemonic"
|
||||
mnemonic, err = input.GetString(bip39Message, reader)
|
||||
if err != nil {
|
||||
log.Fatalf("failed reading mnemonic: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
if !bip39.IsMnemonicValid(mnemonic) {
|
||||
log.Fatal("invalid mnemonic")
|
||||
return
|
||||
}
|
||||
|
||||
oldHdPath = viper.GetBool(flagOldHdPath)
|
||||
} else if viper.GetBool(flagOldHdPath) {
|
||||
log.Fatal("--old-hd-path can not be used without --recover flag")
|
||||
return
|
||||
}
|
||||
|
||||
out, err := generator.AddNewKey(args[0], password, mnemonic, oldHdPath)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
},
|
||||
}
|
||||
|
||||
// key show
|
||||
var keyShow = &cobra.Command{
|
||||
Use: "show [name]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Fetch details for one key",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
out, err := generator.GetKey(args[0], viper.GetString(flagBech))
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("Failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println(string(out))
|
||||
},
|
||||
}
|
||||
|
||||
// /keys/{name} PUT
|
||||
var keyPut = &cobra.Command{
|
||||
Use: "put [name]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Update the password on a key",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
password, err := input.GetPassword("Enter the current passphrase:", reader)
|
||||
if err != nil {
|
||||
log.Fatalf("failed reading password: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
newPassword, err := input.GetCheckPassword(
|
||||
"Enter the new passphrase:",
|
||||
"Repeat the new passphrase:", reader)
|
||||
|
||||
if err != nil {
|
||||
log.Fatalf("failed reading new password: %s", err.Error())
|
||||
return
|
||||
}
|
||||
err = generator.UpdateKey(args[0], password, newPassword)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println("ok")
|
||||
},
|
||||
}
|
||||
|
||||
// /keys/{name} DELETE
|
||||
var keyDelete = &cobra.Command{
|
||||
Use: "delete [name]",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Short: "Delete a key",
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
password, err := input.GetPassword("Enter the passphrase:", reader)
|
||||
if err != nil {
|
||||
log.Fatalf("failed reading password: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
err = generator.DeleteKey(args[0], password)
|
||||
if err != nil {
|
||||
log.Fatalf("Failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
fmt.Println("ok")
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
keysCmd.AddCommand(keysList)
|
||||
|
||||
keysAdd.Flags().Bool(flagRecover, false, "Recovering key option; mnemonic is required")
|
||||
keysAdd.Flags().Bool(flagOldHdPath, false, "Recover key with old hd path")
|
||||
viper.BindPFlag(flagRecover, keysAdd.Flags().Lookup(flagRecover))
|
||||
viper.BindPFlag(flagOldHdPath, keysAdd.Flags().Lookup(flagOldHdPath))
|
||||
keysCmd.AddCommand(keysAdd)
|
||||
|
||||
keyShow.Flags().String(flagBech, "", "bech32 prefix; acc or val or cons")
|
||||
viper.BindPFlag(flagBech, keyShow.Flags().Lookup(flagBech))
|
||||
keysCmd.AddCommand(keyShow)
|
||||
keysCmd.AddCommand(keyPut)
|
||||
keysCmd.AddCommand(keyDelete)
|
||||
rootCmd.AddCommand(keysCmd)
|
||||
|
||||
}
|
|
@ -0,0 +1,84 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/terra-project/feegiver/utils"
|
||||
yaml "gopkg.in/yaml.v2"
|
||||
)
|
||||
|
||||
var (
|
||||
// Path to config
|
||||
cfgFile string
|
||||
|
||||
// The actual app config
|
||||
generator utils.Generator
|
||||
|
||||
// Version for the application. Set via ldflags
|
||||
Version = "undefined"
|
||||
|
||||
// Commit (git) for the application. Set via ldflags
|
||||
Commit = "undefined"
|
||||
|
||||
// Branch (git) for the application. Set via ldflags
|
||||
Branch = "undefined"
|
||||
)
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "feegiver",
|
||||
Short: "An fee giver server for terra",
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.feegiver/config.yaml)")
|
||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||
}
|
||||
|
||||
func initConfig() {
|
||||
generator = utils.Generator{
|
||||
Version: Version,
|
||||
Commit: Commit,
|
||||
Branch: Branch,
|
||||
}
|
||||
|
||||
var bz []byte
|
||||
|
||||
if cfgFile != "" {
|
||||
var err error
|
||||
bz, err = ioutil.ReadFile(cfgFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
} else {
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
cfgFile = fmt.Sprintf("%s/.feegiver/config.yaml", home)
|
||||
bz, err = ioutil.ReadFile(cfgFile)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
yaml.Unmarshal(bz, &generator)
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package cmd
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
input "github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// versionCmd represents the version command
|
||||
var startCmd = &cobra.Command{
|
||||
Use: "start [name]",
|
||||
Short: "Runs auto withdraw program, with given key info",
|
||||
Args: cobra.ExactArgs(1),
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
password, err := input.GetPassword("Enter the passphrase:", reader)
|
||||
if err != nil {
|
||||
log.Fatalf("failed reading password: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
generator.KeyName = args[0]
|
||||
generator.KeyPassword = password
|
||||
|
||||
kb, err := keys.NewKeyBaseFromDir(generator.KeyDir)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to open keybase: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
_, err = kb.Get(generator.KeyName)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to get account: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
generator.ListenNewBLock()
|
||||
// err := generator.SendTx(10000, "vodka")
|
||||
// fmt.Println(err)
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(startCmd)
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
export {};
|
|
@ -1,213 +0,0 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const core = require("@terra-money/core");
|
||||
const rest_1 = require("./utils/rest");
|
||||
const big_js_1 = require("big.js");
|
||||
const fs = require("fs");
|
||||
process.argv = process.argv.slice(2);
|
||||
const argv = {};
|
||||
for (let i in process.argv) {
|
||||
const tmp = process.argv[i].split('=');
|
||||
argv[tmp[0]] = tmp[1];
|
||||
}
|
||||
const lcdURL = argv['lcd'] || "http://127.0.0.1:1317";
|
||||
const outputPath = argv['output'] || "./unsignedTx.json";
|
||||
const logLevel = argv['log'] || 'debug';
|
||||
console.log(`lcd path: ${lcdURL}`);
|
||||
console.log(`output file path: ${outputPath}`);
|
||||
console.log(`\n`);
|
||||
const rest = new rest_1.default(lcdURL);
|
||||
const foundationAddress = "terra1dp0taj85ruc299rkdvzp4z5pfg6z6swaed74e6";
|
||||
const goliathValAddress = "terravaloper163phlen6dn7sp9khhjar2gqqx6kga0ly8d7h9g";
|
||||
const marineValAddress = "terravaloper1d3hatwcsvkktgwp3elglw9glca0h42yg6xy4lp";
|
||||
const ghostValAddress = "terravaloper1rgu3qmm6rllfxlrfk94pgxa0jm37902dynqehm";
|
||||
const wraithValAddress = "terravaloper1eutun6vh83lmyq0wmyf9vgghvurze2xanl9sq6";
|
||||
const filterValAddresses = [
|
||||
goliathValAddress,
|
||||
marineValAddress,
|
||||
ghostValAddress,
|
||||
wraithValAddress,
|
||||
];
|
||||
const filterAddresses = [
|
||||
foundationAddress,
|
||||
core.convertValAddressToAccAddress(goliathValAddress),
|
||||
core.convertValAddressToAccAddress(marineValAddress),
|
||||
core.convertValAddressToAccAddress(ghostValAddress),
|
||||
core.convertValAddressToAccAddress(wraithValAddress),
|
||||
];
|
||||
async function loadFoundationRewards() {
|
||||
const promises = [];
|
||||
promises.push(rest.loadDelegatorRewards(foundationAddress));
|
||||
promises.push(rest.loadValidatorRewards(goliathValAddress));
|
||||
promises.push(rest.loadValidatorRewards(marineValAddress));
|
||||
promises.push(rest.loadValidatorRewards(ghostValAddress));
|
||||
promises.push(rest.loadValidatorRewards(wraithValAddress));
|
||||
const rewardMap = {};
|
||||
await Promise.all(promises)
|
||||
.then(res => {
|
||||
for (let i in res) {
|
||||
const rewards = res[i];
|
||||
if (rewards && rewards.length > 0) {
|
||||
for (let j in rewards) {
|
||||
const denom = rewards[j].denom;
|
||||
const amount = rewards[j].amount.split('.')[0];
|
||||
if (rewardMap[denom]) {
|
||||
rewardMap[denom] = big_js_1.default(rewardMap[denom]).plus(amount).toString();
|
||||
}
|
||||
else {
|
||||
rewardMap[denom] = amount;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
const totalRewards = [];
|
||||
for (let denom in rewardMap) {
|
||||
totalRewards.push({
|
||||
denom: denom,
|
||||
amount: rewardMap[denom]
|
||||
});
|
||||
}
|
||||
return totalRewards;
|
||||
}
|
||||
const validatorBonusRate = 0.2;
|
||||
function computeValidatorsRewardRatio(rewardRatioMap, validators) {
|
||||
let totalBondedToken = big_js_1.default(0);
|
||||
for (let i in validators) {
|
||||
if (filterValAddresses.includes(validators[i].operator_address))
|
||||
continue;
|
||||
totalBondedToken = totalBondedToken.plus(validators[i].tokens);
|
||||
}
|
||||
for (let i in validators) {
|
||||
if (filterValAddresses.includes(validators[i].operator_address))
|
||||
continue;
|
||||
const validator = validators[i];
|
||||
const address = core.convertValAddressToAccAddress(validator.operator_address);
|
||||
rewardRatioMap[address] = big_js_1.default(validator.tokens).div(totalBondedToken).mul(validatorBonusRate).toPrecision(10);
|
||||
}
|
||||
return;
|
||||
}
|
||||
async function computeDelegatorRewardRatio(rewardRatioMap, validators) {
|
||||
const validatorDelegationMap = {};
|
||||
let totalBondedToken = big_js_1.default(0);
|
||||
for (let i in validators) {
|
||||
const validator = validators[i];
|
||||
const delegations = await rest.loadDelegations(validator.operator_address);
|
||||
if (!delegations)
|
||||
continue;
|
||||
validatorDelegationMap[validator.operator_address] = {
|
||||
tokens: validator.tokens,
|
||||
delegatorShares: validator.delegator_shares,
|
||||
delegations: delegations
|
||||
};
|
||||
for (let j in delegations) {
|
||||
const delegation = delegations[j];
|
||||
if (filterAddresses.includes(delegation.delegator_address))
|
||||
continue;
|
||||
const tokens = big_js_1.default(validator.tokens).mul(delegation.shares).div(validator.delegator_shares);
|
||||
totalBondedToken = totalBondedToken.plus(tokens);
|
||||
}
|
||||
}
|
||||
for (let v in validatorDelegationMap) {
|
||||
const info = validatorDelegationMap[v];
|
||||
for (let i in info.delegations) {
|
||||
const delegation = info.delegations[i];
|
||||
if (filterAddresses.includes(delegation.delegator_address))
|
||||
continue;
|
||||
const tokens = big_js_1.default(info.tokens).mul(delegation.shares).div(info.delegatorShares);
|
||||
const ratio = big_js_1.default(tokens).div(totalBondedToken).mul(1 - validatorBonusRate).toPrecision(10);
|
||||
if (rewardRatioMap[delegation.delegator_address]) {
|
||||
rewardRatioMap[delegation.delegator_address]
|
||||
= big_js_1.default(rewardRatioMap[delegation.delegator_address])
|
||||
.plus(ratio).toPrecision(10);
|
||||
}
|
||||
else {
|
||||
rewardRatioMap[delegation.delegator_address] = ratio;
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
async function main() {
|
||||
const foundationRewards = await loadFoundationRewards();
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Foundation Rewards:`, foundationRewards);
|
||||
console.debug(`\n`);
|
||||
}
|
||||
const validators = await rest.loadValidators();
|
||||
if (!validators) {
|
||||
console.error("no validator found");
|
||||
return process.exit(-1);
|
||||
}
|
||||
const rewardRatioMap = {};
|
||||
computeValidatorsRewardRatio(rewardRatioMap, validators);
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Validator Bonus Rewards Map:`, rewardRatioMap);
|
||||
console.debug(`\n`);
|
||||
}
|
||||
await computeDelegatorRewardRatio(rewardRatioMap, validators);
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Total Rewards Map:`, rewardRatioMap);
|
||||
console.debug(`\n`);
|
||||
}
|
||||
// Rotate reward ratio and build msg input
|
||||
let totalRatio = big_js_1.default(0);
|
||||
const outputs = [];
|
||||
for (let addr in rewardRatioMap) {
|
||||
const ratio = rewardRatioMap[addr];
|
||||
totalRatio = totalRatio.plus(ratio);
|
||||
const coins = [];
|
||||
for (let i in foundationRewards) {
|
||||
const amount = big_js_1.default(foundationRewards[i].amount).mul(ratio);
|
||||
if (amount.lt(1))
|
||||
continue; // smaller than 1 will be 0, so just skip it
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: amount.toFixed(1).split(".")[0] // truncate decimal
|
||||
});
|
||||
}
|
||||
if (coins.length == 0)
|
||||
continue;
|
||||
outputs.push({
|
||||
address: addr,
|
||||
coins: coins
|
||||
});
|
||||
}
|
||||
if (totalRatio.gt(1)) {
|
||||
console.error(`Total Reward Ratio(${totalRatio}) is bigger than 1`);
|
||||
return process.exit(-1);
|
||||
}
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Total Reward Ratio:${totalRatio}`);
|
||||
console.debug(`\n`);
|
||||
}
|
||||
const inputs = [];
|
||||
const coins = [];
|
||||
for (let i in foundationRewards) {
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: big_js_1.default(foundationRewards[i].amount).toFixed(1).split(".")[0] // truncate decimal
|
||||
});
|
||||
}
|
||||
inputs.push({
|
||||
address: foundationAddress,
|
||||
coins: coins
|
||||
});
|
||||
const multiSendMsg = core.buildMultiSend(inputs, outputs);
|
||||
const unSingedTx = core.buildStdTx([multiSendMsg], { gas: "1000000", amount: [{
|
||||
denom: "ukrw",
|
||||
amount: "1000000"
|
||||
}] }, "reward distribution");
|
||||
fs.writeFile(outputPath, JSON.stringify(unSingedTx, null, 4), function (err) {
|
||||
if (err) {
|
||||
console.error("Writing Failed", err);
|
||||
return process.exit(-1);
|
||||
}
|
||||
else {
|
||||
console.info("Writing Succeed", `Please check ${outputPath}`);
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
main();
|
||||
//# sourceMappingURL=index.js.map
|
File diff suppressed because one or more lines are too long
|
@ -1,36 +0,0 @@
|
|||
declare class RestInterface {
|
||||
lcdAddress: string;
|
||||
constructor(lcdAddress: string);
|
||||
loadValidators(): Promise<void | Array<Validator>>;
|
||||
loadValidatorRewards(valAddress: string): Promise<void | Array<Coin>>;
|
||||
loadDelegations(valAddress: string): Promise<void | Array<Delegation>>;
|
||||
loadDelegatorRewards(delAddress: string): Promise<void | Array<Coin>>;
|
||||
}
|
||||
export interface Validator {
|
||||
operator_address: string;
|
||||
consensus_pubkey: string;
|
||||
jailed: boolean;
|
||||
status: number;
|
||||
tokens: string;
|
||||
delegator_shares: string;
|
||||
description: [Object];
|
||||
unbonding_height: string;
|
||||
unbonding_time: string;
|
||||
commission: [Object];
|
||||
min_self_delegation: string;
|
||||
}
|
||||
export interface Delegation {
|
||||
delegator_address: string;
|
||||
validator_address: string;
|
||||
shares: string;
|
||||
}
|
||||
export interface Coin {
|
||||
denom: string;
|
||||
amount: string;
|
||||
}
|
||||
export interface ValidatorRewardsInfo {
|
||||
operator_address: string;
|
||||
self_bond_rewards: [Coin];
|
||||
val_commission: [Coin];
|
||||
}
|
||||
export default RestInterface;
|
|
@ -1,51 +0,0 @@
|
|||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const axios_1 = require("axios");
|
||||
class RestInterface {
|
||||
constructor(lcdAddress) {
|
||||
this.lcdAddress = lcdAddress;
|
||||
}
|
||||
async loadValidators() {
|
||||
const queryValidatorsURL = `${this.lcdAddress}/staking/validators`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryValidatorsURL);
|
||||
return res.data ? res.data : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadValidators]", error);
|
||||
}
|
||||
}
|
||||
async loadValidatorRewards(valAddress) {
|
||||
const queryValidatorRewardsInfoURL = `${this.lcdAddress}/distribution/validators/${valAddress}`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryValidatorRewardsInfoURL);
|
||||
// foundation validators have 100% commission, so ignore self_bond_rewards
|
||||
return res.data ? res.data.val_commission : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadValidatorRewardsInfoURL]", error);
|
||||
}
|
||||
}
|
||||
async loadDelegations(valAddress) {
|
||||
const queryDelegatorsURL = `${this.lcdAddress}/staking/validators/${valAddress}/delegations`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryDelegatorsURL);
|
||||
return res.data ? res.data : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadDelegations]", error);
|
||||
}
|
||||
}
|
||||
async loadDelegatorRewards(delAddress) {
|
||||
const queryDelegatorRewardsURL = `${this.lcdAddress}/distribution/delegators/${delAddress}/rewards`;
|
||||
try {
|
||||
const res = await axios_1.default.get(queryDelegatorRewardsURL);
|
||||
return res.data ? res.data : [];
|
||||
}
|
||||
catch (error) {
|
||||
console.error("[LoadDelegatorRewards]", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.default = RestInterface;
|
||||
//# sourceMappingURL=rest.js.map
|
|
@ -1 +0,0 @@
|
|||
{"version":3,"file":"rest.js","sourceRoot":"src/","sources":["utils/rest.ts"],"names":[],"mappings":";;AAAA,iCAA4C;AAE5C,MAAM,aAAa;IAGjB,YAAY,UAAkB;QAC5B,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,cAAc;QAClB,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,UAAU,qBAAqB,CAAA;QAClE,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;YAC/C,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;SAChC;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,kBAAkB,EAAE,KAAK,CAAC,CAAC;SAC1C;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,UAAkB;QAC3C,MAAM,4BAA4B,GAAG,GAAG,IAAI,CAAC,UAAU,4BAA4B,UAAU,EAAE,CAAA;QAC/F,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,4BAA4B,CAAC,CAAA;YACzD,0EAA0E;YAC1E,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,CAAA;SAC/C;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,+BAA+B,EAAE,KAAK,CAAC,CAAC;SACvD;IACH,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,UAAkB;QACtC,MAAM,kBAAkB,GAAG,GAAG,IAAI,CAAC,UAAU,uBAAuB,UAAU,cAAc,CAAA;QAC5F,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,kBAAkB,CAAC,CAAA;YAC/C,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;SAChC;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,mBAAmB,EAAE,KAAK,CAAC,CAAC;SAC3C;IACH,CAAC;IAED,KAAK,CAAC,oBAAoB,CAAC,UAAkB;QAC3C,MAAM,wBAAwB,GAAG,GAAG,IAAI,CAAC,UAAU,4BAA4B,UAAU,UAAU,CAAA;QACnG,IAAI;YACF,MAAM,GAAG,GAAG,MAAM,eAAK,CAAC,GAAG,CAAC,wBAAwB,CAAC,CAAA;YACrD,OAAO,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAA;SAChC;QAAC,OAAO,KAAK,EAAE;YACd,OAAO,CAAC,KAAK,CAAC,wBAAwB,EAAE,KAAK,CAAC,CAAC;SAChD;IACH,CAAC;CACF;AAiCD,kBAAe,aAAa,CAAA"}
|
|
@ -0,0 +1,25 @@
|
|||
module github.com/terra-project/feegiver
|
||||
|
||||
go 1.12
|
||||
|
||||
require (
|
||||
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d
|
||||
github.com/cosmos/cosmos-sdk v0.0.0-00010101000000-000000000000
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d
|
||||
github.com/gorilla/handlers v1.4.0
|
||||
github.com/gorilla/mux v1.7.0
|
||||
github.com/gorilla/websocket v1.4.0
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/spf13/cobra v0.0.3
|
||||
github.com/spf13/viper v1.3.2
|
||||
github.com/stretchr/testify v1.3.0
|
||||
github.com/tendermint/go-amino v0.14.1
|
||||
github.com/tendermint/tendermint v0.31.5
|
||||
github.com/terra-project/core v0.2.3
|
||||
github.com/terra-project/keyserver v0.1.1-0.20190807072644-de151113d1f6
|
||||
gopkg.in/yaml.v2 v2.2.2
|
||||
)
|
||||
|
||||
replace github.com/cosmos/cosmos-sdk => github.com/YunSuk-Yeo/cosmos-sdk v0.35.2-terra
|
||||
|
||||
replace golang.org/x/crypto => github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5
|
|
@ -0,0 +1,334 @@
|
|||
bou.ke/monkey v1.0.1/go.mod h1:FgHuK96Rv2Nlf+0u1OOVDpCMdsWyOFmeeketDHE7LIg=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
|
||||
github.com/OpenPeeDeeP/depguard v0.0.0-20180806142446-a69c782687b2/go.mod h1:7/4sitnI9YlQgTLLk734QlzXT8DuHVnAyztLplQjk+o=
|
||||
github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
|
||||
github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g=
|
||||
github.com/YunSuk-Yeo/cosmos-sdk v0.35.2-terra h1:8Vf1FfsRTn7mo6DryoE0ldhenhGzjXtjuf3aMpKwyA0=
|
||||
github.com/YunSuk-Yeo/cosmos-sdk v0.35.2-terra/go.mod h1:ruF+G4D7hRf34uzZQvf/SIja9fsIThU5D7GirwTMQ9I=
|
||||
github.com/aead/siphash v1.0.1/go.mod h1:Nywa3cDsYNNK3gaciGTWPwHt0wlpNV15vwmswBAUSII=
|
||||
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
|
||||
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
|
||||
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
|
||||
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d h1:1aAija9gr0Hyv4KfQcRcwlmFIrhkDmIj2dz5bkg/s/8=
|
||||
github.com/bartekn/go-bip39 v0.0.0-20171116152956-a05967ea095d/go.mod h1:icNx/6QdFblhsEjZehARqbNumymUT/ydwlLojFdv7Sk=
|
||||
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
|
||||
github.com/beorn7/perks v1.0.0 h1:HWo1m869IqiPhD389kmkxeTalrjNbbJTC8LXupb+sl0=
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/bgentry/speakeasy v0.1.0 h1:ByYyxL9InA1OWqxJqqp2A5pYHUrCiAL6K3J+LKSsQkY=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/btcsuite/btcd v0.0.0-20190115013929-ed77733ec07d/go.mod h1:d3C0AkH6BRcvO8T0UEPu53cnw4IbV63x1bEjildYhO0=
|
||||
github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c h1:5N/b57wo2KfeHCGGdcXtOPsHqkPD+veLZhK/bMg2anQ=
|
||||
github.com/btcsuite/btcd v0.0.0-20190315201642-aa6e0f35703c/go.mod h1:DrZx5ec/dmnfpw9KyYoQyYo7d0KEvTkk/5M/vbZjAr8=
|
||||
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
|
||||
github.com/btcsuite/btcutil v0.0.0-20180706230648-ab6388e0c60a/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190207003914-4c204d697803/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190316010144-3ac1210f4b38 h1:GbQHMJ2u/geMPV1tbN7i7zARSoPAPuXWa44V0KYvJXU=
|
||||
github.com/btcsuite/btcutil v0.0.0-20190316010144-3ac1210f4b38/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
|
||||
github.com/btcsuite/go-socks v0.0.0-20170105172521-4720035b7bfd/go.mod h1:HHNXQzUsZCxOoE+CPiyCTO6x34Zs86zZUiwtpXoGdtg=
|
||||
github.com/btcsuite/goleveldb v0.0.0-20160330041536-7834afc9e8cd/go.mod h1:F+uVaaLLH7j4eDXPRvw78tMflu7Ie2bzYOH4Y8rRKBY=
|
||||
github.com/btcsuite/snappy-go v0.0.0-20151229074030-0bdef8d06723/go.mod h1:8woku9dyThutzjeg+3xrA5iCpBRH8XEEg3lh6TiUghc=
|
||||
github.com/btcsuite/websocket v0.0.0-20150119174127-31079b680792/go.mod h1:ghJtEyQwv5/p4Mg4C0fgbePVuGr935/5ddU9Z3TmDRY=
|
||||
github.com/btcsuite/winsvc v1.0.0/go.mod h1:jsenWakMcC0zFBFurPLEAyrnc/teJEM1O46fmI40EZs=
|
||||
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
|
||||
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
|
||||
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180618194314-52158e4697b8/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d h1:49RLWk1j44Xu4fjHb6JFYmeUnDORVwHNkDxaQ0ctCVU=
|
||||
github.com/cosmos/go-bip39 v0.0.0-20180819234021-555e2067c45d/go.mod h1:tSxLoYXyBmiFeKpvmq4dzayMdCjCnu8uqmCysIGBT2Y=
|
||||
github.com/cosmos/ledger-cosmos-go v0.10.3/go.mod h1:J8//BsAGTo3OC/vDLjMRFLW6q0WAaXvHnVc7ZmE8iUY=
|
||||
github.com/cosmos/ledger-go v0.9.2/go.mod h1:oZJ2hHAZROdlHiwTg4t7kP+GKIIkBT+o6c9QWFanOyI=
|
||||
github.com/davecgh/go-spew v0.0.0-20171005155431-ecdeabc65495/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/dgryski/go-sip13 v0.0.0-20181026042036-e10d5fee7954/go.mod h1:vAd38F8PWV+bWy6jNmig1y/TA+kYO4g3RSRF0IAv0no=
|
||||
github.com/ethereum/go-ethereum v1.8.23/go.mod h1:PwpWDrCLZrV+tfrhqqF6kPknbISMHaJv9Ln3kPCZLwY=
|
||||
github.com/fatih/color v1.6.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
|
||||
github.com/fortytw2/leaktest v1.3.0/go.mod h1:jDsjWgpAGjm2CA7WthBh/CdZYEPF31XHquHwclZch5g=
|
||||
github.com/fsnotify/fsnotify v1.4.7 h1:IXs+QLmnXW2CcXuY+8Mzv/fWEsPGWxqefPtCP5CnV9I=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/go-critic/go-critic v0.0.0-20181204210945-1df300866540/go.mod h1:+sE8vrLDS2M0pZkBk0wy6+nLdKexVDrl/jBqQOTDThA=
|
||||
github.com/go-kit/kit v0.8.0 h1:Wz+5lgoB0kkuqLEc6NVmwRknTKP6dTGbSqvhZtBI/j0=
|
||||
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
|
||||
github.com/go-lintpack/lintpack v0.5.2/go.mod h1:NwZuYi2nUHho8XEIZ6SIxihrnPoqBTDqfpXvXAN0sXM=
|
||||
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
|
||||
github.com/go-logfmt/logfmt v0.4.0 h1:MP4Eh7ZCb31lleYCFuwm0oe4/YGak+5l1vA2NOE80nA=
|
||||
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
|
||||
github.com/go-ole/go-ole v1.2.1/go.mod h1:7FAglXiTm7HKlQRDeOQ6ZNUHidzCWXuZWq/1dTyBNF8=
|
||||
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
|
||||
github.com/go-toolsmith/astcast v1.0.0/go.mod h1:mt2OdQTeAQcY4DQgPSArJjHCcOwlX+Wl/kwN+LbLGQ4=
|
||||
github.com/go-toolsmith/astcopy v1.0.0/go.mod h1:vrgyG+5Bxrnz4MZWPF+pI4R8h3qKRjjyvV/DSez4WVQ=
|
||||
github.com/go-toolsmith/astequal v0.0.0-20180903214952-dcb477bfacd6/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
|
||||
github.com/go-toolsmith/astequal v1.0.0/go.mod h1:H+xSiq0+LtiDC11+h1G32h7Of5O3CYFJ99GVbS5lDKY=
|
||||
github.com/go-toolsmith/astfmt v0.0.0-20180903215011-8f8ee99c3086/go.mod h1:mP93XdblcopXwlyN4X4uodxXQhldPGZbcEJIimQHrkg=
|
||||
github.com/go-toolsmith/astfmt v1.0.0/go.mod h1:cnWmsOAuq4jJY6Ct5YWlVLmcmLMn1JUPuQIHCY7CJDw=
|
||||
github.com/go-toolsmith/astinfo v0.0.0-20180906194353-9809ff7efb21/go.mod h1:dDStQCHtmZpYOmjRP/8gHHnCCch3Zz3oEgCdZVdtweU=
|
||||
github.com/go-toolsmith/astp v0.0.0-20180903215135-0af7e3c24f30/go.mod h1:SV2ur98SGypH1UjcPpCatrV5hPazG6+IfNHbkDXBRrk=
|
||||
github.com/go-toolsmith/astp v1.0.0/go.mod h1:RSyrtpVlfTFGDYRbrjyWP1pYu//tSFcvdYrA8meBmLI=
|
||||
github.com/go-toolsmith/pkgload v0.0.0-20181119091011-e9e65178eee8/go.mod h1:WoMrjiy4zvdS+Bg6z9jZH82QXwkcgCBX6nOfnmdaHks=
|
||||
github.com/go-toolsmith/pkgload v1.0.0/go.mod h1:5eFArkbO80v7Z0kdngIxsRXRMTaX4Ilcwuh3clNrQJc=
|
||||
github.com/go-toolsmith/strparse v1.0.0/go.mod h1:YI2nUKP9YGZnL/L1/DLFBfixrcjslWct4wyljWhSRy8=
|
||||
github.com/go-toolsmith/typep v1.0.0/go.mod h1:JSQCQMUPdRlMZFswiq3TGpNp1GMktqkR2Ns5AIQkATU=
|
||||
github.com/gobwas/glob v0.2.3/go.mod h1:d3Ez4x06l9bZtSvzIay5+Yzi0fmZzPgnTbPcKjJAkT8=
|
||||
github.com/gogo/protobuf v1.1.1 h1:72R+M5VuhED/KujmZVcIquuo8mBgX4oVda//DQb3PXo=
|
||||
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.0.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.1 h1:YF8+flBXS5eO826T4nzqPrxfhQThhXl0YzfuUPu4SBg=
|
||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4=
|
||||
github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/golangci/check v0.0.0-20180506172741-cfe4005ccda2/go.mod h1:k9Qvh+8juN+UKMCS/3jFtGICgW8O96FVaZsaxdzDkR4=
|
||||
github.com/golangci/dupl v0.0.0-20180902072040-3e9179ac440a/go.mod h1:ryS0uhF+x9jgbj/N71xsEqODy9BN81/GonCZiOzirOk=
|
||||
github.com/golangci/errcheck v0.0.0-20181003203344-ef45e06d44b6/go.mod h1:DbHgvLiFKX1Sh2T1w8Q/h4NAI8MHIpzCdnBUDTXU3I0=
|
||||
github.com/golangci/go-misc v0.0.0-20180628070357-927a3d87b613/go.mod h1:SyvUF2NxV+sN8upjjeVYr5W7tyxaT1JVtvhKhOn2ii8=
|
||||
github.com/golangci/go-tools v0.0.0-20180109140146-af6baa5dc196/go.mod h1:unzUULGw35sjyOYjUt0jMTXqHlZPpPc6e+xfO4cd6mM=
|
||||
github.com/golangci/goconst v0.0.0-20180610141641-041c5f2b40f3/go.mod h1:JXrF4TWy4tXYn62/9x8Wm/K/dm06p8tCKwFRDPZG/1o=
|
||||
github.com/golangci/gocyclo v0.0.0-20180528134321-2becd97e67ee/go.mod h1:ozx7R9SIwqmqf5pRP90DhR2Oay2UIjGuKheCBCNwAYU=
|
||||
github.com/golangci/gofmt v0.0.0-20181105071733-0b8337e80d98/go.mod h1:9qCChq59u/eW8im404Q2WWTrnBUQKjpNYKMbU4M7EFU=
|
||||
github.com/golangci/golangci-lint v1.17.1/go.mod h1:+5sJSl2h3aly+fpmL2meSP8CaSKua2E4Twi9LPy7b1g=
|
||||
github.com/golangci/gosec v0.0.0-20180901114220-66fb7fc33547/go.mod h1:0qUabqiIQgfmlAmulqxyiGkkyF6/tOGSnY2cnPVwrzU=
|
||||
github.com/golangci/ineffassign v0.0.0-20180808204949-42439a7714cc/go.mod h1:e5tpTHCfVze+7EpLEozzMB3eafxo2KT5veNg1k6byQU=
|
||||
github.com/golangci/lint-1 v0.0.0-20180610141402-ee948d087217/go.mod h1:66R6K6P6VWk9I95jvqGxkqJxVWGFy9XlDwLwVz1RCFg=
|
||||
github.com/golangci/maligned v0.0.0-20180506175553-b1d89398deca/go.mod h1:tvlJhZqDe4LMs4ZHD0oMUlt9G2LWuDGoisJTBzLMV9o=
|
||||
github.com/golangci/misspell v0.0.0-20180809174111-950f5d19e770/go.mod h1:dEbvlSfYbMQDtrpRMQU675gSDLDNa8sCPPChZ7PhiVA=
|
||||
github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bzsHdTM0bsB7+8mt0GUMvjCgwLpTapNZHU8AajI=
|
||||
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
|
||||
github.com/golangci/unconvert v0.0.0-20180507085042-28b1c447d1f4/go.mod h1:Izgrg8RkN3rCIMLGE9CyYmU9pY2Jer6DgANEnZ/L/cQ=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
||||
github.com/gorilla/handlers v1.4.0/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
|
||||
github.com/gorilla/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
|
||||
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
|
||||
github.com/gostaticanalysis/analysisutil v0.0.0-20190318220348-4088753ea4d3/go.mod h1:eEOZF4jCKGi+aprrirO9e7WKB3beBRtWgqGunKl6pKE=
|
||||
github.com/hashicorp/hcl v0.0.0-20180404174102-ef8a98b0bbce/go.mod h1:oZtUIOe8dh44I2q6ScRibXws4Ajl+d+nod3AaR9vL5w=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jessevdk/go-flags v0.0.0-20141203071132-1679536dcc89/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
github.com/jmhodges/levigo v1.0.0/go.mod h1:Q6Qx+uH3RAqyK4rFQroq9RL7mdkABMcfhEI+nNuzMJQ=
|
||||
github.com/jrick/logrotate v1.0.0/go.mod h1:LNinyqDIJnpAur+b8yyulnQw/wDuN1+BYKlTRt3OuAQ=
|
||||
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
|
||||
github.com/kisielk/gotool v0.0.0-20161130080628-0de1eaf82fa3/go.mod h1:jxZFDH7ILpTPQTk+E2s+z4CUas9lVNjIuKR4c5/zKgM=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
|
||||
github.com/klauspost/compress v1.4.0/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||
github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/logrusorgru/aurora v0.0.0-20181002194514-a7b3b318ed4e/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||
github.com/magiconair/properties v1.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/magiconair/properties v1.8.0 h1:LLgXmsheXeRoUOBOjtwPQCWIYqM/LU1ayDtDePerRcY=
|
||||
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/mattn/go-isatty v0.0.6/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/go-isatty v0.0.7 h1:UvyT9uN+3r7yLEYSlJsbQGdsaB/a0DlgWP3pql6iwOc=
|
||||
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
|
||||
github.com/mattn/goveralls v0.0.2/go.mod h1:8d1ZMHsd7fW6IRPKQh46F2WRpyib5/X4FOpevwGNQEw=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU=
|
||||
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
|
||||
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y=
|
||||
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
|
||||
github.com/mitchellh/go-ps v0.0.0-20170309133038-4fdf99ab2936/go.mod h1:r1VsdOzOPt1ZSrGZWFoNhsAedKnEd6r9Np1+5blZCWk=
|
||||
github.com/mitchellh/mapstructure v0.0.0-20180220230111-00c29f56e238/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
|
||||
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
|
||||
github.com/mozilla/tls-observatory v0.0.0-20180409132520-8791a200eb40/go.mod h1:SrKMQvPiws7F7iqYp8/TX+IhxCYhzr6N/1yb8cwHsGk=
|
||||
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20160627004424-a22cb81b2ecd/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/nbutton23/zxcvbn-go v0.0.0-20171102151520-eafdab6b0663/go.mod h1:o96djdrsSGy3AWPyBgZMAGfxZNfgntdJG+11KU4QvbU=
|
||||
github.com/oklog/ulid v1.3.1/go.mod h1:CirwcVhetQ6Lv90oh/F+FBtV6XMibvdAFo93nm5qn4U=
|
||||
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/gomega v0.0.0-20170829124025-dcabb60a477c/go.mod h1:C1qb7wdrVGGVU+Z6iS04AVkA3Q65CEZX59MT0QO5uiA=
|
||||
github.com/onsi/gomega v1.4.2/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY=
|
||||
github.com/otiai10/copy v0.0.0-20180813032824-7e9a647135a1/go.mod h1:pXzZSDlN+HPzSdyIBnKNN9ptD9Hx7iZMWIJPTwo4FPE=
|
||||
github.com/otiai10/curr v0.0.0-20150429015615-9b4961190c95/go.mod h1:9qAhocn7zKJG+0mI8eUu6xqkFDYS2kb2saOteoSB3cE=
|
||||
github.com/otiai10/mint v1.2.3/go.mod h1:YnfyPNhBvnY8bW4SGQHCs/aAFhkgySlMZbrF5U0bOVw=
|
||||
github.com/pelletier/go-toml v1.1.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pelletier/go-toml v1.2.0 h1:T5zMGML61Wp+FlcbWjRDT7yAxhJNAiPPLOFECq181zc=
|
||||
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
|
||||
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
|
||||
github.com/prometheus/client_golang v0.9.2/go.mod h1:OsXs2jCmiKlQ1lTBmv21f2mNfw4xf/QclQDMrYNZzcM=
|
||||
github.com/prometheus/client_golang v0.9.3 h1:9iH4JKXLzFbOAdtqv/a+j8aewx2Y8lAjAydhbaScPF8=
|
||||
github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso=
|
||||
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90 h1:S/YWwWx/RA8rT8tKFRuGUZhuA90OyIBpPCXkcbwU8DE=
|
||||
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/common v0.0.0-20181113130724-41aa239b4cce/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.0.0-20181126121408-4724e9255275/go.mod h1:daVV7qP5qjZbuso7PdcryaAu0sAZbrN9i7WWcTMWvro=
|
||||
github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/common v0.4.0 h1:7etb9YClo3a6HjLzfl6rIQaU+FDfi0VSX39io3aQ+DM=
|
||||
github.com/prometheus/common v0.4.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
|
||||
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20181204211112-1dc9a6cbc91a/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
|
||||
github.com/prometheus/procfs v0.0.0-20190227231451-bbced9601137/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084 h1:sofwID9zm4tzrgykg80hfFph1mryUeLRsUfoocVVmRY=
|
||||
github.com/prometheus/procfs v0.0.0-20190507164030-5867b95ac084/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
||||
github.com/rakyll/statik v0.1.4/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
|
||||
github.com/rakyll/statik v0.1.6/go.mod h1:OEi9wJV/fMUAGx1eNjq75DKDsJVuEv1U0oYdX6GX8Zs=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20180503174638-e2704e165165/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a h1:9ZKAASQSHhDYGoxY8uLVpewe1GDZ2vu2Tr/vTdVAkFQ=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/rogpeppe/go-internal v1.1.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
|
||||
github.com/rs/cors v1.6.0 h1:G9tHG9lebljV9mfp9SNPDL36nCDxmo3zTlAf1YgvzmI=
|
||||
github.com/rs/cors v1.6.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU=
|
||||
github.com/ryanuber/go-glob v0.0.0-20170128012129-256dc444b735/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc=
|
||||
github.com/shirou/gopsutil v0.0.0-20180427012116-c95755e4bcd7/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA=
|
||||
github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q1u/4XEfrquwF8Lw7D7y5cD8CuHnfIc=
|
||||
github.com/shurcooL/go v0.0.0-20180423040247-9e1955d9fb6e/go.mod h1:TDJrrUr11Vxrven61rcy3hJMUqaf/CLWYhHNPmT14Lk=
|
||||
github.com/shurcooL/go-goon v0.0.0-20170922171312-37c2f522c041/go.mod h1:N5mDOmsrJOB+vfqUK+7DmDyjhSLIIBnXo9lvZJj3MWQ=
|
||||
github.com/sirupsen/logrus v1.0.5/go.mod h1:pMByvHTf9Beacp5x1UXfOR9xyW/9antXMhjMPG0dEzc=
|
||||
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
|
||||
github.com/sourcegraph/go-diff v0.5.1/go.mod h1:j2dHj3m8aZgQO8lMTcTnBcXkRRRqi34cd2MNlA9u1mE=
|
||||
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
|
||||
github.com/spf13/afero v1.1.0/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
|
||||
github.com/spf13/afero v1.2.1/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
|
||||
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
|
||||
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
|
||||
github.com/spf13/cast v1.3.0 h1:oget//CVOEoFewqQxwr0Ej5yjygnqGkvggSE/gB35Q8=
|
||||
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
|
||||
github.com/spf13/cobra v0.0.2/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/cobra v0.0.3 h1:ZlrZ4XsMRm04Fr5pSFxBgfND2EBVa1nLpiy1stUsX/8=
|
||||
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/jwalterweatherman v0.0.0-20180109140146-7c0cea34c8ec/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.0.0/go.mod h1:cQK4TGJAtQXfYWX+Ddv3mKDzgVb68N+wFjFa4jdeBTo=
|
||||
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
|
||||
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
|
||||
github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/pflag v1.0.3 h1:zPAT6CGy6wXeQ7NtTnaTerfKOsV6V6F8agHXFiazDkg=
|
||||
github.com/spf13/pflag v1.0.3/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/spf13/viper v1.0.2/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/spf13/viper v1.0.3/go.mod h1:A8kyI5cUJhb8N+3pkfONlcEcZbueH6nhAm0Fq7SrnBM=
|
||||
github.com/spf13/viper v1.3.2 h1:VUFqw5KcqRf7i70GOzW7N+Q7+gxVBkSSqiXB12+JQ4M=
|
||||
github.com/spf13/viper v1.3.2/go.mod h1:ZiWeW+zYFKm7srdB9IoDzzZXaJaI5eL9QjNiN/DMA2s=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.3.0 h1:TivCn/peBQ7UY8ooIcPgZFpTNSz0Q2U6UrFlUfqbe0Q=
|
||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
|
||||
github.com/syndtr/goleveldb v0.0.0-20180708030551-c4c61651e9e3/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0=
|
||||
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
|
||||
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
|
||||
github.com/tendermint/btcd v0.1.1 h1:0VcxPfflS2zZ3RiOAHkBiFUcPvbtRj5O7zHmcJWHV7s=
|
||||
github.com/tendermint/btcd v0.1.1/go.mod h1:DC6/m53jtQzr/NFmMNEu0rxf18/ktVoVtMrnDD5pN+U=
|
||||
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5 h1:u8i49c+BxloX3XQ55cvzFNXplizZP/q00i+IlttUjAU=
|
||||
github.com/tendermint/crypto v0.0.0-20180820045704-3764759f34a5/go.mod h1:z4YtwM70uOnk8h0pjJYlj3zdYwi9l03By6iAIF5j/Pk=
|
||||
github.com/tendermint/go-amino v0.14.1 h1:o2WudxNfdLNBwMyl2dqOJxiro5rfrEaU0Ugs6offJMk=
|
||||
github.com/tendermint/go-amino v0.14.1/go.mod h1:i/UKE5Uocn+argJJBb12qTZsCDBcAYMbR92AaJVmKso=
|
||||
github.com/tendermint/iavl v0.12.1 h1:JDfyhM/Hhrumu1CL1Nxrypm8sNTPYqmeHo1IZLiJoXM=
|
||||
github.com/tendermint/iavl v0.12.1/go.mod h1:EoKMMv++tDOL5qKKVnoIqtVPshRrEPeJ0WsgDOLAauM=
|
||||
github.com/tendermint/tendermint v0.31.5 h1:vTet8tCq3B9/J9Yo11dNZ8pOB7NtSy++bVSfkP4KzR4=
|
||||
github.com/tendermint/tendermint v0.31.5/go.mod h1:ymcPyWblXCplCPQjbOYbrF1fWnpslATMVqiGgWbZrlc=
|
||||
github.com/terra-project/core v0.2.3 h1:XGxiZuirvQaItee/2qNoaJZ6g+fRpOjjDMNFEdNdQks=
|
||||
github.com/terra-project/core v0.2.3/go.mod h1:hIVtajuqzNGtNs8eTuPDN6hpmoUARrkS6l974QNGUJo=
|
||||
github.com/terra-project/keyserver v0.1.1-0.20190807072644-de151113d1f6/go.mod h1:GgKiRG8K4zmIu4EfFuftjoWlmSHPPxZrdXrzrzoN9TY=
|
||||
github.com/timakin/bodyclose v0.0.0-20190407043127-4a873e97b2bb/go.mod h1:Qimiffbc6q9tBWlVV6x0P9sat/ao1xEkREYPPj9hphk=
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||
github.com/valyala/fasthttp v1.2.0/go.mod h1:4vX61m6KN+xDduDNwXrhIAVZaZaZiQ1luJk8LWSxF3s=
|
||||
github.com/valyala/quicktemplate v1.1.1/go.mod h1:EH+4AkTd43SvgIbQHYu59/cJyxDoOVRUAfrukLPuGJ4=
|
||||
github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/zondax/hid v0.9.0/go.mod h1:l5wttcP0jwtdLjqjMMWFVEE7d1zO0jvSPA9OPZxWpEM=
|
||||
github.com/zondax/ledger-go v0.8.0/go.mod h1:b2vIcu3u9gJoIx4kTWuXOgzGV7FPWeUktqRqVf6feG0=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20170915142106-8351a756f30f/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180911220305-26e67e76b6c3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977 h1:actzWV6iWn3GLqN8dZjzsB+CLt+gaV2+wsxroxiQI8I=
|
||||
golang.org/x/net v0.0.0-20190313220215-9f648a60d977/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20171026204733-164713f0dfce/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
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-20181205085412-a5c9d58dba9a/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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190329044733-9eb1bfa1ce65 h1:hOY+O8MxdkPV10pNf7/XEHaySCiPKxixMKUshfHsGn0=
|
||||
golang.org/x/sys v0.0.0-20190329044733-9eb1bfa1ce65/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/text v0.0.0-20170915090833-1cbadb444a80/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.0 h1:g61tztE5qeGQ89tm6NTjjM9VPIm088od1l6aSorWRWg=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/tools v0.0.0-20170915040203-e531a2a1c15f/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20181117154741-2ddaf7f79a09/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190110163146-51295c7ec13a/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190121143147-24cd39ecf745/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190311215038-5c2858a9cfe5/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190322203728-c1a832b0ad89/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190521203540-521d6ed310dd/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d h1:XB2jc5XQ9uhizGTS2vWcN01bc4dI6z3C4KY5MQm8SS8=
|
||||
google.golang.org/genproto v0.0.0-20190327125643-d831d65fe17d/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.21.0 h1:G+97AoqBnmZIT91cLG/EkCoK9NSelj64P8bOHHNmGn0=
|
||||
google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
|
||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
||||
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
mvdan.cc/interfacer v0.0.0-20180901003855-c20040233aed/go.mod h1:Xkxe497xwlCKkIaQYRfC7CSLworTXY9RMqwhhCm+8Nc=
|
||||
mvdan.cc/lint v0.0.0-20170908181259-adc824a0674b/go.mod h1:2odslEg/xrtNQqCYg2/jCoyKnw3vv5biOc3JnIcYfL4=
|
||||
mvdan.cc/unparam v0.0.0-20190124213536-fbb59629db34/go.mod h1:H6SUd1XjIs+qQCyskXg5OFSrilMRUkD8ePJpHKDPaeY=
|
||||
sourcegraph.com/sqs/pbtypes v0.0.0-20180604144634-d3ebe8f20ae4/go.mod h1:ketZ/q3QxT9HOBeFhu6RdvsftgpsbFHBF5Cas6cDKZ0=
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1 @@
|
|||
MANIFEST-000011
|
|
@ -0,0 +1 @@
|
|||
MANIFEST-000009
|
|
@ -0,0 +1,54 @@
|
|||
=============== Aug 7, 2019 (KST) ===============
|
||||
16:56:58.211679 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:56:58.225722 db@open opening
|
||||
16:56:58.226696 version@stat F·[] S·0B[] Sc·[]
|
||||
16:56:58.232353 db@janitor F·2 G·0
|
||||
16:56:58.233004 db@open done T·7.237371ms
|
||||
16:56:58.233111 db@close closing
|
||||
16:56:58.233208 db@close done T·94.717µs
|
||||
=============== Aug 7, 2019 (KST) ===============
|
||||
16:56:58.233404 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:56:58.233637 version@stat F·[] S·0B[] Sc·[]
|
||||
16:56:58.233664 db@open opening
|
||||
16:56:58.233756 journal@recovery F·1
|
||||
16:56:58.233897 journal@recovery recovering @1
|
||||
16:56:58.234452 version@stat F·[] S·0B[] Sc·[]
|
||||
16:56:58.252330 db@janitor F·2 G·0
|
||||
16:56:58.252363 db@open done T·18.674729ms
|
||||
16:56:58.498076 db@close closing
|
||||
16:56:58.498173 db@close done T·92.831µs
|
||||
=============== Aug 7, 2019 (KST) ===============
|
||||
16:57:24.410988 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:57:24.411185 version@stat F·[] S·0B[] Sc·[]
|
||||
16:57:24.411205 db@open opening
|
||||
16:57:24.411267 journal@recovery F·1
|
||||
16:57:24.411556 journal@recovery recovering @2
|
||||
16:57:24.420661 memdb@flush created L0@4 N·2 S·484B "ter..ess,v2":"yun.info,v1"
|
||||
16:57:24.421713 version@stat F·[1] S·484B[484B] Sc·[0.25]
|
||||
16:57:24.441941 db@janitor F·3 G·0
|
||||
16:57:24.447859 db@open done T·36.631766ms
|
||||
16:57:24.690607 db@close closing
|
||||
16:57:24.691097 db@close done T·486.088µs
|
||||
=============== Aug 7, 2019 (KST) ===============
|
||||
16:57:32.561788 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:57:32.562041 version@stat F·[1] S·484B[484B] Sc·[0.25]
|
||||
16:57:32.562066 db@open opening
|
||||
16:57:32.562137 journal@recovery F·1
|
||||
16:57:32.562405 journal@recovery recovering @5
|
||||
16:57:32.569663 memdb@flush created L0@7 N·2 S·184B "ter..ess,d4":"yun.info,d5"
|
||||
16:57:32.570358 version@stat F·[2] S·668B[668B] Sc·[0.50]
|
||||
16:57:32.595987 db@janitor F·4 G·0
|
||||
16:57:32.596026 db@open done T·33.942315ms
|
||||
16:57:32.596181 db@close closing
|
||||
16:57:32.596288 db@close done T·102.884µs
|
||||
=============== Aug 7, 2019 (KST) ===============
|
||||
16:57:32.596436 log@legend F·NumFile S·FileSize N·Entry C·BadEntry B·BadBlock Ke·KeyError D·DroppedEntry L·Level Q·SeqNum T·TimeElapsed
|
||||
16:57:32.596622 version@stat F·[2] S·668B[668B] Sc·[0.50]
|
||||
16:57:32.596642 db@open opening
|
||||
16:57:32.596721 journal@recovery F·1
|
||||
16:57:32.596980 journal@recovery recovering @8
|
||||
16:57:32.599133 version@stat F·[2] S·668B[668B] Sc·[0.50]
|
||||
16:57:32.617657 db@janitor F·4 G·0
|
||||
16:57:32.617706 db@open done T·21.049788ms
|
||||
16:57:32.863658 db@close closing
|
||||
16:57:32.864305 db@close done T·642.212µs
|
Binary file not shown.
|
@ -0,0 +1,21 @@
|
|||
// Copyright © 2018 NAME HERE <EMAIL ADDRESS>
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
package main
|
||||
|
||||
import "github.com/terra-project/feegiver/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
23
package.json
23
package.json
|
@ -1,23 +0,0 @@
|
|||
{
|
||||
"name": "reward-distributor",
|
||||
"version": "1.0.0",
|
||||
"description": "terra foundation reward distributor to validators & delegators",
|
||||
"main": "dist/index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1",
|
||||
"build": "tsc --declaration",
|
||||
"start": "node ./dist/index.js"
|
||||
},
|
||||
"author": "YunSuk Yeo <sw.yunsuk@gmail.com>",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"@terra-money/core": "^1.0.2",
|
||||
"@types/axios": "^0.14.0",
|
||||
"@types/big.js": "^4.0.5",
|
||||
"@types/loglevel": "^1.5.4",
|
||||
"@types/minimist": "^1.2.0",
|
||||
"axios": "^0.19.0",
|
||||
"big.js": "^5.2.2",
|
||||
"loglevel": "^1.6.3"
|
||||
}
|
||||
}
|
245
src/index.ts
245
src/index.ts
|
@ -1,245 +0,0 @@
|
|||
import * as core from "@terra-money/core"
|
||||
import {default as RestInterface, Coin, Validator, ValidatorRewardsInfo} from "./utils/rest"
|
||||
import bn from "big.js"
|
||||
import * as fs from "fs"
|
||||
|
||||
process.argv = process.argv.slice(2)
|
||||
|
||||
const argv = {}
|
||||
for (let i in process.argv) {
|
||||
const tmp = process.argv[i].split('=')
|
||||
argv[tmp[0]] = tmp[1]
|
||||
}
|
||||
|
||||
const lcdURL = argv['lcd'] || "http://127.0.0.1:1317"
|
||||
const outputPath = argv['output'] || "./unsignedTx.json"
|
||||
const logLevel = argv['log'] || 'debug'
|
||||
|
||||
console.log(`lcd path: ${lcdURL}`)
|
||||
console.log(`output file path: ${outputPath}`)
|
||||
console.log(`\n`)
|
||||
|
||||
const rest = new RestInterface(lcdURL)
|
||||
|
||||
const foundationAddress = "terra1dp0taj85ruc299rkdvzp4z5pfg6z6swaed74e6"
|
||||
const goliathValAddress = "terravaloper163phlen6dn7sp9khhjar2gqqx6kga0ly8d7h9g"
|
||||
const marineValAddress = "terravaloper1d3hatwcsvkktgwp3elglw9glca0h42yg6xy4lp"
|
||||
const ghostValAddress = "terravaloper1rgu3qmm6rllfxlrfk94pgxa0jm37902dynqehm"
|
||||
const wraithValAddress = "terravaloper1eutun6vh83lmyq0wmyf9vgghvurze2xanl9sq6"
|
||||
|
||||
const filterValAddresses = [
|
||||
goliathValAddress,
|
||||
marineValAddress,
|
||||
ghostValAddress,
|
||||
wraithValAddress,
|
||||
]
|
||||
|
||||
const filterAddresses = [
|
||||
foundationAddress,
|
||||
core.convertValAddressToAccAddress(goliathValAddress),
|
||||
core.convertValAddressToAccAddress(marineValAddress),
|
||||
core.convertValAddressToAccAddress(ghostValAddress),
|
||||
core.convertValAddressToAccAddress(wraithValAddress),
|
||||
]
|
||||
|
||||
async function loadFoundationRewards(): Promise<Array<Coin>> {
|
||||
const promises: Array<Promise<void | Array<Coin>>> = []
|
||||
promises.push(rest.loadDelegatorRewards(foundationAddress))
|
||||
promises.push(rest.loadValidatorRewards(goliathValAddress))
|
||||
promises.push(rest.loadValidatorRewards(marineValAddress))
|
||||
promises.push(rest.loadValidatorRewards(ghostValAddress))
|
||||
promises.push(rest.loadValidatorRewards(wraithValAddress))
|
||||
|
||||
const rewardMap = {}
|
||||
await Promise.all(promises)
|
||||
.then(res => {
|
||||
for (let i in res) {
|
||||
const rewards = res[i]
|
||||
|
||||
if (rewards && rewards.length > 0) {
|
||||
for (let j in rewards) {
|
||||
const denom = rewards[j].denom
|
||||
const amount = rewards[j].amount.split('.')[0]
|
||||
if (rewardMap[denom]) {
|
||||
rewardMap[denom] = bn(rewardMap[denom]).plus(amount).toString()
|
||||
} else {
|
||||
rewardMap[denom] = amount
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
const totalRewards: Array<Coin> = []
|
||||
for (let denom in rewardMap) {
|
||||
totalRewards.push({
|
||||
denom: denom,
|
||||
amount: rewardMap[denom]
|
||||
})
|
||||
}
|
||||
|
||||
return totalRewards
|
||||
}
|
||||
|
||||
const validatorBonusRate = 0.2
|
||||
function computeValidatorsRewardRatio(rewardRatioMap: object, validators: Array<Validator>) {
|
||||
let totalBondedToken = bn(0)
|
||||
for (let i in validators) {
|
||||
if (filterValAddresses.includes(validators[i].operator_address)) continue
|
||||
|
||||
totalBondedToken = totalBondedToken.plus(validators[i].tokens)
|
||||
}
|
||||
|
||||
for (let i in validators) {
|
||||
if (filterValAddresses.includes(validators[i].operator_address)) continue
|
||||
|
||||
const validator = validators[i]
|
||||
const address = core.convertValAddressToAccAddress(validator.operator_address)
|
||||
rewardRatioMap[address] = bn(validator.tokens).div(totalBondedToken).mul(validatorBonusRate).toPrecision(10)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
async function computeDelegatorRewardRatio(rewardRatioMap: object, validators: Array<Validator>): Promise<void> {
|
||||
const validatorDelegationMap = {}
|
||||
let totalBondedToken = bn(0)
|
||||
for (let i in validators) {
|
||||
const validator = validators[i]
|
||||
const delegations = await rest.loadDelegations(validator.operator_address)
|
||||
if (!delegations) continue
|
||||
|
||||
validatorDelegationMap[validator.operator_address] = {
|
||||
tokens: validator.tokens,
|
||||
delegatorShares: validator.delegator_shares,
|
||||
delegations: delegations
|
||||
}
|
||||
|
||||
for (let j in delegations) {
|
||||
const delegation = delegations[j]
|
||||
if (filterAddresses.includes(delegation.delegator_address))continue
|
||||
|
||||
const tokens = bn(validator.tokens).mul(delegation.shares).div(validator.delegator_shares)
|
||||
totalBondedToken = totalBondedToken.plus(tokens)
|
||||
}
|
||||
}
|
||||
|
||||
for (let v in validatorDelegationMap) {
|
||||
const info = validatorDelegationMap[v]
|
||||
|
||||
for (let i in info.delegations) {
|
||||
const delegation = info.delegations[i]
|
||||
if (filterAddresses.includes(delegation.delegator_address))continue
|
||||
|
||||
const tokens = bn(info.tokens).mul(delegation.shares).div(info.delegatorShares)
|
||||
const ratio = bn(tokens).div(totalBondedToken).mul(1 - validatorBonusRate).toPrecision(10)
|
||||
|
||||
if (rewardRatioMap[delegation.delegator_address]) {
|
||||
rewardRatioMap[delegation.delegator_address]
|
||||
= bn(rewardRatioMap[delegation.delegator_address])
|
||||
.plus(ratio).toPrecision(10)
|
||||
} else {
|
||||
rewardRatioMap[delegation.delegator_address] = ratio
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
async function main() {
|
||||
|
||||
const foundationRewards = await loadFoundationRewards()
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Foundation Rewards:`, foundationRewards)
|
||||
console.debug(`\n`)
|
||||
}
|
||||
|
||||
|
||||
const validators = await rest.loadValidators()
|
||||
if (!validators) {
|
||||
console.error("no validator found")
|
||||
return process.exit(-1)
|
||||
}
|
||||
|
||||
const rewardRatioMap = {}
|
||||
computeValidatorsRewardRatio(rewardRatioMap, validators)
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Validator Bonus Rewards Map:`, rewardRatioMap)
|
||||
console.debug(`\n`)
|
||||
}
|
||||
|
||||
await computeDelegatorRewardRatio(rewardRatioMap, validators)
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Total Rewards Map:`, rewardRatioMap)
|
||||
console.debug(`\n`)
|
||||
}
|
||||
|
||||
// Rotate reward ratio and build msg input
|
||||
let totalRatio = bn(0)
|
||||
const outputs: Array<core.InOut> = []
|
||||
for (let addr in rewardRatioMap) {
|
||||
const ratio = rewardRatioMap[addr]
|
||||
totalRatio = totalRatio.plus(ratio)
|
||||
|
||||
const coins: Array<core.Coin> = []
|
||||
for (let i in foundationRewards) {
|
||||
const amount = bn(foundationRewards[i].amount).mul(ratio)
|
||||
if (amount.lt(1)) continue // smaller than 1 will be 0, so just skip it
|
||||
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: amount.toFixed(1).split(".")[0] // truncate decimal
|
||||
})
|
||||
}
|
||||
|
||||
if (coins.length == 0) continue
|
||||
outputs.push({
|
||||
address: addr,
|
||||
coins: coins
|
||||
})
|
||||
}
|
||||
|
||||
if (totalRatio.gt(1)) {
|
||||
console.error(`Total Reward Ratio(${totalRatio}) is bigger than 1`)
|
||||
return process.exit(-1)
|
||||
}
|
||||
|
||||
if (logLevel == 'debug') {
|
||||
console.debug(`Total Reward Ratio:${totalRatio}`)
|
||||
console.debug(`\n`)
|
||||
}
|
||||
|
||||
const inputs: Array<core.InOut> = []
|
||||
const coins: Array<core.Coin> = []
|
||||
for (let i in foundationRewards) {
|
||||
coins.push({
|
||||
denom: foundationRewards[i].denom,
|
||||
amount: bn(foundationRewards[i].amount).toFixed(1).split(".")[0] // truncate decimal
|
||||
})
|
||||
}
|
||||
|
||||
inputs.push({
|
||||
address: foundationAddress,
|
||||
coins: coins
|
||||
})
|
||||
|
||||
const multiSendMsg = core.buildMultiSend(inputs, outputs)
|
||||
const unSingedTx = core.buildStdTx([multiSendMsg], {gas: "1000000", amount: [{
|
||||
denom: "ukrw",
|
||||
amount: "1000000"
|
||||
}]}, "reward distribution")
|
||||
|
||||
fs.writeFile(outputPath, JSON.stringify(unSingedTx, null, 4), function(err) {
|
||||
if (err) {
|
||||
console.error("Writing Failed", err);
|
||||
return process.exit(-1)
|
||||
} else {
|
||||
console.info("Writing Succeed", `Please check ${outputPath}`)
|
||||
}
|
||||
})
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
main()
|
|
@ -1,83 +0,0 @@
|
|||
import axios, { AxiosResponse } from "axios"
|
||||
|
||||
class RestInterface {
|
||||
lcdAddress: string
|
||||
|
||||
constructor(lcdAddress: string) {
|
||||
this.lcdAddress = lcdAddress
|
||||
}
|
||||
|
||||
async loadValidators(): Promise<void | Array<Validator>> {
|
||||
const queryValidatorsURL = `${this.lcdAddress}/staking/validators`
|
||||
try {
|
||||
const res = await axios.get(queryValidatorsURL)
|
||||
return res.data ? res.data : []
|
||||
} catch (error) {
|
||||
console.error("[LoadValidators]", error);
|
||||
}
|
||||
}
|
||||
|
||||
async loadValidatorRewards(valAddress: string): Promise<void | Array<Coin>> {
|
||||
const queryValidatorRewardsInfoURL = `${this.lcdAddress}/distribution/validators/${valAddress}`
|
||||
try {
|
||||
const res = await axios.get(queryValidatorRewardsInfoURL)
|
||||
// foundation validators have 100% commission, so ignore self_bond_rewards
|
||||
return res.data ? res.data.val_commission : []
|
||||
} catch (error) {
|
||||
console.error("[LoadValidatorRewardsInfoURL]", error);
|
||||
}
|
||||
}
|
||||
|
||||
async loadDelegations(valAddress: string): Promise<void | Array<Delegation>> {
|
||||
const queryDelegatorsURL = `${this.lcdAddress}/staking/validators/${valAddress}/delegations`
|
||||
try {
|
||||
const res = await axios.get(queryDelegatorsURL)
|
||||
return res.data ? res.data : []
|
||||
} catch (error) {
|
||||
console.error("[LoadDelegations]", error);
|
||||
}
|
||||
}
|
||||
|
||||
async loadDelegatorRewards(delAddress: string): Promise<void | Array<Coin>> {
|
||||
const queryDelegatorRewardsURL = `${this.lcdAddress}/distribution/delegators/${delAddress}/rewards`
|
||||
try {
|
||||
const res = await axios.get(queryDelegatorRewardsURL)
|
||||
return res.data ? res.data : []
|
||||
} catch (error) {
|
||||
console.error("[LoadDelegatorRewards]", error);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface Validator {
|
||||
operator_address: string
|
||||
consensus_pubkey: string
|
||||
jailed: boolean
|
||||
status: number
|
||||
tokens: string
|
||||
delegator_shares: string
|
||||
description: [Object]
|
||||
unbonding_height: string
|
||||
unbonding_time: string
|
||||
commission: [Object]
|
||||
min_self_delegation: string
|
||||
}
|
||||
|
||||
export interface Delegation {
|
||||
delegator_address: string
|
||||
validator_address: string
|
||||
shares: string
|
||||
}
|
||||
|
||||
export interface Coin {
|
||||
denom: string
|
||||
amount: string
|
||||
}
|
||||
|
||||
export interface ValidatorRewardsInfo {
|
||||
operator_address:string
|
||||
self_bond_rewards:[Coin]
|
||||
val_commission:[Coin]
|
||||
}
|
||||
|
||||
export default RestInterface
|
|
@ -1,29 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "es2018",
|
||||
"module": "commonjs",
|
||||
"strict": false,
|
||||
"allowJs": false,
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"strictNullChecks": true,
|
||||
"sourceMap": true,
|
||||
"baseUrl": "src",
|
||||
"sourceRoot": "src",
|
||||
"outDir": "dist",
|
||||
"typeRoots": [
|
||||
"./src/typings",
|
||||
"./node_modules/@types"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"src/**/*.ts"
|
||||
],
|
||||
"exclude": [
|
||||
"node_modules",
|
||||
"dist"
|
||||
]
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package utils
|
||||
|
||||
const (
|
||||
maxValidAccountValue = int(0x80000000 - 1)
|
||||
maxValidIndexalue = int(0x80000000 - 1)
|
||||
)
|
||||
|
||||
const (
|
||||
// Bech32PrefixAccAddr defines the Bech32 prefix of an account's address
|
||||
Bech32PrefixAccAddr = "terra"
|
||||
// Bech32PrefixAccPub defines the Bech32 prefix of an account's public key
|
||||
Bech32PrefixAccPub = "terrapub"
|
||||
// Bech32PrefixValAddr defines the Bech32 prefix of a validator's operator address
|
||||
Bech32PrefixValAddr = "terravaloper"
|
||||
// Bech32PrefixValPub defines the Bech32 prefix of a validator's operator public key
|
||||
Bech32PrefixValPub = "terravaloperpub"
|
||||
// Bech32PrefixConsAddr defines the Bech32 prefix of a consensus node address
|
||||
Bech32PrefixConsAddr = "terravalcons"
|
||||
// Bech32PrefixConsPub defines the Bech32 prefix of a consensus node public key
|
||||
Bech32PrefixConsPub = "terravalconspub"
|
||||
)
|
|
@ -0,0 +1,19 @@
|
|||
package utils
|
||||
|
||||
import "encoding/json"
|
||||
|
||||
type restError struct {
|
||||
Error string `json:"error"`
|
||||
}
|
||||
|
||||
func newError(err error) restError {
|
||||
return restError{err.Error()}
|
||||
}
|
||||
|
||||
func (e restError) marshal() []byte {
|
||||
out, err := json.Marshal(e)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
return out
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
txbldr "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||
|
||||
"github.com/terra-project/core/app"
|
||||
)
|
||||
|
||||
var cdc *codec.Codec
|
||||
|
||||
func init() {
|
||||
cdc = app.MakeCodec()
|
||||
|
||||
config := sdk.GetConfig()
|
||||
config.SetCoinType(330)
|
||||
config.SetFullFundraiserPath("44'/330'/0'/0/0")
|
||||
config.SetBech32PrefixForAccount(Bech32PrefixAccAddr, Bech32PrefixAccPub)
|
||||
config.SetBech32PrefixForValidator(Bech32PrefixValAddr, Bech32PrefixValPub)
|
||||
config.SetBech32PrefixForConsensusNode(Bech32PrefixConsAddr, Bech32PrefixConsPub)
|
||||
config.Seal()
|
||||
}
|
||||
|
||||
// Generator tx generator
|
||||
type Generator struct {
|
||||
KeyDir string `json:"key_dir" yaml:"key_dir"`
|
||||
Node string `json:"node" yaml:"node"`
|
||||
|
||||
KeyName string `json:"key_name" yaml:"key_name,omitempty"`
|
||||
KeyPassword string `json:"key_password" yaml:"key_password,omitempty"`
|
||||
|
||||
TriggerInterval string `json:"trigger_interval" yaml:"trigger_interval"`
|
||||
FeeAmount string `json:"fee_amount" yaml:"fee_amount"`
|
||||
|
||||
Version string `yaml:"version,omitempty"`
|
||||
Commit string `yaml:"commit,omitempty"`
|
||||
Branch string `yaml:"branch,omitempty"`
|
||||
}
|
||||
|
||||
// BankSend handles the /tx/bank/send route
|
||||
func (g Generator) SendTx(height int64, chainID string) (err error) {
|
||||
|
||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(g.KeyName)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
acc, err := g.QueryAccount(cdc, info.GetAddress())
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
targetFeeCoin, err := sdk.ParseCoin(g.FeeAmount)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
targetFeeDenom := targetFeeCoin.Denom
|
||||
spendableCoins := acc.SpendableCoins(time.Now())
|
||||
spendableAmount := spendableCoins.AmountOf(targetFeeDenom)
|
||||
|
||||
if spendableAmount.LT(targetFeeCoin.Amount) {
|
||||
err = fmt.Errorf("not enough balance to distribute fee")
|
||||
return
|
||||
}
|
||||
|
||||
// NOTE - no tax will be charged
|
||||
sendAmount := sdk.NewInt(1)
|
||||
sendCoins := sdk.NewCoins(sdk.NewCoin(targetFeeDenom, sendAmount))
|
||||
feeCoins := sdk.NewCoins(targetFeeCoin)
|
||||
stdTx := auth.NewStdTx(
|
||||
[]sdk.Msg{bank.NewMsgSend(acc.GetAddress(), acc.GetAddress(), sendCoins)},
|
||||
auth.NewStdFee(100000, feeCoins),
|
||||
[]auth.StdSignature{},
|
||||
"",
|
||||
)
|
||||
|
||||
signedTx, err := g.signTx(stdTx, acc, chainID)
|
||||
|
||||
txHash, err := g.BroadcastTx(signedTx)
|
||||
fmt.Println(txHash)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (g Generator) signTx(stdTx auth.StdTx, acc auth.Account, chainID string) (signedTx auth.StdTx, err error) {
|
||||
|
||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
stdSign := txbldr.StdSignMsg{
|
||||
Memo: stdTx.Memo,
|
||||
Msgs: stdTx.Msgs,
|
||||
ChainID: chainID,
|
||||
AccountNumber: uint64(acc.GetAccountNumber()),
|
||||
Sequence: uint64(acc.GetSequence()),
|
||||
Fee: auth.StdFee{
|
||||
Amount: stdTx.Fee.Amount,
|
||||
Gas: uint64(stdTx.Fee.Gas),
|
||||
},
|
||||
}
|
||||
|
||||
sigBytes, pubkey, err := kb.Sign(g.KeyName, g.KeyPassword, sdk.MustSortJSON(cdc.MustMarshalJSON(stdSign)))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
sigs := append(stdTx.GetSignatures(), auth.StdSignature{
|
||||
PubKey: pubkey,
|
||||
Signature: sigBytes,
|
||||
})
|
||||
|
||||
signedTx = auth.NewStdTx(stdTx.GetMsgs(), stdTx.Fee, sigs, stdTx.GetMemo())
|
||||
return
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client/keys"
|
||||
ckeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
|
||||
bip39 "github.com/cosmos/go-bip39"
|
||||
)
|
||||
|
||||
// GetKeys returns key list
|
||||
func (g Generator) GetKeys() (out []byte, err error) {
|
||||
|
||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
infos, err := kb.List()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if len(infos) == 0 {
|
||||
return []byte{}, nil
|
||||
}
|
||||
|
||||
keysOutput, err := ckeys.Bech32KeysOutput(infos)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(keysOutput)
|
||||
}
|
||||
|
||||
// AddNewKey appends new key
|
||||
func (g Generator) AddNewKey(name, password, mnemonic string, oldHdPath bool) (out []byte, err error) {
|
||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if name == "" || password == "" {
|
||||
err = fmt.Errorf("must include both password and name with request")
|
||||
return
|
||||
}
|
||||
|
||||
// if mnemonic is empty, generate one
|
||||
if mnemonic == "" {
|
||||
_, mnemonic, _ = ckeys.NewInMemory().CreateMnemonic("inmemorykey", ckeys.English, "123456789", ckeys.Secp256k1)
|
||||
}
|
||||
|
||||
if !bip39.IsMnemonicValid(mnemonic) {
|
||||
err = fmt.Errorf("invalid mnemonic")
|
||||
return
|
||||
}
|
||||
|
||||
_, err = kb.Get(name)
|
||||
if err == nil {
|
||||
err = fmt.Errorf("key %s already exists", name)
|
||||
return
|
||||
}
|
||||
|
||||
account := uint32(0)
|
||||
index := uint32(0)
|
||||
coinType := uint32(330)
|
||||
if oldHdPath {
|
||||
coinType = uint32(118)
|
||||
}
|
||||
|
||||
hdParams := hd.NewFundraiserParams(account, coinType, index)
|
||||
info, err := kb.Derive(name, mnemonic, "", password, *hdParams)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
keyOutput, err := ckeys.Bech32KeyOutput(info)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
keyOutput.Mnemonic = mnemonic
|
||||
|
||||
out, err = json.Marshal(keyOutput)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// GetKey is the handler for the GET /keys/{name}
|
||||
func (g Generator) GetKey(name, bechPrefix string) (out []byte, err error) {
|
||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if bechPrefix == "" {
|
||||
bechPrefix = "acc"
|
||||
}
|
||||
|
||||
bechKeyOut, err := getBechKeyOut(bechPrefix)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
info, err := kb.Get(name)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
keyOutput, err := bechKeyOut(info)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
out, err = json.Marshal(keyOutput)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
type bechKeyOutFn func(keyInfo ckeys.Info) (ckeys.KeyOutput, error)
|
||||
|
||||
func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) {
|
||||
switch bechPrefix {
|
||||
case "acc":
|
||||
return ckeys.Bech32KeyOutput, nil
|
||||
case "val":
|
||||
return ckeys.Bech32ValKeyOutput, nil
|
||||
case "cons":
|
||||
return ckeys.Bech32ConsKeyOutput, nil
|
||||
}
|
||||
|
||||
return nil, fmt.Errorf("invalid Bech32 prefix encoding provided: %s", bechPrefix)
|
||||
}
|
||||
|
||||
// UpdateKey update key password
|
||||
func (g Generator) UpdateKey(name, newPassword, oldPassword string) (err error) {
|
||||
|
||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = kb.Update(name, oldPassword, func() (string, error) { return newPassword, nil })
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// DeleteKey is the handler for the DELETE /keys/{name}
|
||||
func (g Generator) DeleteKey(name, password string) (err error) {
|
||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = kb.Delete(name, password, false)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,141 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/codec"
|
||||
cmn "github.com/tendermint/tendermint/libs/common"
|
||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||
|
||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
||||
|
||||
"github.com/terra-project/core/x/treasury"
|
||||
)
|
||||
|
||||
// SimulateGas simulates gas for a transaction
|
||||
func (g Generator) SimulateGas(cdc *codec.Codec, txbytes []byte) (res uint64, err error) {
|
||||
result, err := rpcclient.NewHTTP(g.Node, "/websocket").ABCIQueryWithOptions(
|
||||
"/app/simulate",
|
||||
cmn.HexBytes(txbytes),
|
||||
rpcclient.ABCIQueryOptions{},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !result.Response.IsOK() {
|
||||
return 0, errors.New(result.Response.Log)
|
||||
}
|
||||
|
||||
var simulationResult sdk.Result
|
||||
if err := cdc.UnmarshalBinaryLengthPrefixed(result.Response.Value, &simulationResult); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
|
||||
return simulationResult.GasUsed, nil
|
||||
}
|
||||
|
||||
// QueryAccount query account info
|
||||
func (g Generator) QueryAccount(cdc *codec.Codec, accAddr sdk.AccAddress) (acc auth.Account, err error) {
|
||||
bz, err := cdc.MarshalJSON(auth.NewQueryAccountParams(accAddr))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := rpcclient.NewHTTP(g.Node, "/websocket").ABCIQueryWithOptions(
|
||||
"custom/acc/account",
|
||||
bz,
|
||||
rpcclient.ABCIQueryOptions{},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !result.Response.IsOK() {
|
||||
err = errors.New(result.Response.Log)
|
||||
return
|
||||
}
|
||||
|
||||
if err = cdc.UnmarshalJSON(result.Response.Value, &acc); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// QueryTaxRate query tax rate
|
||||
func (g Generator) QueryTaxRate(cdc *codec.Codec, epoch int64) (taxRate sdk.Dec, err error) {
|
||||
result, err := rpcclient.NewHTTP(g.Node, "/websocket").ABCIQueryWithOptions(
|
||||
fmt.Sprintf("custom/treasury/tax-rate/%d", epoch),
|
||||
[]byte{},
|
||||
rpcclient.ABCIQueryOptions{},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !result.Response.IsOK() {
|
||||
err = errors.New(result.Response.Log)
|
||||
return
|
||||
}
|
||||
|
||||
var resp treasury.QueryTaxRateResponse
|
||||
if err = cdc.UnmarshalJSON(result.Response.Value, &resp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
taxRate = resp.TaxRate
|
||||
return
|
||||
}
|
||||
|
||||
// QueryTaxCap query tax cap
|
||||
func (g Generator) QueryTaxCap(cdc *codec.Codec, denom string) (taxCap sdk.Int, err error) {
|
||||
result, err := rpcclient.NewHTTP(g.Node, "/websocket").ABCIQueryWithOptions(
|
||||
fmt.Sprintf("custom/treasury/tax-cap/%s", denom),
|
||||
[]byte{},
|
||||
rpcclient.ABCIQueryOptions{},
|
||||
)
|
||||
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if !result.Response.IsOK() {
|
||||
err = errors.New(result.Response.Log)
|
||||
return
|
||||
}
|
||||
|
||||
var resp treasury.QueryTaxCapResponse
|
||||
if err = cdc.UnmarshalJSON(result.Response.Value, &resp); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
taxCap = resp.TaxCap
|
||||
return
|
||||
}
|
||||
|
||||
// BroadcastTx broadcast tx
|
||||
func (g Generator) BroadcastTx(tx auth.StdTx) (txHash string, err error) {
|
||||
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
result, err := rpcclient.NewHTTP(g.Node, "/websocket").BroadcastTxSync(txBytes)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
if result.Code != 0 {
|
||||
err = errors.New(result.Log)
|
||||
return
|
||||
}
|
||||
|
||||
txHash = result.Hash.String()
|
||||
return
|
||||
}
|
|
@ -0,0 +1,100 @@
|
|||
package utils
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"log"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/gorilla/websocket"
|
||||
amino "github.com/tendermint/go-amino"
|
||||
ctypes "github.com/tendermint/tendermint/rpc/core/types"
|
||||
rpc "github.com/tendermint/tendermint/rpc/lib/types"
|
||||
abci "github.com/tendermint/tendermint/types"
|
||||
)
|
||||
|
||||
var aminoCdc = amino.NewCodec()
|
||||
|
||||
func init() {
|
||||
ctypes.RegisterAmino(aminoCdc)
|
||||
}
|
||||
|
||||
// ListenNewBlock listen new block and trigger sendtx
|
||||
func (g Generator) ListenNewBLock() {
|
||||
|
||||
triggerInterval, err := strconv.ParseInt(g.TriggerInterval, 10, 64)
|
||||
if err != nil {
|
||||
log.Fatal("Trigger interval should be number", err)
|
||||
}
|
||||
|
||||
var scheme string
|
||||
var host string
|
||||
if strings.HasPrefix(g.Node, "https") {
|
||||
scheme = "wss"
|
||||
host = strings.TrimPrefix(g.Node, "https://")
|
||||
} else {
|
||||
scheme = "ws"
|
||||
host = strings.TrimPrefix(g.Node, "http://")
|
||||
}
|
||||
|
||||
u := url.URL{Scheme: scheme, Host: host, Path: "/websocket"}
|
||||
log.Printf("connecting to %s", u.String())
|
||||
|
||||
c, _, err := websocket.DefaultDialer.Dial(u.String(), nil)
|
||||
if err != nil {
|
||||
log.Fatal("dial:", err)
|
||||
}
|
||||
defer c.Close()
|
||||
|
||||
bz, err := json.Marshal(JSONRPC{
|
||||
JSONRPC: "2.0",
|
||||
Method: "subscribe",
|
||||
ID: "0",
|
||||
Params: Query{
|
||||
Query: "tm.event='NewBlock'",
|
||||
},
|
||||
})
|
||||
|
||||
c.WriteMessage(websocket.TextMessage, bz)
|
||||
|
||||
for {
|
||||
_, bz, _ := c.ReadMessage()
|
||||
|
||||
var rpcResponse rpc.RPCResponse
|
||||
var resultEvent ctypes.ResultEvent
|
||||
// var newBlockEvent abci.EventDataNewBlock
|
||||
err := aminoCdc.UnmarshalJSON(bz, &rpcResponse)
|
||||
if err != nil {
|
||||
continue
|
||||
}
|
||||
|
||||
err = aminoCdc.UnmarshalJSON(rpcResponse.Result, &resultEvent)
|
||||
blockEvent, ok := resultEvent.Data.(abci.EventDataNewBlock)
|
||||
if !ok {
|
||||
continue
|
||||
}
|
||||
|
||||
if blockEvent.Block.Height%triggerInterval == 0 {
|
||||
err := g.SendTx(blockEvent.Block.Height, blockEvent.Block.ChainID)
|
||||
if err != nil {
|
||||
log.Fatal("Failed to send tx", err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// no-lint
|
||||
type Query struct {
|
||||
Query string `json:"query"`
|
||||
}
|
||||
|
||||
// no-lint
|
||||
type JSONRPC struct {
|
||||
JSONRPC string `json:"jsonrpc"`
|
||||
Method string `json:"method"`
|
||||
ID string `json:"id"`
|
||||
Params Query `json:"params"`
|
||||
}
|
Loading…
Reference in New Issue