client/rest, cmd/baseserver: started a basecoin REST client

```shell
$ go get -u -v github.com/tendermint/basecoin/cmd/baseserver
$ baseserver init
$ baseserver serve
```
A server that can be ran by default on port 8998
otherwise one can specify the port using flag `--port` like this:
```shell
$ baseserver serve --port 9999
```
to serve it on port 9999, accessible at http://localhost:9999

Implemented:
- [X] /keys POST -- generate a new key
- [X] /keys GET  -- list all keys
- [X] /keys/{name}  DELETE-- delete a named key
- [X] /keys/{name}  GET -- get a named key
- [X] /keys/{name}  POST, PUT -- update a named key
- [X] /sign POST -- sign a transaction
- [X] /build/send POST -- send money from one actor to another. However,
  still needs testing and verification of output
- [X] /tx POST -- post a transaction to the blockchain. However, still
  needs testing and verification of output

This base code to get the handlers starters was adapted from:
* https://github.com/tendermint/go-crypto/blob/master/keys/server
* https://github.com/tendermint/basecoin/blob/unstable/client/commands/proxy/root.go

Updates #186
This commit is contained in:
Emmanuel Odeke
2017-07-29 04:12:24 -06:00
parent eae1883f3d
commit d4ab79ece0
6 changed files with 590 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
# baseserver
baseserver is the REST counterpart to basecli
## Compiling and running it
```shell
$ go get -u -v github.com/tendermint/basecoin/cmd/baseserver
$ baseserver init
$ baseserver serve --port 8888
```
to run the server at localhost:8888, otherwise if you don't specify --port,
by default the server will be run on port 8998.
## Supported routes
Route | Method | Completed | Description
---|---|---|---
/keys|GET|✔️|Lists all keys
/keys|POST|✔️|Generate a new key. It expects fields: "name", "algo", "passphrase"
/keys/{name}|GET|✔️|Retrieves the specific key
/keys/{name}|POST/PUT|✔️|Updates the named key
/keys/{name}|DELETE|✔️|Deletes the named key
/build/send|POST|✔️|Send a transaction
/sign|POST|✔️|Sign a transaction
/tx|POST|✖️|Post a transaction to the blockchain
/seeds/status|GET|✖️|Returns the information on the last seed
## Sample usage
- Generate a key
```shell
$ curl -X POST http://localhost8998/keys --data '{"algo": "ed25519", "name": "SampleX", "passphrase": "Say no more"}'
```
```json
{
"key": {
"name": "SampleX",
"address": "603EE63C41E322FC7A247864A9CD0181282EB458",
"pubkey": {
"type": "ed25519",
"data": "C050948CFC087F5E1068C7E244DDC30E03702621CC9442A28E6C9EDA7771AA0C"
}
},
"seed_phrase": "border almost future parade speak soccer bulk orange real brisk caution body river chapter"
}
```
- Sign a key
```shell
$ curl -X POST http://localhost:8998/sign --data '{
"name": "matt",
"password": "Say no more",
"tx": {
"type": "sigs/multi",
"data": {
"tx": {"type":"coin/send","data":{"inputs":[{"address":{"chain":"","app":"role","addr":"62616E6B32"},"coins":[{"denom":"mycoin","amount":900000}]}],"outputs":[{"address":{"chain":"","app":"sigs","addr":"BDADF167E6CF2CDF2D621E590FF1FED2787A40E0"},"coins":[{"denom":"mycoin","amount":900000}]}]}},
"signatures": null
}
}
}'
```
```json
{
"type": "sigs/multi",
"data": {
"tx": {
"type": "coin/send",
"data": {
"inputs": [
{
"address": {
"chain": "",
"app": "role",
"addr": "62616E6B32"
},
"coins": [
{
"denom": "mycoin",
"amount": 900000
}
]
}
],
"outputs": [
{
"address": {
"chain": "",
"app": "sigs",
"addr": "BDADF167E6CF2CDF2D621E590FF1FED2787A40E0"
},
"coins": [
{
"denom": "mycoin",
"amount": 900000
}
]
}
]
}
},
"signatures": [
{
"Sig": {
"type": "ed25519",
"data": "F6FE3053F1E6C236F886A0D525C1AF840F7831B6E50F7E1108C345AA524303920F09945DA110AD5184B3F45717D7114E368B12AFE027FECECC2FC193D4906A0C"
},
"Pubkey": {
"type": "ed25519",
"data": "0D8D19E527BAE9D1256A3D03009E2708171CDCB71CCDEDA2DC52DD9AD23AEE25"
}
}
]
}
}
```
+66
View File
@@ -0,0 +1,66 @@
package main
import (
"fmt"
"log"
"net/http"
"os"
"github.com/gorilla/mux"
"github.com/spf13/cobra"
"github.com/tendermint/basecoin/client/commands"
rest "github.com/tendermint/basecoin/client/rest"
"github.com/tendermint/tmlibs/cli"
)
var srvCli = &cobra.Command{
Use: "baseserver",
Short: "Light REST client for tendermint",
Long: `Baseserver presents a nice (not raw hex) interface to the basecoin blockchain structure.`,
}
var serveCmd = &cobra.Command{
Use: "serve",
Short: "Serve the light REST client for tendermint",
Long: "Access basecoin via REST",
RunE: serve,
}
var port int
func main() {
commands.AddBasicFlags(srvCli)
flagset := serveCmd.Flags()
flagset.IntVar(&port, "port", 8998, "the port to run the server on")
srvCli.AddCommand(
commands.InitCmd,
serveCmd,
)
// TODO: Decide whether to use $HOME/.basecli for compatibility
// or just use $HOME/.baseserver?
cmd := cli.PrepareMainCmd(srvCli, "BC", os.ExpandEnv("$HOME/.basecli"))
if err := cmd.Execute(); err != nil {
log.Fatal(err)
}
}
const defaultAlgo = "ed25519"
func serve(cmd *cobra.Command, args []string) error {
keysManager := rest.DefaultKeysManager()
router := mux.NewRouter()
ctx := rest.Context{
Keys: rest.New(keysManager, defaultAlgo),
}
if err := ctx.RegisterHandlers(router); err != nil {
return err
}
addr := fmt.Sprintf(":%d", port)
log.Printf("Serving on %q", addr)
return http.ListenAndServe(addr, router)
}