diff --git a/client/client.go b/client/client.go index 1c9c3502a5dc46d661c654414c917257cc143e05..42082a6e7eebc47ce689d15574f77c28e45ad818 100644 --- a/client/client.go +++ b/client/client.go @@ -17,7 +17,9 @@ package client import ( + "encoding/json" "fmt" + "strings" "github.com/tendermint/go-rpc/client" @@ -31,6 +33,7 @@ import ( type NodeClient interface { Broadcast(transaction txs.Tx) (*txs.Receipt, error) + DeriveWebsocketClient() (nodeWsClient *NodeWebsocketClient, err error) Status() (ChainId []byte, ValidatorPublicKey []byte, LatestBlockHash []byte, LatestBlockHeight int, LatestBlockTime int64, err error) @@ -43,6 +46,14 @@ type NodeClient interface { ListValidators() (blockHeight int, bondedValidators, unbondingValidators []consensus_types.Validator, err error) } +type NodeWebsocketClient interface { + Subscribe(eventId string) error + Unsubscribe(eventId string) error + + Wait(eventId string) (chan Confirmation, error) + Close() +} + // NOTE [ben] Compiler check to ensure ErisNodeClient successfully implements // eris-db/client.NodeClient var _ NodeClient = (*ErisNodeClient)(nil) @@ -75,6 +86,34 @@ func (erisNodeClient *ErisNodeClient) Broadcast(tx txs.Tx) (*txs.Receipt, error) return &receipt, nil } +func (erisNodeClient *ErisNodeClient) DeriveWebsocketClient() (nodeWsClient *NodeWebSocketClient, err error) { + var wsAddr string + nodeAddr := erisNodeClient.broadcastRPC + if strings.HasPrefix(nodeAddr, "http://") { + wsAddr = strings.TrimPrefix(nodeAddr, "http://") + } + if strings.HasPrefix(nodeAddr, "tcp://") { + wsAddr = strings.TrimPrefix(nodeAddr, "tcp://") + } + if strings.HasPrefix(nodeAddr, "unix://") { + log.WithFields(log.Fields{ + "node address": nodeAddr, + }).Error("Unable to subscribe to websocket from unix socket.") + return nil, fmt.Errorf("Unable to construct websocket from unix socket: %s", nodeAddr) + } + wsAddr = "ws://" + wsAddr + log.WithFields(log.Fields{ + "websocket address": wsAddr, + "endpoint": "/websocket", + }).Debug("Subscribing to websocket address") + wsClient := rpcclient.NewWSClient(wsAddr, "/websocket") + // NOTE: Failure to start is reported over an error channel + wsClient.Start() + return &ErisNodeWebsocketClient{ + tendermintWebsocket: wsClient, + }, nil +} + //------------------------------------------------------------------------------------ // RPC requests other than transaction related diff --git a/client/core/transaction_factory.go b/client/core/transaction_factory.go index e631144c11bc36f70327b86488bd0ce66347564c..fef9dc97384322ae4c8afd1c47de8dc5666635d4 100644 --- a/client/core/transaction_factory.go +++ b/client/core/transaction_factory.go @@ -21,7 +21,7 @@ import ( "fmt" "strconv" // "strings" - // "time" + "time" log "github.com/eris-ltd/eris-logger" ptypes "github.com/eris-ltd/eris-db/permission/types" @@ -329,6 +329,7 @@ func SignAndBroadcast(chainID string, nodeClient client.NodeClient, keyClient ke } } } + time.Sleep(2*time.Second) return } diff --git a/client/core/transaction_factory_util.go b/client/core/transaction_factory_util.go index 01c2382618907eaaf8e7aa25903167ca0923d08b..c856fc1fc4d9665d3ae5d41052c94fa47bc7ff3d 100644 --- a/client/core/transaction_factory_util.go +++ b/client/core/transaction_factory_util.go @@ -123,7 +123,6 @@ func checkCommon(nodeClient client.NodeClient, keyClient keys.KeyClient, pubkey, err = fmt.Errorf("Failed to fetch pubkey for address (%s): %v", addr, err) return } - } if len(pubKeyBytes) == 0 { diff --git a/client/websocket_client.go b/client/websocket_client.go new file mode 100644 index 0000000000000000000000000000000000000000..f3b388514531e66ecd9df5ee78ec7065814ed9b3 --- /dev/null +++ b/client/websocket_client.go @@ -0,0 +1,73 @@ +// Copyright 2015, 2016 Eris Industries (UK) Ltd. +// This file is part of Eris-RT + +// Eris-RT is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Eris-RT is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// You should have received a copy of the GNU General Public License +// along with Eris-RT. If not, see <http://www.gnu.org/licenses/>. + +package client + +import ( + "encoding/json" + "fmt" + + "github.com/tendermint/go-rpc/client" + + "github.com/eris-ltd/eris-bd/txs" +) + +type Confirmation { + BlockHash []byte + Event *txs.EventData + Exception error +} + +// NOTE [ben] Compiler check to ensure ErisNodeClient successfully implements +// eris-db/client.NodeClient +var _ NodeWebsocketClient = (*ErisNodeWebsocketClient)(nil) + +type ErisNodeWebsocketClient struct { + // TODO: assert no memory leak on closing with open websocket + tendermintWebsocket *rpcclient.WSClient +} + +// Subscribe to an eventid +func (erisNodeWebsocketClient *ErisNodeWebsocketClient) Subscribe(eventid string) error { + return erisNodeWebsocketClient.tendermintWebsocket.Subscribe(eventid) +} + +// Unsubscribe from an eventid +func (erisNodeWebsocketClient *ErisNodeWebsocketClient) Unsubscribe(eventid string) error { + return erisNodeWebsocketClient.tendermintWebsocket.Unsubscribe(eventid) +} + +// Returns a channel with a sign +func (erisNodeWebsocketClient *ErisNodeWebsocketClient) Wait(eventid string) (chan Confirmation, error) { + // Setup the confirmation channel to be returned + confirmationChannel := make(chan Confirmation, 1) + var latestBlockHash []byte + +} + +func (erisNodeWebsocketClient *ErisNodeWebsocketClient) Close() { + if erisNodeWebsocketClient.tendermintWebsocket != nil { + erisNodeWebsocketClient.tendermintWebsocket.Stop() + } +} + +func (erisNodeWebsocketClient *ErisNodeWebsocketClient) assertNoErrors() error { + if erisNodeWebsocketClient.tendermintWebsocket != nil { + + } else { + return fmt.Errorf("") + } +} \ No newline at end of file diff --git a/client/ws_client.go b/client/ws_client.go index f2542c1a477eacb27d12f4e8f0f563c8e530b891..d60986b6f9a41575642dbf963aaceb281d52dfe5 100644 --- a/client/ws_client.go +++ b/client/ws_client.go @@ -1,6 +1,12 @@ // Websocket client implementation. This will be used in tests. package client +// NOTE: this websocket client acts on rpc/v0, +// uses github.com/gorilla/websocket +// and will be deprecated after 0.12 +// It is recommended to use the interfaces NodeClient +// and NodeWebsocketClient. + import ( "fmt" "net/http"