aboutsummaryrefslogblamecommitdiffstats
path: root/utils/websockets.go
blob: e89331a98d6edac9a98efff24fbae9395f44c802 (plain) (tree)
































































































































































                                                                                                                                                              
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
}