mirror of https://github.com/certusone/santa.git
parent
e190a7c08c
commit
7298512113
|
@ -0,0 +1,24 @@
|
||||||
|
version: 2.1
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build:
|
||||||
|
docker:
|
||||||
|
- image: circleci/golang:1.11
|
||||||
|
steps:
|
||||||
|
- checkout
|
||||||
|
- run:
|
||||||
|
name: install
|
||||||
|
command: make install
|
||||||
|
- run:
|
||||||
|
name: codecov report
|
||||||
|
command: |
|
||||||
|
go test -timeout 3600s ./utils/... -coverprofile=coverage.txt
|
||||||
|
- run:
|
||||||
|
name: upload
|
||||||
|
command: bash <(curl -s https://codecov.io/bash) -f coverage.txt
|
||||||
|
|
||||||
|
workflows:
|
||||||
|
version: 2
|
||||||
|
test-suite:
|
||||||
|
jobs:
|
||||||
|
- build
|
|
@ -7,6 +7,7 @@
|
||||||
*.dylib
|
*.dylib
|
||||||
|
|
||||||
.DS_Store
|
.DS_Store
|
||||||
|
.vscode
|
||||||
|
|
||||||
# Test binary, build with `go test -c`
|
# Test binary, build with `go test -c`
|
||||||
*.test
|
*.test
|
||||||
|
|
|
@ -0,0 +1,17 @@
|
||||||
|
{
|
||||||
|
// Use IntelliSense to learn about possible attributes.
|
||||||
|
// Hover to view descriptions of existing attributes.
|
||||||
|
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||||
|
"version": "0.2.0",
|
||||||
|
"configurations": [
|
||||||
|
{
|
||||||
|
"name": "Launch",
|
||||||
|
"type": "go",
|
||||||
|
"request": "launch",
|
||||||
|
"mode": "auto",
|
||||||
|
"program": "${fileDirname}",
|
||||||
|
"env": {},
|
||||||
|
"args": []
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
2
Makefile
2
Makefile
|
@ -1,4 +1,4 @@
|
||||||
BINARY = feegiver
|
BINARY = santa
|
||||||
GITHUB_USERNAME = terra-project
|
GITHUB_USERNAME = terra-project
|
||||||
VERSION = v0.1.0
|
VERSION = v0.1.0
|
||||||
GOARCH = amd64
|
GOARCH = amd64
|
||||||
|
|
55
README.md
55
README.md
|
@ -1,54 +1,55 @@
|
||||||
# Build & Install
|
# Santa Claus
|
||||||
|
|
||||||
|
![banner](docs/terra-core.png)
|
||||||
|
|
||||||
|
Santa Claus subsidizes block rewards for Terra's Columbus mainnet. It is intended to subsidize the security of the network until Terra transaction volume (and attendent staking returns from transaction fees) has had sufficient time to mature. A detailed explanation on the [motivation](./MOTIVATION.md) for starting Santa Claus is explained.
|
||||||
|
|
||||||
|
## Build & Install
|
||||||
|
|
||||||
|
First, check out the rep
|
||||||
|
|
||||||
```
|
```
|
||||||
$ git clone https://github.com/terra-project/feegiver.git
|
$ git clone https://github.com/terra-project/santa.git
|
||||||
$ git checkout master
|
$ git checkout master
|
||||||
```
|
```
|
||||||
|
|
||||||
## Install
|
### Install
|
||||||
```
|
```
|
||||||
$ make install
|
$ make install
|
||||||
```
|
```
|
||||||
## make config
|
### Make config
|
||||||
```
|
```
|
||||||
$ feegiver config
|
$ santa config
|
||||||
```
|
```
|
||||||
## change config
|
### Change config
|
||||||
```
|
```
|
||||||
$ vim ~/.feegiver/config.yaml
|
$ vim ~/.santa/config.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
## Add Key
|
### Add / Recover Key
|
||||||
```
|
```
|
||||||
$ feegiver keys add yun
|
$ 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"}
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
## Recover Key
|
## Recover Key
|
||||||
```
|
```
|
||||||
$ feegiver keys add yun --recover
|
$ 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
|
## Start Server
|
||||||
```
|
```
|
||||||
$ feegiver start yun
|
$ santa start yun
|
||||||
Enter the passphrase:
|
Enter the passphrase:
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
## Status
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Mechanism
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ import (
|
||||||
|
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/terra-project/feegiver/utils"
|
"github.com/terra-project/santa/utils"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -21,8 +21,8 @@ var configCmd = &cobra.Command{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
g := utils.Generator{
|
g := utils.SantaApp{
|
||||||
KeyDir: fmt.Sprintf("%s/.feegiver", home),
|
KeyDir: fmt.Sprintf("%s/.santa", home),
|
||||||
Node: "http://localhost:26657",
|
Node: "http://localhost:26657",
|
||||||
|
|
||||||
TriggerInterval: "5",
|
TriggerInterval: "5",
|
||||||
|
|
10
cmd/keys.go
10
cmd/keys.go
|
@ -29,7 +29,7 @@ var keysList = &cobra.Command{
|
||||||
Use: "list",
|
Use: "list",
|
||||||
Short: "Fetch all keys managed by the server",
|
Short: "Fetch all keys managed by the server",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
out, err := generator.GetKeys()
|
out, err := app.GetKeys()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed: %s", err.Error())
|
log.Fatalf("Failed: %s", err.Error())
|
||||||
return
|
return
|
||||||
|
@ -76,7 +76,7 @@ var keysAdd = &cobra.Command{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
out, err := generator.AddNewKey(args[0], password, mnemonic, oldHdPath)
|
out, err := app.AddNewKey(args[0], password, mnemonic, oldHdPath)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed: %s", err.Error())
|
log.Fatalf("Failed: %s", err.Error())
|
||||||
|
@ -92,7 +92,7 @@ var keyShow = &cobra.Command{
|
||||||
Args: cobra.ExactArgs(1),
|
Args: cobra.ExactArgs(1),
|
||||||
Short: "Fetch details for one key",
|
Short: "Fetch details for one key",
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
out, err := generator.GetKey(args[0], viper.GetString(flagBech))
|
out, err := app.GetKey(args[0], viper.GetString(flagBech))
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed: %s", err.Error())
|
log.Fatalf("Failed: %s", err.Error())
|
||||||
|
@ -123,7 +123,7 @@ var keyPut = &cobra.Command{
|
||||||
log.Fatalf("failed reading new password: %s", err.Error())
|
log.Fatalf("failed reading new password: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = generator.UpdateKey(args[0], password, newPassword)
|
err = app.UpdateKey(args[0], password, newPassword)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed: %s", err.Error())
|
log.Fatalf("Failed: %s", err.Error())
|
||||||
return
|
return
|
||||||
|
@ -145,7 +145,7 @@ var keyDelete = &cobra.Command{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
err = generator.DeleteKey(args[0], password)
|
err = app.DeleteKey(args[0], password)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("Failed: %s", err.Error())
|
log.Fatalf("Failed: %s", err.Error())
|
||||||
return
|
return
|
||||||
|
|
17
cmd/root.go
17
cmd/root.go
|
@ -7,7 +7,7 @@ import (
|
||||||
|
|
||||||
homedir "github.com/mitchellh/go-homedir"
|
homedir "github.com/mitchellh/go-homedir"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/terra-project/feegiver/utils"
|
"github.com/terra-project/santa/utils"
|
||||||
yaml "gopkg.in/yaml.v2"
|
yaml "gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -16,7 +16,7 @@ var (
|
||||||
cfgFile string
|
cfgFile string
|
||||||
|
|
||||||
// The actual app config
|
// The actual app config
|
||||||
generator utils.Generator
|
app utils.SantaApp
|
||||||
|
|
||||||
// Version for the application. Set via ldflags
|
// Version for the application. Set via ldflags
|
||||||
Version = "undefined"
|
Version = "undefined"
|
||||||
|
@ -30,7 +30,7 @@ var (
|
||||||
|
|
||||||
// rootCmd represents the base command when called without any subcommands
|
// rootCmd represents the base command when called without any subcommands
|
||||||
var rootCmd = &cobra.Command{
|
var rootCmd = &cobra.Command{
|
||||||
Use: "feegiver",
|
Use: "santa",
|
||||||
Short: "An fee giver server for terra",
|
Short: "An fee giver server for terra",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -45,12 +45,12 @@ func Execute() {
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cobra.OnInitialize(initConfig)
|
cobra.OnInitialize(initConfig)
|
||||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.feegiver/config.yaml)")
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.santa/config.yaml)")
|
||||||
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
|
||||||
}
|
}
|
||||||
|
|
||||||
func initConfig() {
|
func initConfig() {
|
||||||
generator = utils.Generator{
|
app = utils.SantaApp{
|
||||||
Version: Version,
|
Version: Version,
|
||||||
Commit: Commit,
|
Commit: Commit,
|
||||||
Branch: Branch,
|
Branch: Branch,
|
||||||
|
@ -72,13 +72,16 @@ func initConfig() {
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfgFile = fmt.Sprintf("%s/.feegiver/config.yaml", home)
|
cfgFile = fmt.Sprintf("%s/.santa/config.yaml", home)
|
||||||
|
if _, err := os.Stat(cfgFile); err == nil {
|
||||||
bz, err = ioutil.ReadFile(cfgFile)
|
bz, err = ioutil.ReadFile(cfgFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
yaml.Unmarshal(bz, &app)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
yaml.Unmarshal(bz, &generator)
|
|
||||||
}
|
}
|
||||||
|
|
12
cmd/start.go
12
cmd/start.go
|
@ -24,24 +24,22 @@ var startCmd = &cobra.Command{
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
generator.KeyName = args[0]
|
app.KeyName = args[0]
|
||||||
generator.KeyPassword = password
|
app.KeyPassword = password
|
||||||
|
|
||||||
kb, err := keys.NewKeyBaseFromDir(generator.KeyDir)
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to open keybase: %s", err.Error())
|
log.Fatalf("failed to open keybase: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
_, err = kb.Get(generator.KeyName)
|
_, err = kb.Get(app.KeyName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatalf("failed to get account: %s", err.Error())
|
log.Fatalf("failed to get account: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
generator.ListenNewBLock()
|
app.ListenNewBLock(false)
|
||||||
// err := generator.SendTx(10000, "vodka")
|
|
||||||
// fmt.Println(err)
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
mode: set
|
2
go.mod
2
go.mod
|
@ -1,4 +1,4 @@
|
||||||
module github.com/terra-project/feegiver
|
module github.com/terra-project/santa
|
||||||
|
|
||||||
go 1.12
|
go 1.12
|
||||||
|
|
||||||
|
|
4
go.sum
4
go.sum
|
@ -103,6 +103,7 @@ github.com/golangci/prealloc v0.0.0-20180630174525-215b22d4de21/go.mod h1:tf5+bz
|
||||||
github.com/golangci/revgrep v0.0.0-20180526074752-d9c87f5ffaf0/go.mod h1:qOQCunEYvmd/TLamH+7LlVccLvUH5kZNhbCgTHoBbp4=
|
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/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/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||||
|
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf h1:+RRA9JqSOZFfKrOeqr2z77+8R2RKyh8PG66dcu1V0ck=
|
||||||
github.com/google/gofuzz v0.0.0-20170612174753-24818f796faf/go.mod h1:HP5RmnzzSNb993RKQDq4+1A4ia9nllfqcQFTQJedwGI=
|
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/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/mux v1.7.0/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
|
||||||
|
@ -128,8 +129,10 @@ github.com/klauspost/cpuid v0.0.0-20180405133222-e7e905edc00e/go.mod h1:Pj4uuM52
|
||||||
github.com/klauspost/cpuid v1.2.0/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/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/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
|
||||||
|
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
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/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
|
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/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/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.7.6/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
|
||||||
|
@ -318,6 +321,7 @@ google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij
|
||||||
gopkg.in/airbrake/gobrake.v2 v2.0.9/go.mod h1:/h5ZAUhDkGaJfjzjKLSjv6zCL6O0LLBxU4K+aSYdM/U=
|
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/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 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||||
|
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
@ -1 +0,0 @@
|
||||||
MANIFEST-000011
|
|
|
@ -1 +0,0 @@
|
||||||
MANIFEST-000009
|
|
|
@ -1,54 +0,0 @@
|
||||||
=============== 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.
2
main.go
2
main.go
|
@ -14,7 +14,7 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import "github.com/terra-project/feegiver/cmd"
|
import "github.com/terra-project/santa/cmd"
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
cmd.Execute()
|
cmd.Execute()
|
||||||
|
|
|
@ -11,13 +11,13 @@ import (
|
||||||
txbldr "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
txbldr "github.com/cosmos/cosmos-sdk/x/auth/client/txbuilder"
|
||||||
"github.com/cosmos/cosmos-sdk/x/bank"
|
"github.com/cosmos/cosmos-sdk/x/bank"
|
||||||
|
|
||||||
"github.com/terra-project/core/app"
|
core "github.com/terra-project/core/app"
|
||||||
)
|
)
|
||||||
|
|
||||||
var cdc *codec.Codec
|
var cdc *codec.Codec
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
cdc = app.MakeCodec()
|
cdc = core.MakeCodec()
|
||||||
|
|
||||||
config := sdk.GetConfig()
|
config := sdk.GetConfig()
|
||||||
config.SetCoinType(330)
|
config.SetCoinType(330)
|
||||||
|
@ -28,8 +28,8 @@ func init() {
|
||||||
config.Seal()
|
config.Seal()
|
||||||
}
|
}
|
||||||
|
|
||||||
// Generator tx generator
|
// SantaApp tx app
|
||||||
type Generator struct {
|
type SantaApp struct {
|
||||||
KeyDir string `json:"key_dir" yaml:"key_dir"`
|
KeyDir string `json:"key_dir" yaml:"key_dir"`
|
||||||
Node string `json:"node" yaml:"node"`
|
Node string `json:"node" yaml:"node"`
|
||||||
|
|
||||||
|
@ -44,25 +44,24 @@ type Generator struct {
|
||||||
Branch string `yaml:"branch,omitempty"`
|
Branch string `yaml:"branch,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// BankSend handles the /tx/bank/send route
|
// Send BankSend Tx
|
||||||
func (g Generator) SendTx(height int64, chainID string) (err error) {
|
func (app SantaApp) SendTx(chainID string) (txHash string, err error) {
|
||||||
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
info, err := kb.Get(g.KeyName)
|
info, err := kb.Get(app.KeyName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
acc, err := g.QueryAccount(cdc, info.GetAddress())
|
acc, err := app.QueryAccount(cdc, info.GetAddress())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
targetFeeCoin, err := sdk.ParseCoin(g.FeeAmount)
|
targetFeeCoin, err := sdk.ParseCoin(app.FeeAmount)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -87,16 +86,15 @@ func (g Generator) SendTx(height int64, chainID string) (err error) {
|
||||||
"",
|
"",
|
||||||
)
|
)
|
||||||
|
|
||||||
signedTx, err := g.signTx(stdTx, acc, chainID)
|
signedTx, err := app.signTx(stdTx, acc, chainID)
|
||||||
|
|
||||||
txHash, err := g.BroadcastTx(signedTx)
|
txHash, err = app.BroadcastTx(signedTx)
|
||||||
fmt.Println(txHash)
|
return
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g Generator) signTx(stdTx auth.StdTx, acc auth.Account, chainID string) (signedTx auth.StdTx, err error) {
|
func (app SantaApp) signTx(stdTx auth.StdTx, acc auth.Account, chainID string) (signedTx auth.StdTx, err error) {
|
||||||
|
|
||||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -113,7 +111,7 @@ func (g Generator) signTx(stdTx auth.StdTx, acc auth.Account, chainID string) (s
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
sigBytes, pubkey, err := kb.Sign(g.KeyName, g.KeyPassword, sdk.MustSortJSON(cdc.MustMarshalJSON(stdSign)))
|
sigBytes, pubkey, err := kb.Sign(app.KeyName, app.KeyPassword, sdk.MustSortJSON(cdc.MustMarshalJSON(stdSign)))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
|
@ -0,0 +1,48 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestBuildSendTx(t *testing.T) {
|
||||||
|
//----------------------------------------
|
||||||
|
app := setupWithNotExistsAccount(t)
|
||||||
|
defer os.RemoveAll(app.KeyDir)
|
||||||
|
|
||||||
|
// not exists
|
||||||
|
_, err := app.SendTx(testChainID)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
app2 := setup(t)
|
||||||
|
defer os.RemoveAll(app2.KeyDir)
|
||||||
|
|
||||||
|
// not exist key
|
||||||
|
_, err = app2.SendTx(testChainID)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
app3 := setupWithNoBalanceAccount(t)
|
||||||
|
defer os.RemoveAll(app3.KeyDir)
|
||||||
|
|
||||||
|
// not enough balance to pay fee
|
||||||
|
_, err = app3.SendTx(testChainID)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
app4 := setupWithPlentyBalanceAccount(t)
|
||||||
|
defer os.RemoveAll(app4.KeyDir)
|
||||||
|
|
||||||
|
// invalid fee amount
|
||||||
|
app4.FeeAmount = "1"
|
||||||
|
_, err = app4.SendTx(testChainID)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
//----------------------------------------
|
||||||
|
app5 := setupWithPlentyBalanceAccount(t)
|
||||||
|
defer os.RemoveAll(app5.KeyDir)
|
||||||
|
_, err = app5.SendTx(testChainID)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
|
@ -1,19 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
|
@ -11,9 +11,9 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// GetKeys returns key list
|
// GetKeys returns key list
|
||||||
func (g Generator) GetKeys() (out []byte, err error) {
|
func (app SantaApp) GetKeys() (out []byte, err error) {
|
||||||
|
|
||||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,8 @@ func (g Generator) GetKeys() (out []byte, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddNewKey appends new key
|
// AddNewKey appends new key
|
||||||
func (g Generator) AddNewKey(name, password, mnemonic string, oldHdPath bool) (out []byte, err error) {
|
func (app SantaApp) AddNewKey(name, password, mnemonic string, oldHdPath bool) (out []byte, err error) {
|
||||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -93,8 +93,8 @@ func (g Generator) AddNewKey(name, password, mnemonic string, oldHdPath bool) (o
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetKey is the handler for the GET /keys/{name}
|
// GetKey is the handler for the GET /keys/{name}
|
||||||
func (g Generator) GetKey(name, bechPrefix string) (out []byte, err error) {
|
func (app SantaApp) GetKey(name, bechPrefix string) (out []byte, err error) {
|
||||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -142,9 +142,13 @@ func getBechKeyOut(bechPrefix string) (bechKeyOutFn, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// UpdateKey update key password
|
// UpdateKey update key password
|
||||||
func (g Generator) UpdateKey(name, newPassword, oldPassword string) (err error) {
|
func (app SantaApp) UpdateKey(name, oldPassword, newPassword string) (err error) {
|
||||||
|
if name == "" || oldPassword == "" || newPassword == "" {
|
||||||
|
err = fmt.Errorf("must include name, oldPassword, and newPassword with request")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -158,8 +162,8 @@ func (g Generator) UpdateKey(name, newPassword, oldPassword string) (err error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// DeleteKey is the handler for the DELETE /keys/{name}
|
// DeleteKey is the handler for the DELETE /keys/{name}
|
||||||
func (g Generator) DeleteKey(name, password string) (err error) {
|
func (app SantaApp) DeleteKey(name, password string) (err error) {
|
||||||
kb, err := keys.NewKeyBaseFromDir(g.KeyDir)
|
kb, err := keys.NewKeyBaseFromDir(app.KeyDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,128 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
ckeys "github.com/cosmos/cosmos-sdk/crypto/keys"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestAddKey(t *testing.T) {
|
||||||
|
app := setup(t)
|
||||||
|
defer os.RemoveAll(app.KeyDir)
|
||||||
|
|
||||||
|
out, err := app.GetKeys()
|
||||||
|
require.NoError(t, err)
|
||||||
|
require.Equal(t, 0, len(out))
|
||||||
|
|
||||||
|
// invalid name
|
||||||
|
_, err = app.AddNewKey(testInvalidName, testPassword, testMnemonic, false)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// invalid password
|
||||||
|
_, err = app.AddNewKey(testName, testInvalidPassword, testMnemonic, false)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// invalid mnemonic
|
||||||
|
_, err = app.AddNewKey(testName, testPassword, testInvalidMnemonic, false)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// valid add
|
||||||
|
out, err = app.AddNewKey(testName, testPassword, testMnemonic, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var output ckeys.KeyOutput
|
||||||
|
err = json.Unmarshal(out, &output)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
require.Equal(t, testName, output.Name)
|
||||||
|
require.Equal(t, "terra1ch5ezwqftx8z8969l30j634wzs8772xfp5wur4", output.Address)
|
||||||
|
require.Equal(t, "terrapub1addwnpepqvgqm0lpmjn4dga903dugvmw8qtzcush2agl8lx3xz2mxcm8vvwf2adw7e3", output.PubKey)
|
||||||
|
require.Equal(t, testMnemonic, output.Mnemonic)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGetKey(t *testing.T) {
|
||||||
|
app := setup(t)
|
||||||
|
defer os.RemoveAll(app.KeyDir)
|
||||||
|
|
||||||
|
out, err := app.GetKey(testName, "acc")
|
||||||
|
require.Error(t, err)
|
||||||
|
require.Equal(t, 0, len(out))
|
||||||
|
|
||||||
|
out, err = app.AddNewKey(testName, testPassword, testMnemonic, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
_, err = app.GetKey(testName, "acc")
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestDeleteKey(t *testing.T) {
|
||||||
|
app := setup(t)
|
||||||
|
defer os.RemoveAll(app.KeyDir)
|
||||||
|
|
||||||
|
out, err := app.AddNewKey(testName, testPassword, testMnemonic, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
out, err = app.GetKeys()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var outputs []ckeys.KeyOutput
|
||||||
|
err = json.Unmarshal(out, &outputs)
|
||||||
|
require.Equal(t, 1, len(outputs))
|
||||||
|
|
||||||
|
// not exist name
|
||||||
|
err = app.DeleteKey(testInvalidName, testPassword)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// invalid password
|
||||||
|
err = app.DeleteKey(testName, testInvalidPassword)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// valid
|
||||||
|
err = app.DeleteKey(testName, testPassword)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
out, err = app.GetKeys()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var outputs2 []ckeys.KeyOutput
|
||||||
|
err = json.Unmarshal(out, &outputs2)
|
||||||
|
require.Equal(t, 0, len(outputs2))
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestUpdateKey(t *testing.T) {
|
||||||
|
app := setup(t)
|
||||||
|
defer os.RemoveAll(app.KeyDir)
|
||||||
|
|
||||||
|
out, err := app.AddNewKey(testName, testPassword, testMnemonic, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
out, err = app.GetKeys()
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
var outputs []ckeys.KeyOutput
|
||||||
|
err = json.Unmarshal(out, &outputs)
|
||||||
|
|
||||||
|
// not exist name
|
||||||
|
err = app.UpdateKey(testInvalidName, testPassword, testUpdatePassword)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// invalid password
|
||||||
|
err = app.UpdateKey(testName, testInvalidPassword, testUpdatePassword)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// valid
|
||||||
|
err = app.UpdateKey(testName, testPassword, testUpdatePassword)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
// with old password
|
||||||
|
err = app.DeleteKey(testName, testPassword)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
// valid
|
||||||
|
err = app.DeleteKey(testName, testUpdatePassword)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
88
utils/rpc.go
88
utils/rpc.go
|
@ -2,50 +2,22 @@ package utils
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/cosmos/cosmos-sdk/codec"
|
"github.com/cosmos/cosmos-sdk/codec"
|
||||||
cmn "github.com/tendermint/tendermint/libs/common"
|
|
||||||
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
rpcclient "github.com/tendermint/tendermint/rpc/client"
|
||||||
|
|
||||||
sdk "github.com/cosmos/cosmos-sdk/types"
|
sdk "github.com/cosmos/cosmos-sdk/types"
|
||||||
"github.com/cosmos/cosmos-sdk/x/auth"
|
"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
|
// QueryAccount query account info
|
||||||
func (g Generator) QueryAccount(cdc *codec.Codec, accAddr sdk.AccAddress) (acc auth.Account, err error) {
|
func (app SantaApp) QueryAccount(cdc *codec.Codec, accAddr sdk.AccAddress) (acc auth.Account, err error) {
|
||||||
bz, err := cdc.MarshalJSON(auth.NewQueryAccountParams(accAddr))
|
bz, err := cdc.MarshalJSON(auth.NewQueryAccountParams(accAddr))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := rpcclient.NewHTTP(g.Node, "/websocket").ABCIQueryWithOptions(
|
result, err := rpcclient.NewHTTP(app.Node, "/websocket").ABCIQueryWithOptions(
|
||||||
"custom/acc/account",
|
"custom/acc/account",
|
||||||
bz,
|
bz,
|
||||||
rpcclient.ABCIQueryOptions{},
|
rpcclient.ABCIQueryOptions{},
|
||||||
|
@ -67,66 +39,14 @@ func (g Generator) QueryAccount(cdc *codec.Codec, accAddr sdk.AccAddress) (acc a
|
||||||
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
|
// BroadcastTx broadcast tx
|
||||||
func (g Generator) BroadcastTx(tx auth.StdTx) (txHash string, err error) {
|
func (app SantaApp) BroadcastTx(tx auth.StdTx) (txHash string, err error) {
|
||||||
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
|
txBytes, err := cdc.MarshalBinaryLengthPrefixed(tx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
result, err := rpcclient.NewHTTP(g.Node, "/websocket").BroadcastTxSync(txBytes)
|
result, err := rpcclient.NewHTTP(app.Node, "/websocket").BroadcastTxSync(txBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,110 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
|
||||||
|
)
|
||||||
|
const (
|
||||||
|
testChainID = "vodka"
|
||||||
|
|
||||||
|
testInvalidName = ""
|
||||||
|
testName = "keyname"
|
||||||
|
testName2 = "keyname2"
|
||||||
|
testName3= "keyname3"
|
||||||
|
|
||||||
|
testInvalidPassword = ""
|
||||||
|
testPassword = "12345678"
|
||||||
|
testPassword2 = "12345678910"
|
||||||
|
testPassword3 = "1234567891011"
|
||||||
|
testUpdatePassword = "123456789"
|
||||||
|
|
||||||
|
testInvalidMnemonic = "crop"
|
||||||
|
testMnemonic = "crop vivid nature drastic duck submit night innocent inflict when know divorce fan concert damp stand depart gauge area vanish legend clarify warfare discover"
|
||||||
|
|
||||||
|
// no balance in vodka network
|
||||||
|
testMnemonic2 = "baby reduce notice dice eight remember room avoid gravity patient cement unhappy consider exit beyond uncle oblige lamp fault open save rifle airport craft"
|
||||||
|
|
||||||
|
// not exists on vodka network
|
||||||
|
testMnemonic3 = "rally clarify museum turn slender one fruit october wedding wrong web spike slight domain double connect want flock sport powder gloom yard emerge album"
|
||||||
|
|
||||||
|
|
||||||
|
testNode = "http://15.164.0.235:26657" // vodka network
|
||||||
|
testFeeAmount = "1uluna"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
func setup(t *testing.T) SantaApp {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", ".santa")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
app := SantaApp{
|
||||||
|
KeyDir: dir,
|
||||||
|
}
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupWithPlentyBalanceAccount(t *testing.T) SantaApp {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", ".santa")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
app := SantaApp{
|
||||||
|
KeyDir: dir,
|
||||||
|
Node: testNode, // test vodka net
|
||||||
|
|
||||||
|
KeyName: testName,
|
||||||
|
KeyPassword: testPassword,
|
||||||
|
|
||||||
|
FeeAmount: testFeeAmount,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = app.AddNewKey(testName, testPassword, testMnemonic, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
func setupWithNoBalanceAccount(t *testing.T) SantaApp {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", ".santa")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
app := SantaApp{
|
||||||
|
KeyDir: dir,
|
||||||
|
Node: testNode, // test vodka net
|
||||||
|
|
||||||
|
KeyName: testName2,
|
||||||
|
KeyPassword: testPassword2,
|
||||||
|
|
||||||
|
FeeAmount: testFeeAmount,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = app.AddNewKey(testName2, testPassword2, testMnemonic2, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
func setupWithNotExistsAccount(t *testing.T) SantaApp {
|
||||||
|
dir, err := ioutil.TempDir("/tmp", ".santa")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
app := SantaApp{
|
||||||
|
KeyDir: dir,
|
||||||
|
Node: testNode, // test vodka net
|
||||||
|
|
||||||
|
KeyName: testName3,
|
||||||
|
KeyPassword: testPassword3,
|
||||||
|
|
||||||
|
FeeAmount: testFeeAmount,
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = app.AddNewKey(testName3, testPassword3, testMnemonic3, false)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
return app
|
||||||
|
}
|
|
@ -21,21 +21,20 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenNewBlock listen new block and trigger sendtx
|
// ListenNewBlock listen new block and trigger sendtx
|
||||||
func (g Generator) ListenNewBLock() {
|
func (app SantaApp) ListenNewBLock(isTest bool) {
|
||||||
|
triggerInterval, err := strconv.ParseInt(app.TriggerInterval, 10, 64)
|
||||||
triggerInterval, err := strconv.ParseInt(g.TriggerInterval, 10, 64)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Trigger interval should be number", err)
|
log.Fatal("Trigger interval should be number", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var scheme string
|
var scheme string
|
||||||
var host string
|
var host string
|
||||||
if strings.HasPrefix(g.Node, "https") {
|
if strings.HasPrefix(app.Node, "https") {
|
||||||
scheme = "wss"
|
scheme = "wss"
|
||||||
host = strings.TrimPrefix(g.Node, "https://")
|
host = strings.TrimPrefix(app.Node, "https://")
|
||||||
} else {
|
} else {
|
||||||
scheme = "ws"
|
scheme = "ws"
|
||||||
host = strings.TrimPrefix(g.Node, "http://")
|
host = strings.TrimPrefix(app.Node, "http://")
|
||||||
}
|
}
|
||||||
|
|
||||||
u := url.URL{Scheme: scheme, Host: host, Path: "/websocket"}
|
u := url.URL{Scheme: scheme, Host: host, Path: "/websocket"}
|
||||||
|
@ -76,14 +75,18 @@ func (g Generator) ListenNewBLock() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if blockEvent.Block.Height%triggerInterval == 0 {
|
if blockEvent.Block.Height%triggerInterval == 0 {
|
||||||
err := g.SendTx(blockEvent.Block.Height, blockEvent.Block.ChainID)
|
txHash, err := app.SendTx(blockEvent.Block.ChainID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Failed to send tx", err)
|
log.Fatal("[Fail] to send tx", err)
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Printf("[Success] Height: %d,\tTxHash: %s\n", blockEvent.Block.Height, txHash)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if isTest {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// no-lint
|
// no-lint
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"bytes"
|
||||||
|
"log"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"testing"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
func TestWebsocketListen(t *testing.T) {
|
||||||
|
app := setupWithPlentyBalanceAccount(t)
|
||||||
|
|
||||||
|
var logBuf bytes.Buffer
|
||||||
|
log.SetOutput(&logBuf)
|
||||||
|
defer log.SetOutput(os.Stderr)
|
||||||
|
|
||||||
|
app.TriggerInterval = "1"
|
||||||
|
app.ListenNewBLock(true)
|
||||||
|
|
||||||
|
result := logBuf.String()
|
||||||
|
require.True(t, strings.Contains(result, "[Success]"))
|
||||||
|
}
|
Loading…
Reference in New Issue