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
|
||||
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/rpcfilters"
|
||||
"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/wakuext"
|
||||
"github.com/status-im/status-go/services/wakuv2ext"
|
||||
|
@ -89,6 +90,7 @@ type StatusNode struct {
|
|||
rpcFiltersSrvc *rpcfilters.Service
|
||||
subscriptionsSrvc *subscriptions.Service
|
||||
rpcStatsSrvc *rpcstats.Service
|
||||
statusPublicSrvc *status.Service
|
||||
accountsSrvc *accountssvc.Service
|
||||
browsersSrvc *browsers.Service
|
||||
permissionsSrvc *permissions.Service
|
||||
|
|
|
@ -32,6 +32,7 @@ import (
|
|||
"github.com/status-im/status-go/services/personal"
|
||||
"github.com/status-im/status-go/services/rpcfilters"
|
||||
"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/wakuext"
|
||||
"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.peerService())
|
||||
services = append(services, b.personalService())
|
||||
services = append(services, b.statusPublicService())
|
||||
services = appendIf(config.EnableNTPSync, services, b.timeSource())
|
||||
services = appendIf(b.appDB != nil && b.multiaccountsDB != nil, services, b.accountsService(accountsFeed))
|
||||
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
|
||||
}
|
||||
|
||||
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 {
|
||||
return b.wakuSrvc
|
||||
}
|
||||
|
|
|
@ -5,6 +5,7 @@ import (
|
|||
"crypto/ecdsa"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"github.com/golang/protobuf/proto"
|
||||
|
@ -76,6 +77,73 @@ type CommunityCategory struct {
|
|||
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) {
|
||||
if o.config.MemberIdentity == nil {
|
||||
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
|
||||
// from mailserver. When response received it will be passed through signals handler
|
||||
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 {
|
||||
return nil
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
//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 {
|
||||
filters, err := m.transport.InitPublicFilters([]string{communityID})
|
||||
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 {
|
||||
return fmt.Errorf("Unexpected amount of filters created")
|
||||
return nil, fmt.Errorf("Unexpected amount of filters created")
|
||||
}
|
||||
filter = filters[0]
|
||||
m.requestedCommunities[communityID] = filter
|
||||
|
@ -763,19 +776,44 @@ func (m *Messenger) RequestCommunityInfoFromMailserver(communityID string) error
|
|||
filter,
|
||||
false)
|
||||
|
||||
//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()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if _, ok := m.requestedCommunities[communityID]; ok {
|
||||
m.passStoredCommunityInfoToSignalHandler(communityID)
|
||||
}
|
||||
}()
|
||||
if async {
|
||||
//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
|
||||
|
|
|
@ -482,3 +482,7 @@ func (s *Service) ConnectionChanged(state connection.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