Status public API
This commit is contained in:
parent
07e46714f0
commit
e63f6461ed
|
@ -1121,6 +1121,10 @@ func (b *GethStatusBackend) injectAccountsIntoServices() error {
|
||||||
}
|
}
|
||||||
// Set initial connection state
|
// Set initial connection state
|
||||||
st.ConnectionChanged(b.connectionState)
|
st.ConnectionChanged(b.connectionState)
|
||||||
|
|
||||||
|
messenger := st.Messenger()
|
||||||
|
// Init public status api
|
||||||
|
b.statusNode.StatusPublicService().Init(messenger)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,6 +39,7 @@ import (
|
||||||
"github.com/status-im/status-go/services/personal"
|
"github.com/status-im/status-go/services/personal"
|
||||||
"github.com/status-im/status-go/services/rpcfilters"
|
"github.com/status-im/status-go/services/rpcfilters"
|
||||||
"github.com/status-im/status-go/services/rpcstats"
|
"github.com/status-im/status-go/services/rpcstats"
|
||||||
|
"github.com/status-im/status-go/services/status"
|
||||||
"github.com/status-im/status-go/services/subscriptions"
|
"github.com/status-im/status-go/services/subscriptions"
|
||||||
"github.com/status-im/status-go/services/wakuext"
|
"github.com/status-im/status-go/services/wakuext"
|
||||||
"github.com/status-im/status-go/services/wakuv2ext"
|
"github.com/status-im/status-go/services/wakuv2ext"
|
||||||
|
@ -89,6 +90,7 @@ type StatusNode struct {
|
||||||
rpcFiltersSrvc *rpcfilters.Service
|
rpcFiltersSrvc *rpcfilters.Service
|
||||||
subscriptionsSrvc *subscriptions.Service
|
subscriptionsSrvc *subscriptions.Service
|
||||||
rpcStatsSrvc *rpcstats.Service
|
rpcStatsSrvc *rpcstats.Service
|
||||||
|
statusPublicSrvc *status.Service
|
||||||
accountsSrvc *accountssvc.Service
|
accountsSrvc *accountssvc.Service
|
||||||
browsersSrvc *browsers.Service
|
browsersSrvc *browsers.Service
|
||||||
permissionsSrvc *permissions.Service
|
permissionsSrvc *permissions.Service
|
||||||
|
|
|
@ -32,6 +32,7 @@ import (
|
||||||
"github.com/status-im/status-go/services/personal"
|
"github.com/status-im/status-go/services/personal"
|
||||||
"github.com/status-im/status-go/services/rpcfilters"
|
"github.com/status-im/status-go/services/rpcfilters"
|
||||||
"github.com/status-im/status-go/services/rpcstats"
|
"github.com/status-im/status-go/services/rpcstats"
|
||||||
|
"github.com/status-im/status-go/services/status"
|
||||||
"github.com/status-im/status-go/services/subscriptions"
|
"github.com/status-im/status-go/services/subscriptions"
|
||||||
"github.com/status-im/status-go/services/wakuext"
|
"github.com/status-im/status-go/services/wakuext"
|
||||||
"github.com/status-im/status-go/services/wakuv2ext"
|
"github.com/status-im/status-go/services/wakuv2ext"
|
||||||
|
@ -60,6 +61,7 @@ func (b *StatusNode) initServices(config *params.NodeConfig) error {
|
||||||
services = append(services, b.appmetricsService())
|
services = append(services, b.appmetricsService())
|
||||||
services = append(services, b.peerService())
|
services = append(services, b.peerService())
|
||||||
services = append(services, b.personalService())
|
services = append(services, b.personalService())
|
||||||
|
services = append(services, b.statusPublicService())
|
||||||
services = appendIf(config.EnableNTPSync, services, b.timeSource())
|
services = appendIf(config.EnableNTPSync, services, b.timeSource())
|
||||||
services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService(accountsFeed))
|
services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService(accountsFeed))
|
||||||
services = appendIf(config.BrowsersConfig.Enabled, services, b.browsersService())
|
services = appendIf(config.BrowsersConfig.Enabled, services, b.browsersService())
|
||||||
|
@ -166,6 +168,17 @@ func (b *StatusNode) wakuV2ExtService(config *params.NodeConfig) (*wakuv2ext.Ser
|
||||||
return b.wakuV2ExtSrvc, nil
|
return b.wakuV2ExtSrvc, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (b *StatusNode) statusPublicService() *status.Service {
|
||||||
|
if b.statusPublicSrvc == nil {
|
||||||
|
b.statusPublicSrvc = status.New()
|
||||||
|
}
|
||||||
|
return b.statusPublicSrvc
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b *StatusNode) StatusPublicService() *status.Service {
|
||||||
|
return b.statusPublicSrvc
|
||||||
|
}
|
||||||
|
|
||||||
func (b *StatusNode) WakuService() *waku.Waku {
|
func (b *StatusNode) WakuService() *waku.Waku {
|
||||||
return b.wakuSrvc
|
return b.wakuSrvc
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,6 +5,7 @@ import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/golang/protobuf/proto"
|
"github.com/golang/protobuf/proto"
|
||||||
|
@ -76,6 +77,73 @@ type CommunityCategory struct {
|
||||||
Position int `json:"position"` // Position is used to sort the categories
|
Position int `json:"position"` // Position is used to sort the categories
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (o *Community) MarshalPublicAPIJSON() ([]byte, error) {
|
||||||
|
if o.config.MemberIdentity == nil {
|
||||||
|
return nil, errors.New("member identity not set")
|
||||||
|
}
|
||||||
|
communityItem := struct {
|
||||||
|
ID types.HexBytes `json:"id"`
|
||||||
|
Verified bool `json:"verified"`
|
||||||
|
Chats map[string]CommunityChat `json:"chats"`
|
||||||
|
Categories map[string]CommunityCategory `json:"categories"`
|
||||||
|
Name string `json:"name"`
|
||||||
|
Description string `json:"description"`
|
||||||
|
Images map[string]images.IdentityImage `json:"images"`
|
||||||
|
Color string `json:"color"`
|
||||||
|
MembersCount int `json:"membersCount"`
|
||||||
|
EnsName string `json:"ensName"`
|
||||||
|
Link string `json:"link"`
|
||||||
|
}{
|
||||||
|
ID: o.ID(),
|
||||||
|
Verified: o.config.Verified,
|
||||||
|
Chats: make(map[string]CommunityChat),
|
||||||
|
Categories: make(map[string]CommunityCategory),
|
||||||
|
}
|
||||||
|
if o.config.CommunityDescription != nil {
|
||||||
|
for id, c := range o.config.CommunityDescription.Categories {
|
||||||
|
category := CommunityCategory{
|
||||||
|
ID: id,
|
||||||
|
Name: c.Name,
|
||||||
|
Position: int(c.Position),
|
||||||
|
}
|
||||||
|
communityItem.Categories[id] = category
|
||||||
|
}
|
||||||
|
for id, c := range o.config.CommunityDescription.Chats {
|
||||||
|
canPost, err := o.CanPost(o.config.MemberIdentity, id, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
chat := CommunityChat{
|
||||||
|
ID: id,
|
||||||
|
Name: c.Identity.DisplayName,
|
||||||
|
Description: c.Identity.Description,
|
||||||
|
Permissions: c.Permissions,
|
||||||
|
Members: c.Members,
|
||||||
|
CanPost: canPost,
|
||||||
|
CategoryID: c.CategoryId,
|
||||||
|
Position: int(c.Position),
|
||||||
|
}
|
||||||
|
communityItem.Chats[id] = chat
|
||||||
|
}
|
||||||
|
communityItem.MembersCount = len(o.config.CommunityDescription.Members)
|
||||||
|
communityItem.Link = fmt.Sprintf("https://join.status.im/c/0x%x", o.ID())
|
||||||
|
if o.config.CommunityDescription.Identity != nil {
|
||||||
|
communityItem.Name = o.Name()
|
||||||
|
communityItem.Color = o.config.CommunityDescription.Identity.Color
|
||||||
|
communityItem.Description = o.config.CommunityDescription.Identity.Description
|
||||||
|
for t, i := range o.config.CommunityDescription.Identity.Images {
|
||||||
|
if communityItem.Images == nil {
|
||||||
|
communityItem.Images = make(map[string]images.IdentityImage)
|
||||||
|
}
|
||||||
|
communityItem.Images[t] = images.IdentityImage{Name: t, Payload: i.Payload}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return json.Marshal(communityItem)
|
||||||
|
}
|
||||||
|
|
||||||
func (o *Community) MarshalJSON() ([]byte, error) {
|
func (o *Community) MarshalJSON() ([]byte, error) {
|
||||||
if o.config.MemberIdentity == nil {
|
if o.config.MemberIdentity == nil {
|
||||||
return nil, errors.New("member identity not set")
|
return nil, errors.New("member identity not set")
|
||||||
|
|
|
@ -729,9 +729,22 @@ func (m *Messenger) BanUserFromCommunity(request *requests.BanUserFromCommunity)
|
||||||
// RequestCommunityInfoFromMailserver installs filter for community and requests its details
|
// RequestCommunityInfoFromMailserver installs filter for community and requests its details
|
||||||
// from mailserver. When response received it will be passed through signals handler
|
// from mailserver. When response received it will be passed through signals handler
|
||||||
func (m *Messenger) RequestCommunityInfoFromMailserver(communityID string) error {
|
func (m *Messenger) RequestCommunityInfoFromMailserver(communityID string) error {
|
||||||
|
_, err := m.requestCommunityInfoFromMailserver(communityID, true)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestCommunityInfoFromMailserverSync installs filter for community and requests its details
|
||||||
|
// from mailserver. It will wait for a response and return it if any community is found
|
||||||
|
func (m *Messenger) RequestCommunityInfoFromMailserverSync(communityID string) (*communities.Community, error) {
|
||||||
|
return m.requestCommunityInfoFromMailserver(communityID, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
// RequestCommunityInfoFromMailserver installs filter for community and requests its details
|
||||||
|
// from mailserver. When response received it will be passed through signals handler
|
||||||
|
func (m *Messenger) requestCommunityInfoFromMailserver(communityID string, async bool) (*communities.Community, error) {
|
||||||
|
|
||||||
if _, ok := m.requestedCommunities[communityID]; ok {
|
if _, ok := m.requestedCommunities[communityID]; ok {
|
||||||
return nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//If filter wasn't installed we create it and remember for deinstalling after
|
//If filter wasn't installed we create it and remember for deinstalling after
|
||||||
|
@ -740,10 +753,10 @@ func (m *Messenger) RequestCommunityInfoFromMailserver(communityID string) error
|
||||||
if filter == nil {
|
if filter == nil {
|
||||||
filters, err := m.transport.InitPublicFilters([]string{communityID})
|
filters, err := m.transport.InitPublicFilters([]string{communityID})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Can't install filter for community: %v", err)
|
return nil, fmt.Errorf("Can't install filter for community: %v", err)
|
||||||
}
|
}
|
||||||
if len(filters) != 1 {
|
if len(filters) != 1 {
|
||||||
return fmt.Errorf("Unexpected amount of filters created")
|
return nil, fmt.Errorf("Unexpected amount of filters created")
|
||||||
}
|
}
|
||||||
filter = filters[0]
|
filter = filters[0]
|
||||||
m.requestedCommunities[communityID] = filter
|
m.requestedCommunities[communityID] = filter
|
||||||
|
@ -763,19 +776,44 @@ func (m *Messenger) RequestCommunityInfoFromMailserver(communityID string) error
|
||||||
filter,
|
filter,
|
||||||
false)
|
false)
|
||||||
|
|
||||||
//It is possible that we already processed last existing message for community
|
if err != nil {
|
||||||
//and won't get any updates, so send stored info in this case after timeout
|
return nil, err
|
||||||
go func() {
|
}
|
||||||
time.Sleep(15 * time.Second)
|
|
||||||
m.mutex.Lock()
|
|
||||||
defer m.mutex.Unlock()
|
|
||||||
|
|
||||||
if _, ok := m.requestedCommunities[communityID]; ok {
|
if async {
|
||||||
m.passStoredCommunityInfoToSignalHandler(communityID)
|
//It is possible that we already processed last existing message for community
|
||||||
}
|
//and won't get any updates, so send stored info in this case after timeout
|
||||||
}()
|
go func() {
|
||||||
|
time.Sleep(15 * time.Second)
|
||||||
|
m.mutex.Lock()
|
||||||
|
defer m.mutex.Unlock()
|
||||||
|
|
||||||
return err
|
if _, ok := m.requestedCommunities[communityID]; ok {
|
||||||
|
m.passStoredCommunityInfoToSignalHandler(communityID)
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
time.Sleep(15 * time.Second)
|
||||||
|
|
||||||
|
//send signal to client that message status updated
|
||||||
|
community, err := m.communitiesManager.GetByIDString(communityID)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if community == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
//if there is no info helpful for client, we don't post it
|
||||||
|
if community.Name() == "" && community.DescriptionText() == "" && community.MembersCount() == 0 {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
m.forgetCommunityRequest(communityID)
|
||||||
|
|
||||||
|
return community, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// forgetCommunityRequest removes community from requested ones and removes filter
|
// forgetCommunityRequest removes community from requested ones and removes filter
|
||||||
|
|
|
@ -482,3 +482,7 @@ func (s *Service) ConnectionChanged(state connection.State) {
|
||||||
s.messenger.ConnectionChanged(state)
|
s.messenger.ConnectionChanged(state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Service) Messenger() *protocol.Messenger {
|
||||||
|
return s.messenger
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,83 @@
|
||||||
|
package status
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
|
||||||
|
"github.com/ethereum/go-ethereum/node"
|
||||||
|
"github.com/ethereum/go-ethereum/p2p"
|
||||||
|
"github.com/ethereum/go-ethereum/rpc"
|
||||||
|
|
||||||
|
"github.com/status-im/status-go/eth-node/types"
|
||||||
|
"github.com/status-im/status-go/protocol"
|
||||||
|
)
|
||||||
|
|
||||||
|
// Make sure that Service implements node.Lifecycle interface.
|
||||||
|
var _ node.Lifecycle = (*Service)(nil)
|
||||||
|
var ErrNotInitialized = errors.New("status public api not initialized")
|
||||||
|
|
||||||
|
// Service represents out own implementation of personal sign operations.
|
||||||
|
type Service struct {
|
||||||
|
messenger *protocol.Messenger
|
||||||
|
}
|
||||||
|
|
||||||
|
// New returns a new Service.
|
||||||
|
func New() *Service {
|
||||||
|
return &Service{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Service) Init(messenger *protocol.Messenger) {
|
||||||
|
s.messenger = messenger
|
||||||
|
}
|
||||||
|
|
||||||
|
// Protocols returns a new protocols list. In this case, there are none.
|
||||||
|
func (s *Service) Protocols() []p2p.Protocol {
|
||||||
|
return []p2p.Protocol{}
|
||||||
|
}
|
||||||
|
|
||||||
|
// APIs returns a list of new APIs.
|
||||||
|
func (s *Service) APIs() []rpc.API {
|
||||||
|
return []rpc.API{
|
||||||
|
{
|
||||||
|
Namespace: "status",
|
||||||
|
Version: "1.0",
|
||||||
|
Service: NewPublicAPI(s),
|
||||||
|
Public: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewPublicAPI returns a reference to the PublicAPI object
|
||||||
|
func NewPublicAPI(s *Service) *PublicAPI {
|
||||||
|
api := &PublicAPI{
|
||||||
|
service: s,
|
||||||
|
}
|
||||||
|
return api
|
||||||
|
}
|
||||||
|
|
||||||
|
// Start is run when a service is started.
|
||||||
|
func (s *Service) Start() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Stop is run when a service is stopped.
|
||||||
|
func (s *Service) Stop() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
type PublicAPI struct {
|
||||||
|
service *Service
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *PublicAPI) CommunityInfo(communityID types.HexBytes) (json.RawMessage, error) {
|
||||||
|
if p.service.messenger == nil {
|
||||||
|
return nil, ErrNotInitialized
|
||||||
|
}
|
||||||
|
|
||||||
|
community, err := p.service.messenger.RequestCommunityInfoFromMailserverSync(communityID.String())
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return community.MarshalPublicAPIJSON()
|
||||||
|
}
|
Loading…
Reference in New Issue