From aa8eb8f5f7114261aaa3bfe522074a69457f7c0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adri=C3=A0=20Cidre?= Date: Fri, 11 May 2018 07:55:55 +0200 Subject: [PATCH] support for go-ethereum/rpc --- account.go | 15 ++-- chan.go | 14 ++-- dictionary.go | 169 ++++++++-------------------------------- examples/pinger/main.go | 40 +++++++--- examples/ponger/main.go | 40 ++++++---- msg.go | 7 +- sdk.go | 29 +++---- 7 files changed, 119 insertions(+), 195 deletions(-) diff --git a/account.go b/account.go index 224f894..18fc7c6 100644 --- a/account.go +++ b/account.go @@ -25,13 +25,12 @@ func (a *Account) CreatePrivateChannel(name, password string) (*Channel, error) } func (a *Account) createAndJoin(name, password string) (*Channel, error) { - symkeyResponse, err := shhGenerateSymKeyFromPasswordRequest(a.conn, []string{password}) + symKey, err := shhGenerateSymKeyFromPasswordRequest(a.conn, password) if err != nil { return nil, err } - symKey := symkeyResponse.Key - topicID, err := a.calculatePublicChannelTopicID(name, symkeyResponse.ID) + topicID, err := a.calculatePublicChannelTopicID(name) if err != nil { return nil, err } @@ -41,13 +40,11 @@ func (a *Account) createAndJoin(name, password string) (*Channel, error) { // Join joins a status channel func (a *Account) Join(channelName, topicID, symKey string) (*Channel, error) { - newMessageFilterResponse, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, symKey) + filterID, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, symKey) if err != nil { return nil, err } - filterID := newMessageFilterResponse.FilterID - ch := &Channel{ account: a, name: channelName, @@ -60,13 +57,13 @@ func (a *Account) Join(channelName, topicID, symKey string) (*Channel, error) { return ch, nil } -func (a *Account) calculatePublicChannelTopicID(name string, symkey int) (topicID string, err error) { +func (a *Account) calculatePublicChannelTopicID(name string) (topicID string, err error) { p := "0x" + hex.EncodeToString([]byte(name)) - web3ShaResponse, err := web3Sha3Request(a.conn, symkey, []string{p}) + hash, err := web3Sha3Request(a.conn, p) if err != nil { return } - topicID = web3ShaResponse.Result[0:10] + topicID = hash[0:10] return } diff --git a/chan.go b/chan.go index 3311712..39e7505 100644 --- a/chan.go +++ b/chan.go @@ -83,10 +83,10 @@ func (c *Channel) Publish(body string) error { visibility = c.visibility } - now := time.Now().Unix() + now := time.Now().Unix() * 1000 format := `["%s",["%s","text/plain","%s",%d,%d]]` - msg := fmt.Sprintf(format, StandardMessageType, body, visibility, now*100, now*100) + msg := fmt.Sprintf(format, StandardMessageType, body, visibility, now*100, now) println("[ SENDING ] : " + msg) return c.SendPostRawMsg(msg) @@ -116,7 +116,7 @@ func (c *Channel) ContactUpdateRequest(username, image string) error { // SendPostRawMsg sends a shh_post message with the given body. func (c *Channel) SendPostRawMsg(body string) error { - param := shhPostParam{ + msg := Message{ Signature: c.account.Address, SymKeyID: c.ChannelKey, Payload: rawrChatMessage(body), @@ -126,7 +126,7 @@ func (c *Channel) SendPostRawMsg(body string) error { PowTime: 1, } - _, err := shhPostRequest(c.account.conn, []*shhPostParam{¶m}) + _, err := shhPostRequest(c.account.conn, &msg) if err != nil { log.Println(err.Error()) } @@ -183,13 +183,13 @@ func (c *Channel) PubKey() string { } func (c *Channel) pollMessages() (msg *Msg) { - res, err := shhGetFilterMessagesRequest(c.account.conn, []string{c.filterID}) + res, err := shhGetFilterMessagesRequest(c.account.conn, c.filterID) if err != nil { log.Fatalf("Error when sending request to server: %s", err) return } - switch vv := res.Result.(type) { + switch vv := res.(type) { case []interface{}: for _, u := range vv { msg, err = messageFromEnvelope(u) @@ -206,7 +206,7 @@ func (c *Channel) pollMessages() (msg *Msg) { return nil } default: - log.Println(res.Result, "is of a type I don't know how to handle") + log.Println(res, "is of a type I don't know how to handle") } return } diff --git a/dictionary.go b/dictionary.go index e045dfb..f7033cd 100644 --- a/dictionary.go +++ b/dictionary.go @@ -1,10 +1,5 @@ package sdk -import ( - "encoding/json" - "errors" -) - type shhRequest struct { ID int `json:"id"` JSONRPC string `json:"jsonrpc"` @@ -17,25 +12,10 @@ type generateSymKeyFromPasswordResponse struct { ID int `json:"id"` } -func shhGenerateSymKeyFromPasswordRequest(sdk *SDK, params []string) (res *generateSymKeyFromPasswordResponse, err error) { +func shhGenerateSymKeyFromPasswordRequest(sdk *SDK, password string) (string, error) { // `{"jsonrpc":"2.0","id":2950,"method":"shh_generateSymKeyFromPassword","params":["%s"]}` - req := shhRequest{ - ID: 2950, - JSONRPC: "2.0", - Method: "shh_generateSymKeyFromPassword", - } - for _, p := range params { - req.Params = append(req.Params, p) - } - - body, err := json.Marshal(req) - if err != nil { - return - } - - sdk.call(string(body), &res) - - return + var resp string + return resp, sdk.call("shh_generateSymKeyFromPassword", password, &resp) } type shhFilterFormatParam struct { @@ -49,53 +29,27 @@ type newMessageFilterResponse struct { FilterID string `json:"result"` } -func newShhMessageFilterFormatRequest(sdk *SDK, topics []string, symKey string) (res newMessageFilterResponse, err error) { +func newShhMessageFilterFormatRequest(sdk *SDK, topics []string, symKey string) (string, error) { // `{"jsonrpc":"2.0","id":2,"method":"shh_newMessageFilter","params":[{"allowP2P":true,"topics":["%s"],"type":"sym","symKeyID":"%s"}]}` - req := shhRequest{ - ID: 2, - JSONRPC: "2.0", - Method: "shh_newMessageFilter", - } - req.Params = append(req.Params, &shhFilterFormatParam{ + var res string + params := &shhFilterFormatParam{ AllowP2P: true, Topics: topics, Type: "sym", SymKeyID: symKey, - }) - - body, err := json.Marshal(req) - if err != nil { - return } - sdk.call(string(body), &res) - - return + return res, sdk.call("shh_newMessageFilter", params, &res) } type web3ShaResponse struct { Result string `json:"result"` } -func web3Sha3Request(sdk *SDK, id int, params []string) (res *web3ShaResponse, err error) { +func web3Sha3Request(sdk *SDK, data string) (string, error) { // `{"jsonrpc":"2.0","method":"web3_sha3","params":["%s"],"id":%d}` - req := shhRequest{ - ID: id, - JSONRPC: "2.0", - Method: "web3_sha3", - } - for _, p := range params { - req.Params = append(req.Params, p) - } - - body, err := json.Marshal(req) - if err != nil { - return - } - - sdk.call(string(body), &res) - - return + var res string + return res, sdk.call("web3_sha3", data, &res) } type statusLoginParam struct { @@ -104,31 +58,19 @@ type statusLoginParam struct { } type loginResponse struct { - Result struct { - AddressKeyID string `json:"address_key_id"` - } `json:"result"` + AddressKeyID string `json:"address_key_id"` } -func statusLoginRequest(sdk *SDK, address, password string) (res loginResponse, err error) { +func statusLoginRequest(sdk *SDK, address, password string) (*loginResponse, error) { // `{"jsonrpc":"2.0","method":"status_login","params":[{"address":"%s","password":"%s"}]}` - req := shhRequest{ - JSONRPC: "2.0", - Method: "status_login", - } + var res loginResponse - req.Params = append(req.Params, &statusLoginParam{ + params := &statusLoginParam{ Address: address, Password: password, - }) - - body, err := json.Marshal(req) - if err != nil { - return } - sdk.call(string(body), &res) - - return + return &res, sdk.call("status_login", params, &res) } type statusSignupParam struct { @@ -136,67 +78,41 @@ type statusSignupParam struct { } type signupResponse struct { - Result struct { - Address string `json:"address"` - Pubkey string `json:"pubkey"` - Mnemonic string `json:"mnemonic"` - } `json:"result"` + Address string `json:"address"` + Pubkey string `json:"pubkey"` + Mnemonic string `json:"mnemonic"` } -func statusSignupRequest(sdk *SDK, password string) (res signupResponse, err error) { +func statusSignupRequest(sdk *SDK, password string) (*signupResponse, error) { // `{"jsonrpc":"2.0","method":"status_signup","params":[{"password":"%s"}]}` - req := shhRequest{ - JSONRPC: "2.0", - Method: "status_signup", - } + var res signupResponse - req.Params = append(req.Params, &statusSignupParam{ + params := &statusSignupParam{ Password: password, - }) - - body, err := json.Marshal(req) - if err != nil { - return } - sdk.call(string(body), &res) - - return + return &res, sdk.call("status_signup", params, &res) } type getFilterMessagesResponse struct { Result interface{} `json:"result"` } -func shhGetFilterMessagesRequest(sdk *SDK, filters []string) (res *getFilterMessagesResponse, err error) { +func shhGetFilterMessagesRequest(sdk *SDK, filter string) (interface{}, error) { // `{"jsonrpc":"2.0","id":2968,"method":"shh_getFilterMessages","params":["%s"]}` - req := shhRequest{ - ID: 2968, - JSONRPC: "2.0", - Method: "shh_getFilterMessages", - } - for _, f := range filters { - req.Params = append(req.Params, f) - } + var res interface{} - body, err := json.Marshal(req) - if err != nil { - return - } - - sdk.call(string(body), &res) - - return + return res, sdk.call("shh_getFilterMessages", filter, &res) } -type shhPostParam struct { +type Message struct { Signature string `json:"sig"` SymKeyID string `json:"symKeyID"` Payload string `json:"payload"` Topic string `json:"topic"` - TTL int `json:"ttl"` + TTL uint32 `json:"ttl"` PowTarget float64 `json:"powTarget"` - PowTime int `json:"powTime"` + PowTime uint32 `json:"powTime"` } // error response {"jsonrpc":"2.0","id":633,"error":{"code":-32000,"message":"message rejected, PoW too low"}} @@ -209,30 +125,7 @@ type shhPostResponse struct { Error *sshPostError `json:"error"` } -func shhPostRequest(sdk *SDK, params []*shhPostParam) (res *shhPostResponse, err error) { - // `{"jsonrpc":"2.0","id":633,"method":"shh_post","params":[{"sig":"%s","symKeyID":"%s","payload":"%s","topic":"%s","ttl":10,"powTarget":%g,"powTime":1}]}` - req := shhRequest{ - ID: 633, - JSONRPC: "2.0", - Method: "shh_post", - } - for _, p := range params { - req.Params = append(req.Params, p) - } - - body, err := json.Marshal(req) - if err != nil { - return - } - - err = sdk.call(string(body), &res) - if err != nil { - return res, err - } - - if res.Error != nil { - return res, errors.New(res.Error.Message) - } - - return +func shhPostRequest(sdk *SDK, msg *Message) (string, error) { + var res string + return res, sdk.call("shh_post", msg, &res) } diff --git a/examples/pinger/main.go b/examples/pinger/main.go index 2e94378..bde38cd 100644 --- a/examples/pinger/main.go +++ b/examples/pinger/main.go @@ -2,30 +2,46 @@ package main import ( "fmt" + "log" "time" + "github.com/ethereum/go-ethereum/rpc" "github.com/status-im/status-go-sdk" ) func main() { - client := sdk.New("localhost:30303") + rpcClient, err := rpc.Dial("http://localhost:8545") + checkErr(err) - addr, _, _, err := client.Signup("password") + remoteClient := &remoteClient{rpcClient} + client := sdk.New(remoteClient) + + a, err := client.SignupAndLogin("password") + checkErr(err) + + ch, err := a.JoinPublicChannel("supu") if err != nil { - return + checkErr(err) } - if err := client.Login(addr, "password"); err != nil { - panic(err) - } + fmt.Printf("%+v\n", ch) - ch, err := client.JoinPublicChannel("supu") - if err != nil { - panic("Couldn't connect to status") - } - - for range time.Tick(10 * time.Second) { + for range time.Tick(3 * time.Second) { message := fmt.Sprintf("PING : %d", time.Now().Unix()) _ = ch.Publish(message) } } + +type remoteClient struct { + c *rpc.Client +} + +func (rc *remoteClient) Call(req *sdk.Request, res interface{}) error { + return rc.c.Call(res, req.Method, req.Params) +} + +func checkErr(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/examples/ponger/main.go b/examples/ponger/main.go index 09b52bf..10c3afe 100644 --- a/examples/ponger/main.go +++ b/examples/ponger/main.go @@ -7,35 +7,45 @@ import ( "strings" "time" + "github.com/ethereum/go-ethereum/rpc" "github.com/status-im/status-go-sdk" ) +type remoteClient struct { + c *rpc.Client +} + +func (rc *remoteClient) Call(req *sdk.Request, res interface{}) error { + return rc.c.Call(res, req.Method, req.Params) +} + +func checkErr(err error) { + if err != nil { + log.Fatal(err) + } +} + func main() { - client := sdk.New("localhost:30303") + rpcClient, err := rpc.Dial("http://localhost:8545") + checkErr(err) - addr, _, _, err := client.Signup("password") - if err != nil { - return - } + remoteClient := &remoteClient{rpcClient} + client := sdk.New(remoteClient) - if err := client.Login(addr, "password"); err != nil { - panic(err) - } + a, err := client.SignupAndLogin("password") + checkErr(err) - ch, err := client.JoinPublicChannel("supu") - if err != nil { - panic("Couldn't connect to status") - } + ch, err := a.JoinPublicChannel("supu") + checkErr(err) _, _ = ch.Subscribe(func(m *sdk.Msg) { - log.Println("Message from ", m.From, " with body: ", m.Text) + log.Println("Message from ", m.From, " with body: ", m.Raw) - if strings.Contains(m.Text, "PING :") { + if strings.Contains(m.Raw, "PING :") { time.Sleep(5 * time.Second) message := fmt.Sprintf("PONG : %d", time.Now().Unix()) _ = ch.Publish(message) } - }) runtime.Goexit() diff --git a/msg.go b/msg.go index 82fb7b1..cfb04f0 100644 --- a/msg.go +++ b/msg.go @@ -53,6 +53,7 @@ func supportedMessage(msgType string) bool { // Msg is a structure used by Subscribers and Publish(). type Msg struct { From string `json:"from"` + PubKey string `json:"sig"` ChannelName string `json:"channel"` Channel *Channel `json:"-"` Raw string `json:"-"` @@ -77,7 +78,11 @@ func unrawrChatMessage(message string) ([]byte, error) { func messageFromEnvelope(u interface{}) (msg *Msg, err error) { payload := u.(map[string]interface{})["payload"] - return messageFromPayload(payload.(string)) + msg, err = messageFromPayload(payload.(string)) + if pubkey, ok := u.(map[string]interface{})["sig"]; ok { + msg.PubKey = pubkey.(string) + } + return } func messageFromPayload(payload string) (*Msg, error) { diff --git a/sdk.go b/sdk.go index 247e842..d97156e 100644 --- a/sdk.go +++ b/sdk.go @@ -1,13 +1,12 @@ package sdk import ( - "encoding/json" "log" ) // RPCClient is a client to manage all rpc calls type RPCClient interface { - Call(request interface{}) (response interface{}, err error) + Call(req *Request, res interface{}) error } // SDK is a set of tools to interact with status node @@ -33,7 +32,7 @@ func (c *SDK) Login(addr, pwd string) (a *Account, err error) { } return &Account{ conn: c, - Address: res.Result.AddressKeyID, + Address: res.AddressKeyID, }, err } @@ -45,9 +44,9 @@ func (c *SDK) Signup(pwd string) (a *Account, err error) { } return &Account{ conn: c, - Address: res.Result.Address, - PubKey: res.Result.Pubkey, - Mnemonic: res.Result.Mnemonic, + Address: res.Address, + PubKey: res.Pubkey, + Mnemonic: res.Mnemonic, }, err } @@ -63,18 +62,22 @@ func (c *SDK) SignupAndLogin(password string) (a *Account, err error) { return } +type Request struct { + Method string `json:"method"` + Params interface{} `json:"params"` +} + // NewMessageFilterResponse NewMessageFilter json response type NewMessageFilterResponse struct { Result string `json:"result"` } -func (c *SDK) call(cmd string, res interface{}) error { - log.Println("[ REQUEST ] : " + cmd) - body, err := c.RPCClient.Call(cmd) - if err != nil { - return err +func (c *SDK) call(method string, params interface{}, result interface{}) error { + log.Println("[ REQUEST ] : " + method) + req := &Request{ + Method: method, + Params: params, } - log.Println("[ RESPONSE ] : " + body.(string)) - return json.Unmarshal([]byte(body.(string)), &res) + return c.RPCClient.Call(req, result) }