WebSocket interface
Web sockets handlers fully implemented. Filter handlers have yet to be implemented.
This commit is contained in:
parent
41ae6f298e
commit
6db40ecb22
@ -10,36 +10,41 @@ import (
|
|||||||
"github.com/ethereum/eth-go/ethlog"
|
"github.com/ethereum/eth-go/ethlog"
|
||||||
)
|
)
|
||||||
|
|
||||||
var Identifier string
|
var (
|
||||||
var KeyRing string
|
Identifier string
|
||||||
var DiffTool bool
|
KeyRing string
|
||||||
var DiffType string
|
DiffTool bool
|
||||||
var KeyStore string
|
DiffType string
|
||||||
var StartRpc bool
|
KeyStore string
|
||||||
var RpcPort int
|
StartRpc bool
|
||||||
var UseUPnP bool
|
StartWebSockets bool
|
||||||
var OutboundPort string
|
RpcPort int
|
||||||
var ShowGenesis bool
|
UseUPnP bool
|
||||||
var AddPeer string
|
OutboundPort string
|
||||||
var MaxPeer int
|
ShowGenesis bool
|
||||||
var GenAddr bool
|
AddPeer string
|
||||||
var UseSeed bool
|
MaxPeer int
|
||||||
var SecretFile string
|
GenAddr bool
|
||||||
var ExportDir string
|
UseSeed bool
|
||||||
var NonInteractive bool
|
SecretFile string
|
||||||
var Datadir string
|
ExportDir string
|
||||||
var LogFile string
|
NonInteractive bool
|
||||||
var ConfigFile string
|
Datadir string
|
||||||
var DebugFile string
|
LogFile string
|
||||||
var LogLevel int
|
ConfigFile string
|
||||||
var Dump bool
|
DebugFile string
|
||||||
var DumpHash string
|
LogLevel int
|
||||||
var DumpNumber int
|
Dump bool
|
||||||
|
DumpHash string
|
||||||
|
DumpNumber int
|
||||||
|
)
|
||||||
|
|
||||||
// flags specific to cli client
|
// flags specific to cli client
|
||||||
var StartMining bool
|
var (
|
||||||
var StartJsConsole bool
|
StartMining bool
|
||||||
var InputFile string
|
StartJsConsole bool
|
||||||
|
InputFile string
|
||||||
|
)
|
||||||
|
|
||||||
func defaultDataDir() string {
|
func defaultDataDir() string {
|
||||||
usr, _ := user.Current()
|
usr, _ := user.Current()
|
||||||
@ -62,6 +67,7 @@ func Init() {
|
|||||||
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
|
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
|
||||||
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
|
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
|
||||||
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
|
flag.BoolVar(&StartRpc, "rpc", false, "start rpc server")
|
||||||
|
flag.BoolVar(&StartWebSockets, "ws", false, "start websocket server")
|
||||||
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
|
flag.BoolVar(&NonInteractive, "y", false, "non-interactive mode (say yes to confirmations)")
|
||||||
flag.BoolVar(&UseSeed, "seed", true, "seed peers")
|
flag.BoolVar(&UseSeed, "seed", true, "seed peers")
|
||||||
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
|
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
|
||||||
|
@ -103,6 +103,10 @@ func main() {
|
|||||||
utils.StartRpc(ethereum, RpcPort)
|
utils.StartRpc(ethereum, RpcPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if StartWebSockets {
|
||||||
|
utils.StartWebSockets(ethereum)
|
||||||
|
}
|
||||||
|
|
||||||
utils.StartEthereum(ethereum, UseSeed)
|
utils.StartEthereum(ethereum, UseSeed)
|
||||||
|
|
||||||
// this blocks the thread
|
// this blocks the thread
|
||||||
|
@ -1,9 +1,8 @@
|
|||||||
// The magic return variable. The magic return variable will be set during the execution of the QML call.
|
// The magic return variable. The magic return variable will be set during the execution of the QML call.
|
||||||
(function(window) {
|
(function(window) {
|
||||||
function message(type, data) {
|
var Promise = window.Promise;
|
||||||
document.title = JSON.stringify({type: type, data: data});
|
if(typeof(Promise) === "undefined") {
|
||||||
|
var Promise = Q.Promise;
|
||||||
return window.____returnData;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function isPromise(o) {
|
function isPromise(o) {
|
||||||
@ -446,6 +445,7 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
var g_seed = 1;
|
var g_seed = 1;
|
||||||
function postData(data, cb) {
|
function postData(data, cb) {
|
||||||
data._seed = g_seed;
|
data._seed = g_seed;
|
||||||
@ -459,24 +459,6 @@
|
|||||||
|
|
||||||
g_seed++;
|
g_seed++;
|
||||||
|
|
||||||
navigator.qt.postMessage(JSON.stringify(data));
|
window._messagingAdapter.call(this, JSON.stringify(data))
|
||||||
}
|
|
||||||
|
|
||||||
navigator.qt.onmessage = function(ev) {
|
|
||||||
var data = JSON.parse(ev.data)
|
|
||||||
|
|
||||||
if(data._event !== undefined) {
|
|
||||||
eth.trigger(data._event, data.data);
|
|
||||||
} else {
|
|
||||||
if(data._seed) {
|
|
||||||
var cb = eth._callbacks[data._seed];
|
|
||||||
if(cb) {
|
|
||||||
cb.call(this, data.data)
|
|
||||||
|
|
||||||
// Remove the "trigger" callback
|
|
||||||
delete eth._callbacks[ev._seed];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})(this);
|
})(this);
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
if(typeof(Promise) === "undefined") {
|
|
||||||
window.Promise = Q.Promise;
|
|
||||||
}
|
|
21
mist/assets/ext/qt_messaging_adapter.js
Normal file
21
mist/assets/ext/qt_messaging_adapter.js
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
window._messagingAdapter = function(data) {
|
||||||
|
navigator.qt.postMessage(data);
|
||||||
|
};
|
||||||
|
|
||||||
|
navigator.qt.onmessage = function(ev) {
|
||||||
|
var data = JSON.parse(ev.data)
|
||||||
|
|
||||||
|
if(data._event !== undefined) {
|
||||||
|
eth.trigger(data._event, data.data);
|
||||||
|
} else {
|
||||||
|
if(data._seed) {
|
||||||
|
var cb = eth._callbacks[data._seed];
|
||||||
|
if(cb) {
|
||||||
|
cb.call(this, data.data)
|
||||||
|
|
||||||
|
// Remove the "trigger" callback
|
||||||
|
delete eth._callbacks[ev._seed];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -164,7 +164,7 @@ import "../ext/qml_messaging.js" as Messaging
|
|||||||
experimental.preferences.javascriptEnabled: true
|
experimental.preferences.javascriptEnabled: true
|
||||||
experimental.preferences.navigatorQtObjectEnabled: true
|
experimental.preferences.navigatorQtObjectEnabled: true
|
||||||
experimental.preferences.developerExtrasEnabled: true
|
experimental.preferences.developerExtrasEnabled: true
|
||||||
experimental.userScripts: ["../ext/q.js", "../ext/pre.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"]
|
experimental.userScripts: ["../ext/qt_messaging_adapter.js", "../ext/q.js", "../ext/big.js", "../ext/string.js", "../ext/html_messaging.js"]
|
||||||
experimental.onMessageReceived: {
|
experimental.onMessageReceived: {
|
||||||
console.log("[onMessageReceived]: ", message.data)
|
console.log("[onMessageReceived]: ", message.data)
|
||||||
// TODO move to messaging.js
|
// TODO move to messaging.js
|
||||||
|
161
utils/websockets.go
Normal file
161
utils/websockets.go
Normal file
@ -0,0 +1,161 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/ethereum/eth-go"
|
||||||
|
"github.com/ethereum/eth-go/ethpipe"
|
||||||
|
"github.com/ethereum/eth-go/ethutil"
|
||||||
|
"github.com/ethereum/eth-go/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
func args(v ...interface{}) []interface{} {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
type WebSocketServer struct {
|
||||||
|
ethereum *eth.Ethereum
|
||||||
|
filterCallbacks map[int][]int
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewWebSocketServer(eth *eth.Ethereum) *WebSocketServer {
|
||||||
|
return &WebSocketServer{eth, make(map[int][]int)}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (self *WebSocketServer) Serv() {
|
||||||
|
pipe := ethpipe.NewJSPipe(self.ethereum)
|
||||||
|
|
||||||
|
wsServ := websocket.NewServer("/eth", ":40404")
|
||||||
|
wsServ.MessageFunc(func(c *websocket.Client, msg *websocket.Message) {
|
||||||
|
switch msg.Call {
|
||||||
|
case "compile":
|
||||||
|
data := ethutil.NewValue(msg.Args)
|
||||||
|
bcode, err := ethutil.Compile(data.Get(0).Str(), false)
|
||||||
|
if err != nil {
|
||||||
|
c.Write(args(nil, err.Error()), msg.Seed)
|
||||||
|
}
|
||||||
|
|
||||||
|
code := ethutil.Bytes2Hex(bcode)
|
||||||
|
c.Write(args(code, nil), msg.Seed)
|
||||||
|
case "getBlockByNumber":
|
||||||
|
args := msg.Arguments()
|
||||||
|
|
||||||
|
block := pipe.BlockByNumber(int32(args.Get(0).Uint()))
|
||||||
|
c.Write(block, msg.Seed)
|
||||||
|
|
||||||
|
case "getKey":
|
||||||
|
c.Write(pipe.Key().PrivateKey, msg.Seed)
|
||||||
|
case "transact":
|
||||||
|
if mp, ok := msg.Args[0].(map[string]interface{}); ok {
|
||||||
|
object := mapToTxParams(mp)
|
||||||
|
c.Write(
|
||||||
|
args(pipe.Transact(object["from"], object["to"], object["value"], object["gas"], object["gasPrice"], object["data"])),
|
||||||
|
msg.Seed,
|
||||||
|
)
|
||||||
|
|
||||||
|
}
|
||||||
|
case "getCoinBase":
|
||||||
|
c.Write(pipe.CoinBase(), msg.Seed)
|
||||||
|
|
||||||
|
case "getIsListening":
|
||||||
|
c.Write(pipe.IsListening(), msg.Seed)
|
||||||
|
|
||||||
|
case "getIsMining":
|
||||||
|
c.Write(pipe.IsMining(), msg.Seed)
|
||||||
|
|
||||||
|
case "getPeerCoint":
|
||||||
|
c.Write(pipe.PeerCount(), msg.Seed)
|
||||||
|
|
||||||
|
case "getCountAt":
|
||||||
|
args := msg.Arguments()
|
||||||
|
|
||||||
|
c.Write(pipe.TxCountAt(args.Get(0).Str()), msg.Seed)
|
||||||
|
|
||||||
|
case "getCodeAt":
|
||||||
|
args := msg.Arguments()
|
||||||
|
|
||||||
|
c.Write(len(pipe.CodeAt(args.Get(0).Str())), msg.Seed)
|
||||||
|
|
||||||
|
case "getBlockByHash":
|
||||||
|
args := msg.Arguments()
|
||||||
|
|
||||||
|
c.Write(pipe.BlockByHash(args.Get(0).Str()), msg.Seed)
|
||||||
|
|
||||||
|
case "getStorageAt":
|
||||||
|
args := msg.Arguments()
|
||||||
|
|
||||||
|
c.Write(pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str()), msg.Seed)
|
||||||
|
|
||||||
|
case "getBalanceAt":
|
||||||
|
args := msg.Arguments()
|
||||||
|
|
||||||
|
c.Write(pipe.BalanceAt(args.Get(0).Str()), msg.Seed)
|
||||||
|
|
||||||
|
case "getSecretToAddress":
|
||||||
|
args := msg.Arguments()
|
||||||
|
|
||||||
|
c.Write(pipe.SecretToAddress(args.Get(0).Str()), msg.Seed)
|
||||||
|
|
||||||
|
case "newFilter":
|
||||||
|
case "newFilterString":
|
||||||
|
case "messages":
|
||||||
|
// TODO
|
||||||
|
}
|
||||||
|
|
||||||
|
})
|
||||||
|
|
||||||
|
wsServ.Listen()
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartWebSockets(eth *eth.Ethereum) {
|
||||||
|
sock := NewWebSocketServer(eth)
|
||||||
|
go sock.Serv()
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO This is starting to become a generic method. Move to utils
|
||||||
|
func mapToTxParams(object map[string]interface{}) map[string]string {
|
||||||
|
// Default values
|
||||||
|
if object["from"] == nil {
|
||||||
|
object["from"] = ""
|
||||||
|
}
|
||||||
|
if object["to"] == nil {
|
||||||
|
object["to"] = ""
|
||||||
|
}
|
||||||
|
if object["value"] == nil {
|
||||||
|
object["value"] = ""
|
||||||
|
}
|
||||||
|
if object["gas"] == nil {
|
||||||
|
object["gas"] = ""
|
||||||
|
}
|
||||||
|
if object["gasPrice"] == nil {
|
||||||
|
object["gasPrice"] = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
var dataStr string
|
||||||
|
var data []string
|
||||||
|
if str, ok := object["data"].(string); ok {
|
||||||
|
data = []string{str}
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, str := range data {
|
||||||
|
if ethutil.IsHex(str) {
|
||||||
|
str = str[2:]
|
||||||
|
|
||||||
|
if len(str) != 64 {
|
||||||
|
str = ethutil.LeftPadString(str, 64)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
str = ethutil.Bytes2Hex(ethutil.LeftPadBytes(ethutil.Big(str).Bytes(), 32))
|
||||||
|
}
|
||||||
|
|
||||||
|
dataStr += str
|
||||||
|
}
|
||||||
|
object["data"] = dataStr
|
||||||
|
|
||||||
|
conv := make(map[string]string)
|
||||||
|
for key, value := range object {
|
||||||
|
if v, ok := value.(string); ok {
|
||||||
|
conv[key] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conv
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user