Merge pull request #1 from terra-project/develop

go version automatic feegiver
This commit is contained in:
yys 2019-08-07 18:07:57 +09:00 committed by GitHub
commit 4dea694f47
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 1490 additions and 845 deletions

156
.gitignore vendored
View File

@ -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

42
Makefile Normal file
View File

@ -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

View File

@ -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:
```

62
cmd/config.go Normal file
View File

@ -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)
}

173
cmd/keys.go Normal file
View File

@ -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)
}

84
cmd/root.go Normal file
View File

@ -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)
}

50
cmd/start.go Normal file
View File

@ -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
dist/index.d.ts vendored
View File

@ -1 +0,0 @@
export {};

213
dist/index.js vendored
View File

@ -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

1
dist/index.js.map vendored

File diff suppressed because one or more lines are too long

36
dist/utils/rest.d.ts vendored
View File

@ -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;

51
dist/utils/rest.js vendored
View File

@ -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

View File

@ -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"}

25
go.mod Normal file
View File

@ -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

334
go.sum Normal file
View File

@ -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=

BIN
keys/keys.db/000004.ldb Normal file

Binary file not shown.

BIN
keys/keys.db/000007.ldb Normal file

Binary file not shown.

BIN
keys/keys.db/000010.log Normal file

Binary file not shown.

1
keys/keys.db/CURRENT Normal file
View File

@ -0,0 +1 @@
MANIFEST-000011

1
keys/keys.db/CURRENT.bak Normal file
View File

@ -0,0 +1 @@
MANIFEST-000009

0
keys/keys.db/LOCK Normal file
View File

54
keys/keys.db/LOG Normal file
View File

@ -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.

21
main.go Normal file
View File

@ -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()
}

View File

@ -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"
}
}

View File

@ -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()

View File

@ -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

View File

@ -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"
]
}

21
utils/constants.go Normal file
View File

@ -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"
)

19
utils/errors.go Normal file
View File

@ -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
}

128
utils/generator.go Normal file
View File

@ -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
}

173
utils/keys.go Normal file
View File

@ -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
}

141
utils/rpc.go Normal file
View File

@ -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
}

100
utils/websocket.go Normal file
View File

@ -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"`
}