diff --git a/README.md b/README.md index bc2393aca..c14319c5d 100644 --- a/README.md +++ b/README.md @@ -13,23 +13,55 @@ _NOTE: This is alpha software. Please contact us if you intend to run it in prod You'll need [docker](https://docker.com/) and [docker compose](https://docs.docker.com/compose/) installed. Clone Minter to your machine -``` -git clone https://github.com/MinterTeam/minter-go-node.git -cd minter +```bash +$ git clone https://github.com/MinterTeam/minter-go-node.git +$ cd minter-go-node ``` Prepare configs -``` -mkdir -p ~/.tendermint/data -mkdir -p ~/.minter/data +```bash +$ mkdir -p ~/.tendermint/data +$ mkdir -p ~/.minter/data -chmod -R 0777 ~/.tendermint -chmod -R 0777 ~/.minter +$ chmod -R 0777 ~/.tendermint +$ chmod -R 0777 ~/.minter -cp -R networks/testnet/ ~/.tendermint/config +$ cp -R networks/testnet/ ~/.tendermint/config ``` Start Minter +```bash +$ docker-compose up ``` -docker-compose up + +## Build and run manually + +Install [Tendermint 0.20](https://github.com/tendermint/tendermint/blob/master/docs/install.rst) + +```bash +$ mkdir $GOPATH/src/github.com/MinterTeam +$ cd $GOPATH/src/github.com/MinterTeam +$ git clone https://github.com/MinterTeam/minter-go-node.git + +$ cd minter-go-node +$ make get_tools +$ make get_vendor_deps + +$ make install + +$ mkdir -p ~/.tendermint/data +$ mkdir -p ~/.minter/data + +$ cp -R networks/testnet/ ~/.tendermint/config +``` + +Run Tendermint +```bash +$ tendermint node ``` + +Run Minter + +```bash +$ minter +``` \ No newline at end of file diff --git a/api/api.go b/api/api.go index 4830082db..b8c4229fe 100644 --- a/api/api.go +++ b/api/api.go @@ -9,8 +9,10 @@ import ( "github.com/MinterTeam/minter-go-node/cmd/utils" "github.com/MinterTeam/minter-go-node/core/minter" + "github.com/MinterTeam/minter-go-node/core/state" "github.com/tendermint/tendermint/rpc/core/types" "github.com/tendermint/tendermint/rpc/lib/client" + "strconv" "time" ) @@ -68,3 +70,15 @@ type Response struct { Result interface{} `json:"result,omitempty"` Log string `json:"log,omitempty"` } + +func GetStateForRequest(r *http.Request) *state.StateDB { + height, _ := strconv.Atoi(r.URL.Query().Get("height")) + + cState := blockchain.CurrentState() + + if height > 0 { + cState, _ = blockchain.GetStateForHeight(height) + } + + return cState +} diff --git a/api/balance.go b/api/balance.go index ad55b3f1c..8bf56bf96 100644 --- a/api/balance.go +++ b/api/balance.go @@ -16,11 +16,13 @@ type BalanceRequest struct { func GetBalance(w http.ResponseWriter, r *http.Request) { + cState := GetStateForRequest(r) + vars := mux.Vars(r) address := types.HexToAddress(vars["address"]) balance := BalanceResponse{} - balances := blockchain.CurrentState().GetBalances(address) + balances := cState.GetBalances(address) for k, v := range balances.Data { balance[k.String()] = v.String() diff --git a/api/block.go b/api/block.go index 2dfaf5231..ec9f15741 100644 --- a/api/block.go +++ b/api/block.go @@ -18,13 +18,17 @@ func Block(w http.ResponseWriter, r *http.Request) { "height": height, }, result) + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + if err != nil { - panic(err) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(Response{ + Code: 0, + Result: err.Error(), + }) + return } - // TODO: check error - - w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) err = json.NewEncoder(w).Encode(Response{ diff --git a/api/candidate.go b/api/candidate.go index 3caa2d361..f1d31482e 100644 --- a/api/candidate.go +++ b/api/candidate.go @@ -7,7 +7,6 @@ import ( "github.com/MinterTeam/minter-go-node/core/types" "github.com/gorilla/mux" "net/http" - "strconv" "strings" ) @@ -16,13 +15,7 @@ func GetCandidate(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) pubkey := types.Hex2Bytes(strings.TrimLeft(vars["pubkey"], "Mx")) - height, _ := strconv.Atoi(r.URL.Query().Get("height")) - - cState := blockchain.CurrentState() - - if height > 0 { - cState, _ = blockchain.GetStateForHeight(height) - } + cState := GetStateForRequest(r) candidate := cState.GetStateCandidate(pubkey) diff --git a/api/coin_info.go b/api/coin_info.go index d3462ac7c..326dfa5a3 100644 --- a/api/coin_info.go +++ b/api/coin_info.go @@ -19,6 +19,8 @@ type CoinInfoResponse struct { func GetCoinInfo(w http.ResponseWriter, r *http.Request) { + cState := GetStateForRequest(r) + vars := mux.Vars(r) symbol := vars["symbol"] @@ -26,7 +28,7 @@ func GetCoinInfo(w http.ResponseWriter, r *http.Request) { copy(coinSymbol[:], []byte(symbol)) - coin := blockchain.CurrentState().GetStateCoin(coinSymbol).Data() + coin := cState.GetStateCoin(coinSymbol).Data() w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) diff --git a/api/estimate_coin_exchange_return.go b/api/estimate_coin_exchange_return.go index 3a3bf5d8f..5b9e7d192 100644 --- a/api/estimate_coin_exchange_return.go +++ b/api/estimate_coin_exchange_return.go @@ -10,6 +10,8 @@ import ( func EstimateCoinExchangeReturn(w http.ResponseWriter, r *http.Request) { + cState := GetStateForRequest(r) + query := r.URL.Query() fromCoin := query.Get("from_coin") toCoin := query.Get("to_coin") @@ -24,14 +26,14 @@ func EstimateCoinExchangeReturn(w http.ResponseWriter, r *http.Request) { var result *big.Int if fromCoinSymbol == blockchain.BaseCoin { - coin := blockchain.CurrentState().GetStateCoin(toCoinSymbol).Data() + coin := cState.GetStateCoin(toCoinSymbol).Data() result = formula.CalculatePurchaseReturn(coin.Volume, coin.ReserveBalance, coin.Crr, value) } else if toCoinSymbol == blockchain.BaseCoin { - coin := blockchain.CurrentState().GetStateCoin(fromCoinSymbol).Data() + coin := cState.GetStateCoin(fromCoinSymbol).Data() result = formula.CalculateSaleReturn(coin.Volume, coin.ReserveBalance, coin.Crr, value) } else { - coinFrom := blockchain.CurrentState().GetStateCoin(fromCoinSymbol).Data() - coinTo := blockchain.CurrentState().GetStateCoin(toCoinSymbol).Data() + coinFrom := cState.GetStateCoin(fromCoinSymbol).Data() + coinTo := cState.GetStateCoin(toCoinSymbol).Data() val := formula.CalculateSaleReturn(coinFrom.Volume, coinFrom.ReserveBalance, coinFrom.Crr, value) result = formula.CalculatePurchaseReturn(coinTo.Volume, coinTo.ReserveBalance, coinTo.Crr, val) diff --git a/api/transaction.go b/api/transaction.go index 230c41a78..1e1660f74 100644 --- a/api/transaction.go +++ b/api/transaction.go @@ -30,13 +30,17 @@ func Transaction(w http.ResponseWriter, r *http.Request) { "hash": decoded, }, result) + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + if err != nil { - panic(err) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(Response{ + Code: 0, + Result: err.Error(), + }) + return } - // TODO: check error - - w.Header().Set("Content-Type", "application/json; charset=UTF-8") w.WriteHeader(http.StatusOK) err = json.NewEncoder(w).Encode(Response{ diff --git a/api/transaction_count.go b/api/transaction_count.go index 549a0994b..33f67538e 100644 --- a/api/transaction_count.go +++ b/api/transaction_count.go @@ -11,6 +11,8 @@ type TransactionCountResponse uint64 func GetTransactionCount(w http.ResponseWriter, r *http.Request) { + cState := GetStateForRequest(r) + vars := mux.Vars(r) address := types.HexToAddress(vars["address"]) @@ -19,6 +21,6 @@ func GetTransactionCount(w http.ResponseWriter, r *http.Request) { json.NewEncoder(w).Encode(Response{ Code: 0, - Result: blockchain.CurrentState().GetNonce(address), + Result: cState.GetNonce(address), }) } diff --git a/api/transactions.go b/api/transactions.go index 5a9557b8e..412695217 100644 --- a/api/transactions.go +++ b/api/transactions.go @@ -58,11 +58,18 @@ func Transactions(w http.ResponseWriter, r *http.Request) { "per_page": 100, }, rpcResult) + w.Header().Set("Content-Type", "application/json; charset=UTF-8") + if err != nil { - panic(err) + w.WriteHeader(http.StatusBadRequest) + json.NewEncoder(w).Encode(Response{ + Code: 0, + Result: err.Error(), + }) + return } - // TODO: check error + w.WriteHeader(http.StatusOK) result := make([]TransactionResponse, len(rpcResult.Txs)) @@ -92,9 +99,6 @@ func Transactions(w http.ResponseWriter, r *http.Request) { } } - w.Header().Set("Content-Type", "application/json; charset=UTF-8") - w.WriteHeader(http.StatusOK) - err = json.NewEncoder(w).Encode(Response{ Code: 0, Result: result, diff --git a/core/transaction/transaction.go b/core/transaction/transaction.go index 893572f3c..36979897c 100644 --- a/core/transaction/transaction.go +++ b/core/transaction/transaction.go @@ -141,8 +141,16 @@ type DeclareCandidacyData struct { func (s DeclareCandidacyData) MarshalJSON() ([]byte, error) { return json.Marshal(struct { - // TODO: complete marshal function - }{}) + Address types.Address + PubKey string + Commission uint + Stake string + }{ + Address: s.Address, + PubKey: fmt.Sprintf("Mp%x", s.PubKey), + Commission: s.Commission, + Stake: s.Stake.String(), + }) } type DelegateData struct { @@ -152,8 +160,12 @@ type DelegateData struct { func (s DelegateData) MarshalJSON() ([]byte, error) { return json.Marshal(struct { - // TODO: complete marshal function - }{}) + PubKey string + Stake string + }{ + PubKey: fmt.Sprintf("Mp%x", s.PubKey), + Stake: s.Stake.String(), + }) } type RedeemCheckData struct { @@ -163,8 +175,12 @@ type RedeemCheckData struct { func (s RedeemCheckData) MarshalJSON() ([]byte, error) { return json.Marshal(struct { - // TODO: complete marshal function - }{}) + RawCheck string + Proof string + }{ + RawCheck: fmt.Sprintf("Mc%x", s.RawCheck), + Proof: fmt.Sprintf("%x", s.Proof), + }) } type UnbondData struct { @@ -174,8 +190,12 @@ type UnbondData struct { func (s UnbondData) MarshalJSON() ([]byte, error) { return json.Marshal(struct { - // TODO: complete marshal function - }{}) + PubKey string + Value string + }{ + PubKey: fmt.Sprintf("Mp%x", s.PubKey), + Value: s.Value.String(), + }) } func (tx *Transaction) Serialize() ([]byte, error) { diff --git a/docker-compose.yml b/docker-compose.yml index 6f867fc0b..b1d7bbdb9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -21,6 +21,7 @@ services: - ~/.tendermint:/tendermint ports: - "46656:46656" + - "46657:46657" restart: always healthcheck: test: ["CMD", "curl", "-f", "http://localhost:46657/health"]