mirror of https://github.com/status-im/op-geth.git
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"
|
||||
)
|
||||
|
||||
var Identifier string
|
||||
var KeyRing string
|
||||
var DiffTool bool
|
||||
var DiffType string
|
||||
var KeyStore string
|
||||
var StartRpc bool
|
||||
var RpcPort int
|
||||
var UseUPnP bool
|
||||
var OutboundPort string
|
||||
var ShowGenesis bool
|
||||
var AddPeer string
|
||||
var MaxPeer int
|
||||
var GenAddr bool
|
||||
var UseSeed bool
|
||||
var SecretFile string
|
||||
var ExportDir string
|
||||
var NonInteractive bool
|
||||
var Datadir string
|
||||
var LogFile string
|
||||
var ConfigFile string
|
||||
var DebugFile string
|
||||
var LogLevel int
|
||||
var Dump bool
|
||||
var DumpHash string
|
||||
var DumpNumber int
|
||||
var (
|
||||
Identifier string
|
||||
KeyRing string
|
||||
DiffTool bool
|
||||
DiffType string
|
||||
KeyStore string
|
||||
StartRpc bool
|
||||
StartWebSockets bool
|
||||
RpcPort int
|
||||
UseUPnP bool
|
||||
OutboundPort string
|
||||
ShowGenesis bool
|
||||
AddPeer string
|
||||
MaxPeer int
|
||||
GenAddr bool
|
||||
UseSeed bool
|
||||
SecretFile string
|
||||
ExportDir string
|
||||
NonInteractive bool
|
||||
Datadir string
|
||||
LogFile string
|
||||
ConfigFile string
|
||||
DebugFile string
|
||||
LogLevel int
|
||||
Dump bool
|
||||
DumpHash string
|
||||
DumpNumber int
|
||||
)
|
||||
|
||||
// flags specific to cli client
|
||||
var StartMining bool
|
||||
var StartJsConsole bool
|
||||
var InputFile string
|
||||
var (
|
||||
StartMining bool
|
||||
StartJsConsole bool
|
||||
InputFile string
|
||||
)
|
||||
|
||||
func defaultDataDir() string {
|
||||
usr, _ := user.Current()
|
||||
|
@ -62,6 +67,7 @@ func Init() {
|
|||
flag.IntVar(&MaxPeer, "maxpeer", 10, "maximum desired peers")
|
||||
flag.IntVar(&RpcPort, "rpcport", 8080, "port to start json-rpc server on")
|
||||
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(&UseSeed, "seed", true, "seed peers")
|
||||
flag.BoolVar(&GenAddr, "genaddr", false, "create a new priv/pub key")
|
||||
|
|
|
@ -103,6 +103,10 @@ func main() {
|
|||
utils.StartRpc(ethereum, RpcPort)
|
||||
}
|
||||
|
||||
if StartWebSockets {
|
||||
utils.StartWebSockets(ethereum)
|
||||
}
|
||||
|
||||
utils.StartEthereum(ethereum, UseSeed)
|
||||
|
||||
// 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.
|
||||
(function(window) {
|
||||
function message(type, data) {
|
||||
document.title = JSON.stringify({type: type, data: data});
|
||||
|
||||
return window.____returnData;
|
||||
var Promise = window.Promise;
|
||||
if(typeof(Promise) === "undefined") {
|
||||
var Promise = Q.Promise;
|
||||
}
|
||||
|
||||
function isPromise(o) {
|
||||
|
@ -446,6 +445,7 @@
|
|||
}
|
||||
});
|
||||
|
||||
|
||||
var g_seed = 1;
|
||||
function postData(data, cb) {
|
||||
data._seed = g_seed;
|
||||
|
@ -459,24 +459,6 @@
|
|||
|
||||
g_seed++;
|
||||
|
||||
navigator.qt.postMessage(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];
|
||||
}
|
||||
}
|
||||
}
|
||||
window._messagingAdapter.call(this, JSON.stringify(data))
|
||||
}
|
||||
})(this);
|
||||
|
|
|
@ -1,3 +0,0 @@
|
|||
if(typeof(Promise) === "undefined") {
|
||||
window.Promise = Q.Promise;
|
||||
}
|
|
@ -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.navigatorQtObjectEnabled: 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: {
|
||||
console.log("[onMessageReceived]: ", message.data)
|
||||
// TODO move to messaging.js
|
||||
|
|
|
@ -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