support for go-ethereum/rpc
This commit is contained in:
parent
8cbd6ec442
commit
aa8eb8f5f7
15
account.go
15
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
|
||||
}
|
||||
|
|
14
chan.go
14
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
|
||||
}
|
||||
|
|
161
dictionary.go
161
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"`
|
||||
}
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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()
|
||||
|
|
7
msg.go
7
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) {
|
||||
|
|
29
sdk.go
29
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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue