websockets.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186
  1. /*
  2. This file is part of go-ethereum
  3. go-ethereum is free software: you can redistribute it and/or modify
  4. it under the terms of the GNU General Public License as published by
  5. the Free Software Foundation, either version 3 of the License, or
  6. (at your option) any later version.
  7. go-ethereum is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. GNU General Public License for more details.
  11. You should have received a copy of the GNU General Public License
  12. along with go-ethereum. If not, see <http://www.gnu.org/licenses/>.
  13. */
  14. /**
  15. * @authors
  16. * Jeffrey Wilcke <i@jev.io>
  17. */
  18. package utils
  19. import (
  20. "github.com/ethereum/go-ethereum/eth"
  21. "github.com/ethereum/go-ethereum/ethutil"
  22. "github.com/ethereum/go-ethereum/logger"
  23. "github.com/ethereum/go-ethereum/websocket"
  24. "github.com/ethereum/go-ethereum/xeth"
  25. )
  26. var wslogger = logger.NewLogger("WS")
  27. func args(v ...interface{}) []interface{} {
  28. return v
  29. }
  30. type WebSocketServer struct {
  31. ethereum *eth.Ethereum
  32. filterCallbacks map[int][]int
  33. }
  34. func NewWebSocketServer(eth *eth.Ethereum) *WebSocketServer {
  35. return &WebSocketServer{eth, make(map[int][]int)}
  36. }
  37. func (self *WebSocketServer) Serv() {
  38. pipe := xeth.NewJSXEth(self.ethereum)
  39. wsServ := websocket.NewServer("/eth", ":40404")
  40. wsServ.MessageFunc(func(c *websocket.Client, msg *websocket.Message) {
  41. switch msg.Call {
  42. case "compile":
  43. data := ethutil.NewValue(msg.Args)
  44. bcode, err := ethutil.Compile(data.Get(0).Str(), false)
  45. if err != nil {
  46. c.Write(args(nil, err.Error()), msg.Id)
  47. }
  48. code := ethutil.Bytes2Hex(bcode)
  49. c.Write(args(code, nil), msg.Id)
  50. case "eth_blockByNumber":
  51. args := msg.Arguments()
  52. block := pipe.BlockByNumber(int32(args.Get(0).Uint()))
  53. c.Write(block, msg.Id)
  54. case "eth_blockByHash":
  55. args := msg.Arguments()
  56. c.Write(pipe.BlockByHash(args.Get(0).Str()), msg.Id)
  57. case "eth_transact":
  58. if mp, ok := msg.Args[0].(map[string]interface{}); ok {
  59. object := mapToTxParams(mp)
  60. c.Write(
  61. args(pipe.Transact(pipe.Key().PrivateKey, object["to"], object["value"], object["gas"], object["gasPrice"], object["data"])),
  62. msg.Id,
  63. )
  64. }
  65. case "eth_gasPrice":
  66. c.Write("10000000000000", msg.Id)
  67. case "eth_coinbase":
  68. c.Write(pipe.CoinBase(), msg.Id)
  69. case "eth_listening":
  70. c.Write(pipe.IsListening(), msg.Id)
  71. case "eth_mining":
  72. c.Write(pipe.IsMining(), msg.Id)
  73. case "eth_peerCount":
  74. c.Write(pipe.PeerCount(), msg.Id)
  75. case "eth_countAt":
  76. args := msg.Arguments()
  77. c.Write(pipe.TxCountAt(args.Get(0).Str()), msg.Id)
  78. case "eth_codeAt":
  79. args := msg.Arguments()
  80. c.Write(len(pipe.CodeAt(args.Get(0).Str())), msg.Id)
  81. case "eth_storageAt":
  82. args := msg.Arguments()
  83. c.Write(pipe.StorageAt(args.Get(0).Str(), args.Get(1).Str()), msg.Id)
  84. case "eth_balanceAt":
  85. args := msg.Arguments()
  86. c.Write(pipe.BalanceAt(args.Get(0).Str()), msg.Id)
  87. case "eth_secretToAddress":
  88. args := msg.Arguments()
  89. c.Write(pipe.SecretToAddress(args.Get(0).Str()), msg.Id)
  90. case "eth_newFilter":
  91. case "eth_newFilterString":
  92. case "eth_messages":
  93. // TODO
  94. }
  95. })
  96. wsServ.Listen()
  97. }
  98. func StartWebSockets(eth *eth.Ethereum) {
  99. wslogger.Infoln("Starting WebSockets")
  100. sock := NewWebSocketServer(eth)
  101. go sock.Serv()
  102. }
  103. // TODO This is starting to become a generic method. Move to utils
  104. func mapToTxParams(object map[string]interface{}) map[string]string {
  105. // Default values
  106. if object["from"] == nil {
  107. object["from"] = ""
  108. }
  109. if object["to"] == nil {
  110. object["to"] = ""
  111. }
  112. if object["value"] == nil {
  113. object["value"] = ""
  114. }
  115. if object["gas"] == nil {
  116. object["gas"] = ""
  117. }
  118. if object["gasPrice"] == nil {
  119. object["gasPrice"] = ""
  120. }
  121. var dataStr string
  122. var data []string
  123. if str, ok := object["data"].(string); ok {
  124. data = []string{str}
  125. }
  126. for _, str := range data {
  127. if ethutil.IsHex(str) {
  128. str = str[2:]
  129. if len(str) != 64 {
  130. str = ethutil.LeftPadString(str, 64)
  131. }
  132. } else {
  133. str = ethutil.Bytes2Hex(ethutil.LeftPadBytes(ethutil.Big(str).Bytes(), 32))
  134. }
  135. dataStr += str
  136. }
  137. object["data"] = dataStr
  138. conv := make(map[string]string)
  139. for key, value := range object {
  140. if v, ok := value.(string); ok {
  141. conv[key] = v
  142. }
  143. }
  144. return conv
  145. }