fix_: fill missing community tokens in controlled communities (#5154) (#5188)

Needed for https://github.com/status-im/status-desktop/issues/14679

On app start, fills controlled communities with missing deployed community tokens if there are.
This commit is contained in:
Jonathan Rainville 2024-05-21 12:00:32 -04:00 committed by GitHub
parent 6f1b82966a
commit af66f517f5
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
3 changed files with 124 additions and 0 deletions

View File

@ -865,6 +865,24 @@ func (o *Community) AddCommunityTokensMetadata(token *protobuf.CommunityTokenMet
return o.config.CommunityDescription, nil
}
func containsToken(tokens []*protobuf.CommunityTokenMetadata, symbol string) bool {
for _, token := range tokens {
if token.Symbol == symbol {
return true
}
}
return false
}
func (o *Community) UpsertCommunityTokensMetadata(token *protobuf.CommunityTokenMetadata) (bool, error) {
if containsToken(o.config.CommunityDescription.CommunityTokensMetadata, token.Symbol) {
return false, nil
}
_, err := o.AddCommunityTokensMetadata(token)
return true, err
}
func (o *Community) UnbanUserFromCommunity(pk *ecdsa.PublicKey) (*protobuf.CommunityDescription, error) {
o.mutex.Lock()
defer o.mutex.Unlock()

View File

@ -481,6 +481,11 @@ func (m *Manager) Start() error {
if m.ownerVerifier != nil {
m.runOwnerVerificationLoop()
}
go func() {
_ = m.fillMissingCommunityTokens()
}()
return nil
}
@ -513,6 +518,61 @@ func (m *Manager) runENSVerificationLoop() {
}()
}
// This function is mostly a way to fix any community that is missing tokens in its description
func (m *Manager) fillMissingCommunityTokens() error {
controlledCommunities, err := m.Controlled()
if err != nil {
m.logger.Error("failed to retrieve orgs", zap.Error(err))
return err
}
unlock := func() {
for _, c := range controlledCommunities {
m.communityLock.Unlock(c.ID())
}
}
for _, c := range controlledCommunities {
m.communityLock.Lock(c.ID())
}
defer unlock()
for _, community := range controlledCommunities {
tokens, err := m.GetCommunityTokens(community.IDString())
if err != nil {
m.logger.Error("failed to retrieve community tokens", zap.Error(err))
return err
}
for _, token := range tokens {
if token.DeployState != community_token.Deployed {
continue
}
tokenMetadata := &protobuf.CommunityTokenMetadata{
ContractAddresses: map[uint64]string{uint64(token.ChainID): token.Address},
Description: token.Description,
Image: token.Base64Image,
Symbol: token.Symbol,
TokenType: token.TokenType,
Name: token.Name,
Decimals: uint32(token.Decimals),
}
modified, err := community.UpsertCommunityTokensMetadata(tokenMetadata)
if err != nil {
m.logger.Error("failed to add token metadata to the description", zap.Error(err))
return err
}
if modified {
err = m.saveAndPublish(community)
if err != nil {
m.logger.Error("failed to save the new community", zap.Error(err))
return err
}
}
}
}
return nil
}
// Only for testing
func (m *Manager) CommunitiesToValidate() (map[string][]communityToValidate, error) { // nolint: golint
return m.persistence.getCommunitiesToValidate()

View File

@ -19,6 +19,7 @@ import (
userimages "github.com/status-im/status-go/images"
"github.com/status-im/status-go/params"
"github.com/status-im/status-go/protocol/common"
community_token "github.com/status-im/status-go/protocol/communities/token"
"github.com/status-im/status-go/protocol/requests"
"github.com/status-im/status-go/protocol/transport"
v1 "github.com/status-im/status-go/protocol/v1"
@ -2003,3 +2004,48 @@ func (s *ManagerSuite) TestCommunityQueueMultipleDifferentSignersIgnoreIfNotRetu
s.Require().NoError(err)
s.Require().Equal(clock1, fetchedCommunity.config.CommunityDescription.Clock)
}
func (s *ManagerSuite) TestFillMissingCommunityTokens() {
// Create community
request := &requests.CreateCommunity{
Name: "status",
Description: "token membership description",
Membership: protobuf.CommunityPermissions_AUTO_ACCEPT,
}
community, err := s.manager.CreateCommunity(request, true)
s.Require().NoError(err)
s.Require().NotNil(community)
s.Require().Len(community.CommunityTokensMetadata(), 0)
// Create community token but without adding to the description
token := community_token.CommunityToken{
TokenType: protobuf.CommunityTokenType_ERC721,
CommunityID: community.IDString(),
Address: "0x001",
Name: "TestTok",
Symbol: "TST",
Description: "Desc",
Supply: &bigint.BigInt{Int: big.NewInt(0)},
InfiniteSupply: true,
Transferable: true,
RemoteSelfDestruct: true,
ChainID: 1,
DeployState: community_token.Deployed,
Base64Image: "",
Decimals: 18,
Deployer: "0x0002",
PrivilegesLevel: community_token.CommunityLevel,
}
err = s.manager.persistence.AddCommunityToken(&token)
s.Require().NoError(err)
// Fill community with missing token
err = s.manager.fillMissingCommunityTokens()
s.Require().NoError(err)
community, err = s.manager.GetByID(community.ID())
s.Require().NoError(err)
s.Require().Len(community.CommunityTokensMetadata(), 1)
}