Add support for multiple accounts on the same connection

This commit is contained in:
Adrià Cidre 2018-05-07 12:03:45 +02:00
parent 2259b20eab
commit 4132f48a45
No known key found for this signature in database
GPG Key ID: D246A27D58A92CAB
3 changed files with 96 additions and 84 deletions

70
account.go Normal file
View File

@ -0,0 +1,70 @@
package sdk
import (
"encoding/hex"
)
// Account represents a logged in user on statusd node
type Account struct {
conn *SDK
Address string
PubKey string
Mnemonic string
Username string
channels []*Channel
}
// JoinPublicChannel joins a status public channel
func (a *Account) JoinPublicChannel(channelName string) (*Channel, error) {
symkeyResponse, err := shhGenerateSymKeyFromPasswordRequest(a.conn, []string{channelName})
if err != nil {
return nil, err
}
symKey := symkeyResponse.Key
topicID, err := a.calculatePublicChannelTopicID(channelName, symkeyResponse.ID)
if err != nil {
return nil, err
}
return a.Join(channelName, topicID, symKey)
}
// Join joins a status channel
func (a *Account) Join(channelName, topicID, symKey string) (*Channel, error) {
newMessageFilterResponse, err := newShhMessageFilterFormatRequest(a.conn, []string{topicID}, symKey)
if err != nil {
return nil, err
}
filterID := newMessageFilterResponse.FilterID
ch := &Channel{
account: a,
name: channelName,
filterID: filterID,
topicID: topicID,
channelKey: symKey,
}
a.channels = append(a.channels, ch)
return ch, nil
}
func (a *Account) calculatePublicChannelTopicID(name string, symkey int) (topicID string, err error) {
p := "0x" + hex.EncodeToString([]byte(name))
web3ShaResponse, err := web3Sha3Request(a.conn, symkey, []string{p})
if err != nil {
return
}
topicID = web3ShaResponse.Result[0:10]
return
}
// Close all channels you're subscribed to
func (a *Account) Close() {
for _, ch := range a.channels {
ch.Close()
}
}

18
chan.go
View File

@ -9,7 +9,7 @@ import (
// Channel : ...
type Channel struct {
conn *SDK
account *Account
name string
filterID string
channelKey string
@ -52,7 +52,7 @@ func (c *Channel) NewContactKeyRequest(username string) error {
contactRequest := fmt.Sprintf(format, ContactRequestType, username, "", "", "")
format = `["%s",["%s","%s",%s]`
msg := fmt.Sprintf(format, NewContactKeyType, c.conn.address, c.topicID, contactRequest)
msg := fmt.Sprintf(format, NewContactKeyType, c.account.Address, c.topicID, contactRequest)
return c.SendPostRawMsg(msg)
}
@ -60,7 +60,7 @@ func (c *Channel) NewContactKeyRequest(username string) error {
// ContactRequest wrapped in a NewContactKey message when initiating a contact request.
func (c *Channel) ContactRequest(username, image string) error {
format := `["%s",["%s","%s","%s","%s"]]]`
msg := fmt.Sprintf(format, ContactRequestType, username, image, c.conn.address, "")
msg := fmt.Sprintf(format, ContactRequestType, username, image, c.account.Address, "")
return c.SendPostRawMsg(msg)
}
@ -71,7 +71,7 @@ func (c *Channel) ContactRequest(username, image string) error {
// Both users will therefore have the same filter.
func (c *Channel) ConfirmedContactRequest(username, image string) error {
format := `["%s",["%s","%s","%s","%s"]]`
msg := fmt.Sprintf(format, ConfirmedContactRequestType, username, image, c.conn.address, "")
msg := fmt.Sprintf(format, ConfirmedContactRequestType, username, image, c.account.Address, "")
return c.SendPostRawMsg(msg)
}
@ -117,16 +117,16 @@ 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{
Signature: c.conn.address,
Signature: c.account.Address,
SymKeyID: c.channelKey,
Payload: rawrChatMessage(body),
Topic: c.topicID,
TTL: 10,
PowTarget: c.conn.minimumPoW,
PowTarget: c.account.conn.minimumPoW,
PowTime: 1,
}
_, err := shhPostRequest(c.conn, []*shhPostParam{&param})
_, err := shhPostRequest(c.account.conn, []*shhPostParam{&param})
if err != nil {
log.Println(err.Error())
}
@ -139,7 +139,7 @@ func (c *Channel) SendPostRawMsg(body string) error {
// push notification server Public Key.
func (c *Channel) PNBroadcastAvailabilityRequest() error {
format := `["%s",["%s"]]`
msg := fmt.Sprintf(format, PNBroadcastAvailabilityType, c.conn.pubkey)
msg := fmt.Sprintf(format, PNBroadcastAvailabilityType, c.account.PubKey)
return c.SendPostRawMsg(msg)
}
@ -178,7 +178,7 @@ func (c *Channel) removeSubscription(sub *Subscription) {
}
func (c *Channel) pollMessages() (msg *Msg) {
res, err := shhGetFilterMessagesRequest(c.conn, []string{c.filterID})
res, err := shhGetFilterMessagesRequest(c.account.conn, []string{c.filterID})
if err != nil {
log.Fatalf("Error when sending request to server: %s", err)
return

92
sdk.go
View File

@ -1,7 +1,6 @@
package sdk
import (
"encoding/hex"
"encoding/json"
"log"
)
@ -14,11 +13,7 @@ type RPCClient interface {
// SDK is a set of tools to interact with status node
type SDK struct {
RPCClient RPCClient
address string
pubkey string
mnemonic string
userName string
channels []*Channel
accounts []*Account
minimumPoW float64
}
@ -30,44 +25,39 @@ func New(c RPCClient) *SDK {
}
}
// Close all channels you're subscribed to
func (c *SDK) Close() {
for _, channel := range c.channels {
channel.Close()
}
}
// Login to status with the given credentials
func (c *SDK) Login(addr, pwd string) error {
func (c *SDK) Login(addr, pwd string) (a *Account, err error) {
res, err := statusLoginRequest(c, addr, pwd)
if err != nil {
return err
return a, err
}
c.address = res.Result.AddressKeyID
return nil
return &Account{
Address: res.Result.AddressKeyID,
}, err
}
// Signup creates a new account with the given credentials
func (c *SDK) Signup(pwd string) (addr string, pubkey string, mnemonic string, err error) {
func (c *SDK) Signup(pwd string) (a *Account, err error) {
res, err := statusSignupRequest(c, pwd)
if err != nil {
return "", "", "", err
return a, err
}
c.address = res.Result.Address
c.pubkey = res.Result.Pubkey
c.mnemonic = res.Result.Mnemonic
return &Account{
Address: res.Result.Address,
PubKey: res.Result.Pubkey,
Mnemonic: res.Result.Mnemonic,
}, err
return res.Result.Address, res.Result.Pubkey, res.Result.Mnemonic, err
}
// SignupAndLogin sign up and login on status network
func (c *SDK) SignupAndLogin(password string) (addr string, pubkey string, mnemonic string, err error) {
addr, pubkey, mnemonic, err = c.Signup(password)
func (c *SDK) SignupAndLogin(password string) (a *Account, err error) {
a, err = c.Signup(password)
if err != nil {
return
}
err = c.Login(addr, password)
la, err := c.Login(a.Address, password)
a.Address = la.Address
return
}
@ -76,54 +66,6 @@ type NewMessageFilterResponse struct {
Result string `json:"result"`
}
// JoinPublicChannel joins a status public channel
func (c *SDK) JoinPublicChannel(channelName string) (*Channel, error) {
symkeyResponse, err := shhGenerateSymKeyFromPasswordRequest(c, []string{channelName})
if err != nil {
return nil, err
}
symKey := symkeyResponse.Key
topicID, err := c.calculatePublicChannelTopicID(channelName, symkeyResponse.ID)
if err != nil {
return nil, err
}
return c.Join(channelName, topicID, symKey)
}
// Join joins a status channel
func (c *SDK) Join(channelName, topicID, symKey string) (*Channel, error) {
newMessageFilterResponse, err := newShhMessageFilterFormatRequest(c, []string{topicID}, symKey)
if err != nil {
return nil, err
}
filterID := newMessageFilterResponse.FilterID
ch := &Channel{
conn: c,
name: channelName,
filterID: filterID,
topicID: topicID,
channelKey: symKey,
}
c.channels = append(c.channels, ch)
return ch, nil
}
func (c *SDK) calculatePublicChannelTopicID(name string, symkey int) (topicID string, err error) {
p := "0x" + hex.EncodeToString([]byte(name))
web3ShaResponse, err := web3Sha3Request(c, symkey, []string{p})
if err != nil {
return
}
topicID = web3ShaResponse.Result[0:10]
return
}
func (c *SDK) call(cmd string, res interface{}) error {
log.Println("[ REQUEST ] : " + cmd)
body, err := c.RPCClient.Call(cmd)