diff --git a/account.go b/account.go index 96e93e0..542ac57 100644 --- a/account.go +++ b/account.go @@ -12,6 +12,7 @@ type Account struct { PubKey string Mnemonic string Username string + Image string channels []*Channel } @@ -39,19 +40,58 @@ func (a *Account) createAndJoin(name, password string) (*Channel, error) { return a.Join(name, topicID, symKey) } +// OnContactRequest executes specified ContactRequestHandler logic when a contact +// request is received +func (a *Account) OnContactRequest(fn ContactRequestHandler) error { + topicID, err := a.calculatePublicChannelTopicID(discoveryChannelName) + if err != nil { + return err + } + + filterID, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, "", a.PubKey) + if err != nil { + println(err.Error()) + return err + } + + discoveryChannel := &Channel{ + account: a, + name: discoveryChannelName, + filterID: filterID, + TopicID: topicID, + ChannelPubKey: a.PubKey, + } + + _, err = discoveryChannel.Subscribe(func(msg *Msg) { + switch c := msg.Properties.(type) { + case *NewContactKeyMsg: + fn(&Contact{ + account: a, + SymKey: c.Address, + TopicID: c.Topic, + Name: c.Contact.Name, + Address: c.Contact.Address, + Image: c.Contact.Image, + }) + } + }) + + return err +} + // Join joins a status channel func (a *Account) Join(channelName, topicID, symKey string) (*Channel, error) { - filterID, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, symKey) + filterID, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, symKey, "") if err != nil { return nil, err } ch := &Channel{ - account: a, - name: channelName, - filterID: filterID, - TopicID: topicID, - ChannelKey: symKey, + account: a, + name: channelName, + filterID: filterID, + TopicID: topicID, + ChannelSymKey: symKey, } a.channels = append(a.channels, ch) diff --git a/chan.go b/chan.go index 0c844a5..060a84c 100644 --- a/chan.go +++ b/chan.go @@ -7,12 +7,15 @@ import ( "time" ) +const discoveryChannelName = "contact-discovery" + // Channel : ... type Channel struct { account *Account name string filterID string - ChannelKey string + ChannelSymKey string + ChannelPubKey string TopicID string visibility string subscriptions []*Subscription @@ -69,9 +72,9 @@ func (c *Channel) ContactRequest(username, image string) error { // contact accepts the contact request. It will be sent on the topic that // was provided in the NewContactKey message and use the sym-key. // Both users will therefore have the same filter. -func (c *Channel) ConfirmedContactRequest(username, image string) error { +func (c *Channel) ConfirmedContactRequest(ct *Contact) error { format := `["%s",["%s","%s","%s","%s"]]` - msg := fmt.Sprintf(format, ConfirmedContactRequestType, username, image, c.account.Address, "") + msg := fmt.Sprintf(format, ConfirmedContactRequestType, c.account.Username, c.account.Image, c.account.Address, "") return c.SendPostRawMsg(msg) } @@ -118,7 +121,7 @@ func (c *Channel) ContactUpdateRequest(username, image string) error { func (c *Channel) SendPostRawMsg(body string) error { msg := Message{ Signature: c.account.AddressKeyID, - SymKeyID: c.ChannelKey, + SymKeyID: c.ChannelSymKey, Payload: rawrChatMessage(body), Topic: c.TopicID, TTL: 10, diff --git a/contact.go b/contact.go new file mode 100644 index 0000000..430592d --- /dev/null +++ b/contact.go @@ -0,0 +1,30 @@ +package sdk + +// Contact details for a known user +type Contact struct { + account *Account + ch *Channel + SymKey string + TopicID string + Name string + Image string + Address string +} + +// Accept accepts a contact as a friend, sends back a ConfirmedContactRequest +func (c *Contact) Accept() error { + // Add the proposed symkey + symkey, err := addSymKey(c.account.conn, c.SymKey) + if err != nil { + return err + } + c.ch, err = c.account.Join(c.Name, c.TopicID, symkey) + if err != nil { + return err + } + + return c.ch.ConfirmedContactRequest(c) +} + +// ContactRequestHandler handler for contact requests +type ContactRequestHandler func(*Contact) diff --git a/dictionary.go b/dictionary.go index e5a6bf7..32a4cae 100644 --- a/dictionary.go +++ b/dictionary.go @@ -7,20 +7,28 @@ func shhGenerateSymKeyFromPasswordRequest(sdk *SDK, password string) (string, er } type shhFilterFormatParam struct { - AllowP2P bool `json:"allowP2P"` - Topics []string `json:"topics"` - Type string `json:"type"` - SymKeyID string `json:"symKeyID"` + AllowP2P bool `json:"allowP2P"` + Topics []string `json:"topics"` + Type string `json:"type"` + SymKeyID string `json:"symKeyID"` + PrivateKeyID string `json:"privateKeyID"` } -func newShhMessageFilterFormatRequest(sdk *SDK, topics []string, symKey string) (string, error) { +func newShhMessageFilterFormatRequest(sdk *SDK, topics []string, symKey, privateKeyID string) (string, error) { // `{"jsonrpc":"2.0","id":2,"method":"shh_newMessageFilter","params":[{"allowP2P":true,"topics":["%s"],"type":"sym","symKeyID":"%s"}]}` var res string params := &shhFilterFormatParam{ - AllowP2P: true, - Topics: topics, - Type: "sym", - SymKeyID: symKey, + AllowP2P: true, + Topics: topics, + Type: "sym", + SymKeyID: symKey, + PrivateKeyID: privateKeyID, + } + if len(symKey) > 0 { + params.SymKeyID = symKey + } + if len(privateKeyID) > 0 { + params.PrivateKeyID = privateKeyID } return res, sdk.RPCClient.Call(&res, "shh_newMessageFilter", params) @@ -83,7 +91,8 @@ func shhGetFilterMessagesRequest(sdk *SDK, filter string) (interface{}, error) { // Message message to be sent though ssh_post calls type Message struct { Signature string `json:"sig"` - SymKeyID string `json:"symKeyID"` + SymKeyID string `json:"symKeyID,omitempty"` + PubKey string `json:"pubKey,omitempty"` Payload string `json:"payload"` Topic string `json:"topic"` TTL uint32 `json:"ttl"` @@ -93,5 +102,11 @@ type Message struct { func shhPostRequest(sdk *SDK, msg *Message) (string, error) { var res string - return res, sdk.RPCClient.Call(&res, "shh_post", msg) + return res, sdk.RPCClient.Call(&res, "shhext_post", msg) +} + +func addSymKey(sdk *SDK, symKey string) (string, error) { + // {"jsonrpc":"2.0","method":"shh_addSymKey", "params":["` + symkey + `"], "id":1} + var res string + return res, sdk.RPCClient.Call(&res, "shh_addSymKey", symKey) } diff --git a/dictionary_test.go b/dictionary_test.go index b66288b..f64c8a4 100644 --- a/dictionary_test.go +++ b/dictionary_test.go @@ -59,7 +59,7 @@ func TestDictionaryMethods(t *testing.T) { { Description: "shhPostRequest", Response: &str, - Method: "shh_post", + Method: "shhext_post", Params: &Message{}, Callback: func(sdk *SDK) { response, err := shhPostRequest(sdk, &Message{}) @@ -100,7 +100,7 @@ func TestDictionaryMethods(t *testing.T) { SymKeyID: "", }, Callback: func(sdk *SDK) { - response, err := newShhMessageFilterFormatRequest(sdk, []string{}, "") + response, err := newShhMessageFilterFormatRequest(sdk, []string{}, "", "") assert.NoError(t, err) assert.NotNil(t, response) }, diff --git a/examples/contact/main.go b/examples/contact/main.go new file mode 100644 index 0000000..8c45622 --- /dev/null +++ b/examples/contact/main.go @@ -0,0 +1,48 @@ +package main + +import ( + "log" + "runtime" + + "github.com/ethereum/go-ethereum/rpc" + "github.com/status-im/status-go-sdk" +) + +const ( + botUsername = "TestBot" + botImage = "data:image/png;base64,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" +) + +func main() { + rpcClient, err := rpc.Dial("http://localhost:8545") + checkErr(err) + + client := sdk.New(rpcClient) + bot, err := client.SignupAndLogin("password") + bot.Username = botUsername + bot.Image = botImage + + // Wait for contact requests + err = bot.OnContactRequest(func(ct *sdk.Contact) { + log.Println("Received contact request from " + ct.Name) + log.Println("Accepting " + ct.Name + "'s contact request'") + // And we simply accept them all (you can add any conditional you want here) + err = ct.Accept() + checkErr(err) + }) + checkErr(err) + + log.Println("Makeing the bot visible on a public channel so you can easily get its address") + ch, err := bot.JoinPublicChannel("supu") + checkErr(err) + err = ch.Publish("hey there! I'm " + botUsername + ", and I am accepting contact requests :P") + checkErr(err) + + runtime.Goexit() +} + +func checkErr(err error) { + if err != nil { + log.Fatal(err) + } +} diff --git a/msg.go b/msg.go index cfb04f0..c667458 100644 --- a/msg.go +++ b/msg.go @@ -166,7 +166,7 @@ type ContactMsg struct { } func contactMsgFromProperties(properties []interface{}) *ContactMsg { - crProperties := properties[2].([]interface{}) + crProperties := properties[1].([]interface{}) return &ContactMsg{ Name: crProperties[0].(string),