feat(Communities): allow for creating community permissions

This commit is the first of implementing community permissions.
**It is not implementing the complete feature**, rather does it
introduce the first pieces, such that we can get code reviewed and
merged before it grows too big.

To review these features, please make sure to

1. Enable wallet (Settings -> Advanced -> Wallet toggle)
2. Enable community permissions (Settings -> Advanced -> Community
   Permissions toggle)

You'll have to restart the app after doing so.

The commit introduces the following:

**UI, API calls and view models to CRUD community permissions**

After creating a community, the user can go to the community
settings and create new token permissions. The user can also update
and delete existing permissions.

**Asset and collectible view models**

To create community token permissions, users have to select
the token criteria. This commit introduces the `assetsModel` for ERC20
tokens and `collectiblesModel` for `ERC721` tokens.

The latter only supports custom minted community tokens at this point.

**This commit requires:** https://github.com/status-im/status-go/pull/3207
This commit is contained in:
Pascal Precht 2023-02-28 16:23:09 +01:00 committed by r4bbit
parent 489d5d501d
commit e4b8814bfa
31 changed files with 1364 additions and 144 deletions

View File

@ -16,7 +16,13 @@ type
NewMessage,
NewMessageWithPersonalMention,
NewMessageWithGlobalMention,
IdentityVerificationRequest
IdentityVerificationRequest,
CommunityTokenPermissionCreated,
CommunityTokenPermissionUpdated,
CommunityTokenPermissionDeleted,
CommunityTokenPermissionCreationFailed,
CommunityTokenPermissionUpdateFailed,
CommunityTokenPermissionDeletionFailed
NotificationDetails* = object
notificationType*: NotificationType # the default value is `UnknownNotification`

View File

@ -85,6 +85,12 @@ QtObject:
self, "onMeMentionedIconBadgeNotification(int)", 2)
signalConnect(singletonInstance.globalEvents, "showAcceptedContactRequest(QString, QString, QString)",
self, "onShowAcceptedContactRequest(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionCreatedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionCreatedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionUpdatedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionUpdatedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionDeletedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionDeletedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionCreationFailedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionCreationFailedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionUpdateFailedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionUpdateFailedNotification(QString, QString, QString)", 2)
signalConnect(singletonInstance.globalEvents, "showCommunityTokenPermissionDeletionFailedNotification(QString, QString, QString)", self, "onShowCommunityTokenPermissionDeletionFailedNotification(QString, QString, QString)", 2)
self.notificationSetUp = true
@ -140,6 +146,30 @@ QtObject:
messageId: messageId)
self.processNotification(title, message, details)
proc onShowCommunityTokenPermissionCreatedNotification*(self: NotificationsManager, sectionId: string, title: string, message: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionCreated, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowCommunityTokenPermissionUpdatedNotification*(self: NotificationsManager, sectionId: string, title: string, message: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionUpdated, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowCommunityTokenPermissionDeletedNotification*(self: NotificationsManager, sectionId: string, title: string, message: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionDeleted, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowCommunityTokenPermissionCreationFailedNotification*(self: NotificationsManager, sectionId: string, title: string, message: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionCreationFailed, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowCommunityTokenPermissionUpdateFailedNotification*(self: NotificationsManager, sectionId: string, title: string, message: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionUpdateFailed, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowCommunityTokenPermissionDeletionFailedNotification*(self: NotificationsManager, sectionId: string, title: string, message: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.CommunityTokenPermissionDeletionFailed, sectionId: sectionId, isCommunitySection: true)
self.processNotification(title, message, details)
proc onShowNewContactRequestNotification*(self: NotificationsManager, title: string, message: string,
sectionId: string) {.slot.} =
let details = NotificationDetails(notificationType: NotificationType.NewContactRequest, sectionId: sectionId)
@ -306,4 +336,4 @@ QtObject:
# In all other cases (TestNotification, AcceptedContactRequest, JoinCommunityRequest, MyRequestToJoinCommunityAccepted,
# MyRequestToJoinCommunityRejected)
else:
self.notificationCheck(title, message, details, "")
self.notificationCheck(title, message, details, "")

View File

@ -15,6 +15,18 @@ QtObject:
proc showTestNotification*(self: GlobalEvents, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionCreatedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionUpdatedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionDeletedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionCreationFailedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionUpdateFailedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showCommunityTokenPermissionDeletionFailedNotification*(self: GlobalEvents, sectionId: string, title: string, message: string) {.signal.}
proc showMessageNotification*(self: GlobalEvents, title: string, message: string, sectionId: string,
isCommunitySection: bool, isSectionActive: bool, chatId: string, isChatActive: bool, messageId: string,
notificationType: int, isOneToOne: bool, isGroupChat: bool) {.signal.}
@ -34,4 +46,4 @@ QtObject:
proc showAcceptedContactRequest*(self: GlobalEvents, title: string, message: string,
sectionId: string) {.signal.}
proc meMentionedIconBadgeNotification*(self: GlobalEvents, allMentions: int) {.signal.}
proc meMentionedIconBadgeNotification*(self: GlobalEvents, allMentions: int) {.signal.}

View File

@ -10,6 +10,9 @@ import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service
import ../../../../app_service/service/gif/service as gif_service
import ../../../../app_service/service/mailservers/service as mailservers_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/token/service as token_service
import ../../../../app_service/service/community_tokens/service as community_tokens_service
import ../../../../app_service/service/visual_identity/service as procs_from_visual_identity_service
import ../../../core/signals/types
@ -33,12 +36,18 @@ type
messageService: message_service.Service
gifService: gif_service.Service
mailserversService: mailservers_service.Service
walletAccountService: wallet_account_service.Service
tokenService: token_service.Service
communityTokensService: community_tokens_service.Service
proc newController*(delegate: io_interface.AccessInterface, sectionId: string, isCommunity: bool, events: EventEmitter,
settingsService: settings_service.Service, nodeConfigurationService: node_configuration_service.Service,
contactService: contact_service.Service, chatService: chat_service.Service, communityService: community_service.Service,
messageService: message_service.Service, gifService: gif_service.Service,
mailserversService: mailservers_service.Service): Controller =
mailserversService: mailservers_service.Service,
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service,
communityTokensService: community_tokens_service.Service): Controller =
result = Controller()
result.delegate = delegate
result.sectionId = sectionId
@ -53,6 +62,9 @@ proc newController*(delegate: io_interface.AccessInterface, sectionId: string, i
result.messageService = messageService
result.gifService = gifService
result.mailserversService = mailserversService
result.walletAccountService = walletAccountService
result.tokenService = tokenService
result.communityTokensService = communityTokensService
proc delete*(self: Controller) =
discard
@ -202,6 +214,40 @@ proc init*(self: Controller) =
if (args.communityId == self.sectionId):
self.delegate.onCategoryUnmuted(args.categoryId)
self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATED) do(e: Args):
let args = CommunityTokenPermissionArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onCommunityTokenPermissionCreated(args.communityId, args.tokenPermission)
self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_FAILED) do(e: Args):
let args = CommunityTokenPermissionArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onCommunityTokenPermissionCreationFailed(args.communityId)
self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED) do(e: Args):
let args = CommunityTokenPermissionArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onCommunityTokenPermissionUpdated(args.communityId, args.tokenPermission)
self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATE_FAILED) do(e: Args):
let args = CommunityTokenPermissionArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onCommunityTokenPermissionUpdateFailed(args.communityId)
self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETED) do(e: Args):
let args = CommunityTokenPermissionRemovedArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onCommunityTokenPermissionDeleted(args.communityId, args.permissionId)
self.events.on(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETION_FAILED) do(e: Args):
let args = CommunityTokenPermissionArgs(e)
if (args.communityId == self.sectionId):
self.delegate.onCommunityTokenPermissionDeletionFailed(args.communityId)
self.events.on(SIGNAL_WALLET_ACCOUNT_TOKENS_REBUILT) do(e: Args):
self.delegate.onWalletAccountTokensRebuilt()
self.events.on(SIGNAL_CONTACT_NICKNAME_CHANGED) do(e: Args):
var args = ContactArgs(e)
self.delegate.onContactDetailsUpdated(args.contactId)
@ -258,8 +304,11 @@ proc getMySectionId*(self: Controller): string =
proc isCommunity*(self: Controller): bool =
return self.isCommunitySection
proc getCommunityByIdFromAllCommunities*(self: Controller, communityId: string): CommunityDto =
return self.communityService.getCommunityByIdFromAllCommunities(communityId)
proc getMyCommunity*(self: Controller): CommunityDto =
return self.communityService.getCommunityById(self.sectionId)
return self.getCommunityByIdFromAllCommunities(self.sectionId)
proc getCommunityById*(self: Controller, communityId: string): CommunityDto =
return self.communityService.getCommunityById(communityId)
@ -502,3 +551,25 @@ proc getColorHash*(self: Controller, pubkey: string): ColorHashDto =
proc getColorId*(self: Controller, pubkey: string): int =
procs_from_visual_identity_service.colorIdOf(pubkey)
proc createOrEditCommunityTokenPermission*(self: Controller, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
self.communityService.createOrEditCommunityTokenPermission(communityId, tokenPermission)
proc deleteCommunityTokenPermission*(self: Controller, communityId: string, permissionId: string) =
self.communityService.deleteCommunityTokenPermission(communityId, permissionId)
proc allAccountsTokenBalance*(self: Controller, symbol: string): float64 =
return self.walletAccountService.allAccountsTokenBalance(symbol)
proc getTokenList*(self: Controller): seq[TokenDto] =
return self.tokenService.getTokenList()
proc getContractAddressesForToken*(self: Controller, symbol: string): Table[int, string] =
var contractAddresses = self.tokenService.getContractAddressesForToken(symbol)
let communityToken = self.communityTokensService.getCommunityTokenBySymbol(self.getMySectionId(), symbol)
if communityToken.address != "":
contractAddresses[communityToken.chainId] = communityToken.address
return contractAddresses
proc getCommunityTokenList*(self: Controller): seq[CommunityTokenDto] =
return self.communityTokensService.getCommunityTokens(self.getMySectionId())

View File

@ -8,10 +8,13 @@ import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service
import ../../../../app_service/service/gif/service as gif_service
import ../../../../app_service/service/mailservers/service as mailservers_service
import ../../../../app_service/service/token/service as token_service
import model as chats_model
import ../../../core/eventemitter
import ../../shared_models/token_list_item
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -325,3 +328,30 @@ method switchToChannel*(self: AccessInterface, channelName: string) =
method joinSpectatedCommunity*(self: AccessInterface) =
raise newException(ValueError, "No implementation available")
method createOrEditCommunityTokenPermission*(self: AccessInterface, communityId: string, permissionId: string, permissionType: int, tokenCriteriaJson: string, isPrivate: bool) {.base.} =
raise newException(ValueError, "No implementation available")
method deleteCommunityTokenPermission*(self: AccessInterface, communityId: string, permissionId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method onCommunityTokenPermissionCreated*(self: AccessInterface, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
raise newException(ValueError, "No implementation available")
method onCommunityTokenPermissionCreationFailed*(self: AccessInterface, communityId: string) =
raise newException(ValueError, "No implementation available")
method onCommunityTokenPermissionUpdated*(self: AccessInterface, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
raise newException(ValueError, "No implementation available")
method onCommunityTokenPermissionUpdateFailed*(self: AccessInterface, communityId: string) =
raise newException(ValueError, "No implementation available")
method onCommunityTokenPermissionDeleted*(self: AccessInterface, communityId: string, permissionId: string) =
raise newException(ValueError, "No implementation available")
method onCommunityTokenPermissionDeletionFailed*(self: AccessInterface, communityId: string) =
raise newException(ValueError, "No implementation available")
method onWalletAccountTokensRebuilt*(self: AccessInterface) =
raise newException(ValueError, "No implementation available")

View File

@ -7,6 +7,11 @@ import model as chats_model
import item as chat_item
import ../../shared_models/user_item as user_item
import ../../shared_models/user_model as user_model
import ../../shared_models/token_permissions_model
import ../../shared_models/token_permission_item
import ../../shared_models/token_criteria_item
import ../../shared_models/token_criteria_model
import ../../shared_models/token_list_item
import chat_content/module as chat_content_module
import chat_content/users/module as users_module
@ -24,8 +29,12 @@ import ../../../../app_service/service/community/service as community_service
import ../../../../app_service/service/message/service as message_service
import ../../../../app_service/service/mailservers/service as mailservers_service
import ../../../../app_service/service/gif/service as gif_service
import ../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../app_service/service/token/service as token_service
import ../../../../app_service/service/community_tokens/service as community_tokens_service
import ../../../../app_service/service/visual_identity/service as visual_identity
import ../../../../app_service/service/contacts/dto/contacts as contacts_dto
import ../../../../app_service/service/community/dto/community as community_dto
export io_interface
@ -55,6 +64,8 @@ proc buildChatSectionUI(self: Module,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service)
proc buildTokenPermissionItem*(self: Module, tokenPermission: CommunityTokenPermissionDto): TokenPermissionItem
proc newModule*(
delegate: delegate_interface.AccessInterface,
events: EventEmitter,
@ -68,12 +79,15 @@ proc newModule*(
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service
mailserversService: mailservers_service.Service,
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service,
communityTokensService: community_tokens_service.Service
): Module =
result = Module()
result.delegate = delegate
result.controller = controller.newController(result, sectionId, isCommunity, events, settingsService, nodeConfigurationService,
contactService, chatService, communityService, messageService, gifService, mailserversService)
contactService, chatService, communityService, messageService, gifService, mailserversService, walletAccountService, tokenService, communityTokensService)
result.view = view.newView(result)
result.viewVariant = newQVariant(result.view)
result.moduleLoaded = false
@ -288,6 +302,67 @@ proc initContactRequestsModel(self: Module) =
self.view.contactRequestsModel().addItems(contactsWhoAddedMe)
proc rebuildCommunityTokenPermissionsModel(self: Module) =
let community = self.controller.getMyCommunity()
var tokenPermissionsItems: seq[TokenPermissionItem] = @[]
var allTokenRequirementsMet = false
for id, tokenPermission in community.tokenPermissions:
# TODO: for startes we only deal with "become member" permissions
if tokenPermission.`type` == TokenPermissionType.BecomeMember:
let tokenPermissionItem = self.buildTokenPermissionItem(tokenPermission)
# multiple permissions of the same type act as logical OR
# so if at least one of them is fulfilled we can mark the view
# as all lights green
if tokenPermissionItem.tokenCriteriaMet:
allTokenRequirementsMet = true
tokenPermissionsItems.add(tokenPermissionItem)
self.view.tokenPermissionsModel().setItems(tokenPermissionsItems)
self.view.setAllTokenRequirementsMet(allTokenRequirementsMet)
proc initCommunityTokenPermissionsModel(self: Module) =
self.rebuildCommunityTokenPermissionsModel()
proc buildTokenList(self: Module) =
var tokenListItems: seq[TokenListItem]
var collectiblesListItems: seq[TokenListItem]
let erc20Tokens = self.controller.getTokenList()
let communityTokens = self.controller.getCommunityTokenList()
for token in erc20Tokens:
let tokenListItem = initTokenListItem(
key = token.symbol,
name = token.name,
symbol = token.symbol,
color = token.color,
image = "",
category = ord(TokenListItemCategory.General)
)
tokenListItems.add(tokenListItem)
for token in communityTokens:
let tokenListItem = initTokenListItem(
key = token.symbol,
name = token.name,
symbol = token.symbol,
color = "", # community tokens don't have `color`
image = token.image,
category = ord(TokenListItemCategory.Community)
)
collectiblesListItems.add(tokenListItem)
self.view.setTokenListItems(tokenListItems)
self.view.setCollectiblesListItems(collectiblesListItems)
method onWalletAccountTokensRebuilt*(self: Module) =
self.rebuildCommunityTokenPermissionsModel()
proc convertPubKeysToJson(self: Module, pubKeys: string): seq[string] =
return map(parseJson(pubKeys).getElems(), proc(x:JsonNode):string = x.getStr)
@ -327,6 +402,8 @@ method load*(
self.initContactRequestsModel()
else:
self.usersModule.load()
self.initCommunityTokenPermissionsModel()
self.buildTokenList()
let activeChatId = self.controller.getActiveChatId()
let isCurrentSectionActive = self.controller.getIsCurrentSectionActive()
@ -664,6 +741,49 @@ method onChatMuted*(self: Module, chatId: string) =
method onChatUnmuted*(self: Module, chatId: string) =
self.view.chatsModel().changeMutedOnItemById(chatId, muted=false)
method onCommunityTokenPermissionDeleted*(self: Module, communityId: string, permissionId: string) =
self.view.tokenPermissionsModel().removeItemWithId(permissionId)
singletonInstance.globalEvents.showCommunityTokenPermissionDeletedNotification(communityId, "Community permission deleted", "A token permission has been removed")
method onCommunityTokenPermissionCreated*(self: Module, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
if tokenPermission.`type` == TokenPermissionType.BecomeMember:
let tokenPermissionItem = self.buildTokenPermissionItem(tokenPermission)
self.view.tokenPermissionsModel.addItem(tokenPermissionItem)
if tokenPermissionItem.tokenCriteriaMet:
self.view.setAllTokenRequirementsMet(true)
singletonInstance.globalEvents.showCommunityTokenPermissionCreatedNotification(communityId, "Community permission created", "A token permission has been added")
method onCommunityTokenPermissionUpdated*(self: Module, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
if tokenPermission.`type` == TokenPermissionType.BecomeMember:
let tokenPermissionItem = self.buildTokenPermissionItem(tokenPermission)
self.view.tokenPermissionsModel.updateItem(tokenPermission.id, tokenPermissionItem)
if tokenPermissionItem.tokenCriteriaMet:
self.view.setAllTokenRequirementsMet(true)
return
# we now need to check whether any other permission criteria where met.
let community = self.controller.getMyCommunity()
for id, permission in community.tokenPermissions:
if id != tokenPermission.id:
for tc in permission.tokenCriteria:
let balance = self.controller.allAccountsTokenBalance(tc.symbol)
let amount = tc.amount.parseFloat
let tokenCriteriaMet = balance >= amount
if tokenCriteriaMet:
return
self.view.setAllTokenRequirementsMet(false)
singletonInstance.globalEvents.showCommunityTokenPermissionUpdatedNotification(communityId, "Community permission updated", "A token permission has been updated")
method onCommunityTokenPermissionCreationFailed*(self: Module, communityId: string) =
singletonInstance.globalEvents.showCommunityTokenPermissionCreationFailedNotification(communityId, "Failed to create community permission", "Something went wrong")
method onCommunityTokenPermissionUpdateFailed*(self: Module, communityId: string) =
singletonInstance.globalEvents.showCommunityTokenPermissionUpdateFailedNotification(communityId, "Failed to update community permission", "Something went wrong")
method onCommunityTokenPermissionDeletionFailed*(self: Module, communityId: string) =
singletonInstance.globalEvents.showCommunityTokenPermissionDeletionFailedNotification(communityId, "Failed to delete community permission", "Something went wrong")
method onMarkAllMessagesRead*(self: Module, chatId: string) =
self.updateBadgeNotifications(chatId, hasUnreadMessages=false, unviewedMentionsCount=0)
let chatDetails = self.controller.getChatDetails(chatId)
@ -995,3 +1115,65 @@ method contactsStatusUpdated*(self: Module, statusUpdates: seq[StatusUpdateDto])
method joinSpectatedCommunity*(self: Module) =
if self.usersModule != nil:
self.usersModule.updateMembersList()
method createOrEditCommunityTokenPermission*(self: Module, communityId: string, permissionId: string, permissionType: int, tokenCriteriaJson: string, isPrivate: bool) =
var tokenPermission = CommunityTokenPermissionDto()
tokenPermission.id = permissionId
tokenPermission.isPrivate = isPrivate
tokenPermission.`type` = TokenPermissionType(permissionType)
let tokenCriteriaJsonObj = tokenCriteriaJson.parseJson
for tokenCriteria in tokenCriteriaJsonObj:
let viewAmount = tokenCriteria{"amount"}.getFloat
var tokenCriteriaDto = tokenCriteria.toTokenCriteriaDto
let contractAddresses = self.controller.getContractAddressesForToken(tokenCriteriaDto.symbol)
if contractAddresses.len == 0 and tokenCriteriaDto.`type` != TokenCriteriaType.ENS:
if permissionId == "":
self.onCommunityTokenPermissionCreationFailed(communityId)
return
self.onCommunityTokenPermissionUpdateFailed(communityId)
return
tokenCriteriaDto.amount = viewAmount.formatBiggestFloat(ffDecimal)
tokenCriteriaDto.contractAddresses = contractAddresses
tokenPermission.tokenCriteria.add(tokenCriteriaDto)
self.controller.createOrEditCommunityTokenPermission(communityId, tokenPermission)
method deleteCommunityTokenPermission*(self: Module, communityId: string, permissionId: string) =
self.controller.deleteCommunityTokenPermission(communityId, permissionId)
proc buildTokenPermissionItem*(self: Module, tokenPermission: CommunityTokenPermissionDto): TokenPermissionItem =
var tokenCriteriaItems: seq[TokenCriteriaItem] = @[]
var allTokenCriteriaMet = true
for tc in tokenPermission.tokenCriteria:
let balance = self.controller.allAccountsTokenBalance(tc.symbol)
let amount = tc.amount.parseFloat
let tokenCriteriaMet = balance >= amount
let tokenCriteriaItem = initTokenCriteriaItem(
tc.symbol,
tc.name,
amount,
tc.`type`.int,
tc.ensPattern,
tokenCriteriaMet
)
if not tokenCriteriaMet:
allTokenCriteriaMet = false
tokenCriteriaItems.add(tokenCriteriaItem)
let tokenPermissionItem = initTokenPermissionItem(
tokenPermission.id,
tokenPermission.`type`.int,
tokenCriteriaItems,
@[], # TODO: handle chat list items
tokenPermission.isPrivate,
allTokenCriteriaMet
)
return tokenPermissionItem

View File

@ -2,6 +2,11 @@ import NimQml, json, sequtils
import model as chats_model
import item, active_item
import ../../shared_models/user_model as user_model
import ../../shared_models/token_permissions_model
import ../../shared_models/token_permission_item
import ../../shared_models/token_list_model
import ../../shared_models/token_list_item
import ../../../../app_service/service/token/dto
import io_interface
QtObject:
@ -20,6 +25,13 @@ QtObject:
editCategoryChannelsModel: chats_model.Model
editCategoryChannelsVariant: QVariant
loadingHistoryMessagesInProgress: bool
tokenPermissionsModel: TokenPermissionsModel
tokenPermissionsVariant: QVariant
tokenListModel: TokenListModel
tokenListModelVariant: QVariant
collectiblesListModel: TokenListModel
collectiblesListModelVariant: QVariant
allTokenRequirementsMet: bool
proc delete*(self: View) =
self.model.delete
@ -32,6 +44,13 @@ QtObject:
self.listOfMyContactsVariant.delete
self.editCategoryChannelsModel.delete
self.editCategoryChannelsVariant.delete
self.tokenPermissionsModel.delete
self.tokenPermissionsVariant.delete
self.tokenListModel.delete
self.tokenListModelVariant.delete
self.collectiblesListModel.delete
self.collectiblesListModelVariant.delete
self.QObject.delete
proc newView*(delegate: io_interface.AccessInterface): View =
@ -49,6 +68,12 @@ QtObject:
result.listOfMyContacts = user_model.newModel()
result.listOfMyContactsVariant = newQVariant(result.listOfMyContacts)
result.loadingHistoryMessagesInProgress = false
result.tokenPermissionsModel = newTokenPermissionsModel()
result.tokenPermissionsVariant = newQVariant(result.tokenPermissionsModel)
result.tokenListModel = newTokenListModel()
result.tokenListModelVariant = newQVariant(result.tokenListModel)
result.collectiblesListModel = newTokenListModel()
result.collectiblesListModelVariant = newQVariant(result.collectiblesListModel)
proc load*(self: View) =
self.delegate.viewDidLoad()
@ -316,3 +341,57 @@ QtObject:
proc downloadMessages*(self: View, chatId: string, filePath: string) {.slot.} =
self.delegate.downloadMessages(chatId, filePath)
proc tokenListModel*(self: View): TokenListModel =
result = self.tokenListModel
proc getTokenListModel(self: View): QVariant{.slot.} =
return self.tokenListModelVariant
QtProperty[QVariant] tokenList:
read = getTokenListModel
proc setTokenListItems*(self: View, tokenListItems: seq[TokenListItem]) =
self.tokenListModel.setItems(tokenListItems)
proc collectiblesListModel*(self: View): TokenListModel =
result = self.collectiblesListModel
proc getCollectiblesListModel(self: View): QVariant{.slot.} =
return self.collectiblesListModelVariant
QtProperty[QVariant] collectiblesModel:
read = getCollectiblesListModel
proc setCollectiblesListItems*(self: View, tokenListItems: seq[TokenListItem]) =
self.collectiblesListModel.setItems(tokenListItems)
proc tokenPermissionsModel*(self: View): TokenPermissionsModel =
result = self.tokenPermissionsModel
proc getTokenPermissionsModel(self: View): QVariant{.slot.} =
return self.tokenPermissionsVariant
QtProperty[QVariant] permissionsModel:
read = getTokenPermissionsModel
proc createOrEditCommunityTokenPermission*(self: View, communityId: string, permissionId: string, permissionType: int, tokenCriteriaJson: string, isPrivate: bool) {.slot.} =
self.delegate.createOrEditCommunityTokenPermission(communityId, permissionId, permissionType, tokenCriteriaJson, isPrivate)
proc deleteCommunityTokenPermission*(self: View, communityId: string, permissionId: string) {.slot.} =
self.delegate.deleteCommunityTokenPermission(communityId, permissionId)
proc getAllTokenRequirementsMet*(self: View): bool {.slot.} =
return self.allTokenRequirementsMet
proc allTokenRequirementsMetChanged*(self: View) {.signal.}
proc setAllTokenRequirementsMet*(self: View, value: bool) =
if (value == self.allTokenRequirementsMet):
return
self.allTokenRequirementsMet = value
self.allTokenRequirementsMetChanged()
QtProperty[bool] allTokenRequirementsMet:
read = getAllTokenRequirementsMet
notify = allTokenRequirementsMetChanged

View File

@ -18,6 +18,8 @@ import ../../../app_service/service/mailservers/service as mailservers_service
import ../../../app_service/service/privacy/service as privacy_service
import ../../../app_service/service/node/service as node_service
import ../../../app_service/service/community_tokens/service as community_tokens_service
import ../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../app_service/service/token/service as token_service
import ../shared_models/section_item, io_interface
import ../shared_modules/keycard_popup/io_interface as keycard_shared_module
@ -46,6 +48,8 @@ type
communityTokensService: community_tokens_service.Service
activeSectionId: string
authenticateUserFlowRequestedBy: string
walletAccountService: wallet_account_service.Service
tokenService: token_service.Service
# Forward declaration
proc setActiveSection*(self: Controller, sectionId: string, skipSavingInSettings: bool = false)
@ -64,6 +68,8 @@ proc newController*(delegate: io_interface.AccessInterface,
mailserversService: mailservers_service.Service,
nodeService: node_service.Service,
communityTokensService: community_tokens_service.Service,
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service
):
Controller =
result = Controller()
@ -81,6 +87,8 @@ proc newController*(delegate: io_interface.AccessInterface,
result.nodeService = nodeService
result.mailserversService = mailserversService
result.communityTokensService = communityTokensService
result.walletAccountService = walletAccountService
result.tokenService = tokenService
proc delete*(self: Controller) =
discard
@ -103,6 +111,9 @@ proc init*(self: Controller) =
self.messageService,
self.gifService,
self.mailserversService,
self.walletAccountService,
self.tokenService,
self.communityTokensService
)
self.events.on(SIGNAL_CHATS_LOADING_FAILED) do(e:Args):
@ -135,6 +146,9 @@ proc init*(self: Controller) =
self.messageService,
self.gifService,
self.mailserversService,
self.walletAccountService,
self.tokenService,
self.communityTokensService,
setActive = args.fromUserAction
)
@ -151,6 +165,9 @@ proc init*(self: Controller) =
self.messageService,
self.gifService,
self.mailserversService,
self.walletAccountService,
self.tokenService,
self.communityTokensService,
setActive = args.fromUserAction
)
@ -171,6 +188,9 @@ proc init*(self: Controller) =
self.messageService,
self.gifService,
self.mailserversService,
self.walletAccountService,
self.tokenService,
self.communityTokensService,
setActive = true
)
@ -189,6 +209,9 @@ proc init*(self: Controller) =
self.messageService,
self.gifService,
self.mailserversService,
self.walletAccountService,
self.tokenService,
self.communityTokensService,
setActive = false
)

View File

@ -8,7 +8,10 @@ import ../../../app_service/service/community/service as community_service
import ../../../app_service/service/message/service as message_service
import ../../../app_service/service/gif/service as gif_service
import ../../../app_service/service/mailservers/service as mailservers_service
import ../../../app_service/service/community_tokens/service as token_service
import ../../../app_service/service/community_tokens/service as community_token_service
import ../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../app_service/service/token/service as token_service
import ../../../app_service/service/community_tokens/service as community_tokens_service
from ../../../app_service/common/types import StatusType
import ../../global/app_signals
@ -80,7 +83,10 @@ method onChatsLoaded*(
communityService: community_service.Service,
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service)
mailserversService: mailservers_service.Service,
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service,
communityTokensService: community_tokens_service.Service)
{.base.} =
raise newException(ValueError, "No implementation available")
@ -121,6 +127,9 @@ method communityJoined*(self: AccessInterface, community: CommunityDto, events:
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service,
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service,
communityTokensService: community_tokens_service.Service,
setActive: bool = false,) {.base.} =
raise newException(ValueError, "No implementation available")

View File

@ -157,7 +157,9 @@ proc newModule*[T](
privacyService,
mailserversService,
nodeService,
communityTokensService
communityTokensService,
walletAccountService,
tokenService
)
result.moduleLoaded = false
@ -512,6 +514,9 @@ method onChatsLoaded*[T](
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service,
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service,
communityTokensService: community_tokens_service.Service
) =
var activeSection: SectionItem
var activeSectionId = singletonInstance.localAccountSensitiveSettings.getActiveSection()
@ -531,7 +536,10 @@ method onChatsLoaded*[T](
communityService,
messageService,
gifService,
mailserversService
mailserversService,
walletAccountService,
tokenService,
communityTokensService
)
let channelGroupItem = self.createChannelGroupItem(channelGroup)
self.view.model().addItem(channelGroupItem)
@ -768,6 +776,9 @@ method communityJoined*[T](
messageService: message_service.Service,
gifService: gif_service.Service,
mailserversService: mailservers_service.Service,
walletAccountService: wallet_account_service.Service,
tokenService: token_service.Service,
communityTokensService: community_tokens_service.Service,
setActive: bool = false,
) =
var firstCommunityJoined = false
@ -785,7 +796,10 @@ method communityJoined*[T](
communityService,
messageService,
gifService,
mailserversService
mailserversService,
walletAccountService,
tokenService,
communityTokensService
)
let channelGroup = community.toChannelGroupDto()
self.channelGroupModules[community.id].load(channelGroup, events, settingsService, nodeConfigurationService, contactsService,
@ -960,6 +974,12 @@ method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle
method displayEphemeralNotification*[T](self: Module[T], title: string, subTitle: string, details: NotificationDetails) =
if(details.notificationType == NotificationType.NewMessage or
details.notificationType == NotificationType.NewMessageWithPersonalMention or
details.notificationType == NotificationType.CommunityTokenPermissionCreated or
details.notificationType == NotificationType.CommunityTokenPermissionUpdated or
details.notificationType == NotificationType.CommunityTokenPermissionDeleted or
details.notificationType == NotificationType.CommunityTokenPermissionCreationFailed or
details.notificationType == NotificationType.CommunityTokenPermissionUpdateFailed or
details.notificationType == NotificationType.CommunityTokenPermissionDeletionFailed or
details.notificationType == NotificationType.NewMessageWithGlobalMention):
self.displayEphemeralNotification(title, subTitle, "", false, EphemeralNotificationType.Default.int, "", details)

View File

@ -0,0 +1,53 @@
import strformat
type
TokenCriteriaItem* = object
symbol*: string
name*: string
amount*: float64
`type`*: int
ensPattern*: string
criteriaMet*: bool
proc initTokenCriteriaItem*(
symbol: string,
name: string,
amount: float64,
`type`: int,
ensPattern: string,
criteriaMet: bool
): TokenCriteriaItem =
result.symbol = symbol
result.name = name
result.`type` = `type`
result.ensPattern = ensPattern
result.amount = amount
result.criteriaMet = criteriaMet
proc `$`*(self: TokenCriteriaItem): string =
result = fmt"""TokenCriteriaItem(
symbol: {self.symbol},
name: {self.name},
amount: {self.amount},
type: {self.type},
ensPattern: {self.ensPattern},
criteriaMet: {self.criteriaMet}
]"""
proc getType*(self: TokenCriteriaItem): int =
return self.`type`
proc getSymbol*(self: TokenCriteriaItem): string =
return self.symbol
proc getName*(self: TokenCriteriaItem): string =
return self.name
proc getAmount*(self: TokenCriteriaItem): float64 =
return self.amount
proc getEnsPattern*(self: TokenCriteriaItem): string =
return self.ensPattern
proc getCriteriaMet*(self: TokenCriteriaItem): bool =
return self.criteriaMet

View File

@ -0,0 +1,87 @@
import NimQml, Tables
import token_criteria_item
import ../../../app_service/service/community/dto/community
type
ModelRole {.pure.} = enum
Key = UserRole + 1
Type
Symbol
ShortName
Name
Amount
CriteriaMet
QtObject:
type TokenCriteriaModel* = ref object of QAbstractListModel
items*: seq[TokenCriteriaItem]
proc setup(self: TokenCriteriaModel) =
self.QAbstractListModel.setup
proc delete(self: TokenCriteriaModel) =
self.items = @[]
self.QAbstractListModel.delete
proc newTokenCriteriaModel*(): TokenCriteriaModel =
new(result, delete)
result.setup
method roleNames(self: TokenCriteriaModel): Table[int, string] =
{
ModelRole.Key.int:"key",
ModelRole.Type.int:"type",
ModelRole.Symbol.int:"symbol",
ModelRole.ShortName.int:"shortName",
ModelRole.Name.int:"name",
ModelRole.Amount.int:"amount",
ModelRole.CriteriaMet.int:"available",
}.toTable
proc countChanged(self: TokenCriteriaModel) {.signal.}
proc getCount(self: TokenCriteriaModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
method rowCount(self: TokenCriteriaModel, index: QModelIndex = nil): int =
return self.items.len
method data(self: TokenCriteriaModel, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.items.len:
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Key:
if item.getType() == ord(TokenCriteriaType.ENS):
result = newQVariant(item.getEnsPattern())
else:
result = newQVariant(item.getSymbol())
of ModelRole.Type:
result = newQVariant(item.getType())
of ModelRole.Symbol:
result = newQVariant(item.getSymbol())
of ModelRole.ShortName:
result = newQVariant(item.getSymbol())
of ModelRole.Name:
result = newQVariant(item.getSymbol())
of ModelRole.Amount:
result = newQVariant(item.getAmount())
of ModelRole.CriteriaMet:
result = newQVariant(item.getCriteriaMet())
proc getItems*(self: TokenCriteriaModel): seq[TokenCriteriaItem] =
return self.items
proc addItem*(self: TokenCriteriaModel, item: TokenCriteriaItem) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()

View File

@ -0,0 +1,56 @@
import strformat
type TokenListItemCategory* {.pure.}= enum
Community = 0,
Own = 1,
General = 2
type
TokenListItem* = object
key*: string
name*: string
symbol*: string
color*: string
image*: string
category*: int
proc initTokenListItem*(
key: string,
name: string,
symbol: string,
color: string,
image: string,
category: int
): TokenListItem =
result.key = key
result.symbol = symbol
result.name = name
result.color = color
result.image = image
result.category = category
proc `$`*(self: TokenListItem): string =
result = fmt"""TokenListItem(
key: {self.key},
name: {self.name},
color: {self.color},
symbol: {self.symbol}
]"""
proc getKey*(self: TokenListItem): string =
return self.key
proc getSymbol*(self: TokenListItem): string =
return self.symbol
proc getName*(self: TokenListItem): string =
return self.name
proc getColor*(self: TokenListItem): string =
return self.color
proc getImage*(self: TokenListItem): string =
return self.image
proc getCategory*(self: TokenListItem): int =
return self.category

View File

@ -0,0 +1,92 @@
import NimQml, Tables
import token_list_item
type
ModelRole {.pure.} = enum
Key = UserRole + 1
Name
Shortname
Symbol
Color
Image
Category
QtObject:
type TokenListModel* = ref object of QAbstractListModel
items*: seq[TokenListItem]
proc setup(self: TokenListModel) =
self.QAbstractListModel.setup
proc delete(self: TokenListModel) =
self.items = @[]
self.QAbstractListModel.delete
proc newTokenListModel*(): TokenListModel =
new(result, delete)
result.setup
proc countChanged(self: TokenListModel) {.signal.}
proc getCount(self: TokenListModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
proc setItems*(self: TokenlistModel, items: seq[TokenListItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
proc addItems*(self: TokenlistModel, items: seq[TokenListItem]) =
if(items.len == 0):
return
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
let first = self.items.len
let last = first + items.len - 1
self.beginInsertRows(parentModelIndex, first, last)
self.items.add(items)
self.endInsertRows()
self.countChanged()
method roleNames(self: TokenListModel): Table[int, string] =
{
ModelRole.Key.int:"key",
ModelRole.Name.int:"name",
ModelRole.Symbol.int:"symbol",
ModelRole.Shortname.int:"shortName",
ModelRole.Color.int:"color",
ModelRole.Image.int:"iconSource",
ModelRole.Category.int:"category",
}.toTable
method rowCount(self: TokenlistModel, index: QModelIndex = nil): int =
return self.items.len
method data(self: TokenListModel, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.items.len:
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Key:
result = newQVariant(item.getKey())
of ModelRole.Name:
result = newQVariant(item.getName())
of ModelRole.Symbol:
result = newQVariant(item.getSymbol())
of ModelRole.Shortname:
result = newQVariant(item.getSymbol())
of ModelRole.Color:
result = newQVariant(item.getColor())
of ModelRole.Image:
result = newQVariant(item.getImage())
of ModelRole.Category:
result = newQVariant(item.getCategory())

View File

@ -0,0 +1,25 @@
import strformat
type
TokenPermissionChatListItem* = object
key: string
name: string
proc `$`*(self: TokenPermissionChatListItem): string =
result = fmt"""TokenPermissionChatListItem(
key: {self.key},
name: {self.name},
]"""
proc initTokenPermissionChatListItem*(
key: string,
name: string,
): TokenPermissionChatListItem =
result.key = key
result.name = name
proc getKey*(self: TokenPermissionChatListItem): string =
return self.key
proc getName*(self: TokenPermissionChatListItem): string =
return self.name

View File

@ -0,0 +1,59 @@
import NimQml, Tables
import token_permission_chat_list_item
type
ModelRole {.pure.} = enum
Key = UserRole + 1
Name
QtObject:
type TokenPermissionChatListModel* = ref object of QAbstractListModel
items*: seq[TokenPermissionChatListItem]
proc setup(self: TokenPermissionChatListModel) =
self.QAbstractListModel.setup
proc delete(self: TokenPermissionChatListModel) =
self.items = @[]
self.QAbstractListModel.delete
proc newTokenPermissionChatListModel*(): TokenPermissionChatListModel =
new(result, delete)
result.setup
method roleNames(self: TokenPermissionChatListModel): Table[int, string] =
{
ModelRole.Key.int:"key",
ModelRole.Name.int:"name",
}.toTable
proc countChanged(self: TokenPermissionChatListModel) {.signal.}
proc getCount(self: TokenPermissionChatListModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
method rowCount(self: TokenPermissionChatListModel, index: QModelIndex = nil): int =
return self.items.len
method data(self: TokenPermissionChatListModel, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.items.len:
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Key:
result = newQVariant(item.getKey())
of ModelRole.Name:
result = newQVariant(item.getName())
proc addItem*(self: TokenPermissionChatListModel, item: TokenPermissionChatListItem) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()

View File

@ -0,0 +1,64 @@
import strformat
import ../../../app_service/service/community/dto/community
import ../../../app_service/service/chat/dto/chat
import token_criteria_model
import token_criteria_item
import token_permission_chat_list_model
import token_permission_chat_list_item
type
TokenPermissionItem* = object
id*: string
`type`*: int
tokenCriteria*: TokenCriteriaModel
chatList*: TokenPermissionChatListModel
isPrivate*: bool
tokenCriteriaMet*: bool
proc `$`*(self: TokenPermissionItem): string =
result = fmt"""TokenPermissionItem(
id: {self.id},
type: {self.type},
]"""
proc initTokenPermissionItem*(
id: string,
`type`: int,
tokenCriteria: seq[TokenCriteriaItem],
chatList: seq[TokenPermissionChatListItem],
isPrivate: bool,
tokenCriteriaMet: bool
): TokenPermissionItem =
result.id = id
result.`type` = `type`
result.tokenCriteria = newTokenCriteriaModel()
result.chatList = newTokenPermissionChatListModel()
result.isPrivate = isPrivate
result.tokenCriteriaMet = tokenCriteriaMet
for tcItem in tokenCriteria:
result.tokenCriteria.addItem(tcItem)
for clItem in chatList:
result.chatList.addItem(clItem)
proc addTokenCriteria*(self: TokenPermissionItem, tokenCriteria: TokenCriteriaItem) =
self.tokenCriteria.addItem(tokenCriteria)
proc getId*(self: TokenPermissionItem): string =
return self.id
proc getType*(self: TokenPermissionItem): int =
return self.`type`
proc getTokenCriteria*(self: TokenPermissionItem): TokenCriteriaModel =
return self.tokenCriteria
proc getChatList*(self: TokenPermissionItem): TokenPermissionChatListModel =
return self.chatList
proc getIsPrivate*(self: TokenPermissionItem): bool =
return self.isPrivate
proc getTokenCriteriaMet*(self: TokenPermissionItem): bool =
return self.tokenCriteriaMet

View File

@ -0,0 +1,123 @@
import NimQml, Tables
import token_permission_item
type
ModelRole {.pure.} = enum
Id = UserRole + 1
Key
Type
TokenCriteria
ChatList
IsPrivate
QtObject:
type TokenPermissionsModel* = ref object of QAbstractListModel
items*: seq[TokenPermissionItem]
proc setup(self: TokenPermissionsModel) =
self.QAbstractListModel.setup
proc delete(self: TokenPermissionsModel) =
self.items = @[]
self.QAbstractListModel.delete
proc newTokenPermissionsModel*(): TokenPermissionsModel =
new(result, delete)
result.setup
method roleNames(self: TokenPermissionsModel): Table[int, string] =
{
ModelRole.Id.int:"id",
ModelRole.Key.int:"key",
ModelRole.Type.int:"permissionType",
ModelRole.TokenCriteria.int:"holdingsListModel",
ModelRole.ChatList.int:"channelsModel",
ModelRole.IsPrivate.int:"isPrivate",
}.toTable
proc countChanged(self: TokenPermissionsModel) {.signal.}
proc getCount(self: TokenPermissionsModel): int {.slot.} =
self.items.len
QtProperty[int] count:
read = getCount
notify = countChanged
method rowCount(self: TokenPermissionsModel, index: QModelIndex = nil): int =
return self.items.len
method data(self: TokenPermissionsModel, index: QModelIndex, role: int): QVariant =
if not index.isValid:
return
if index.row < 0 or index.row >= self.items.len:
return
let item = self.items[index.row]
let enumRole = role.ModelRole
case enumRole:
of ModelRole.Id:
result = newQVariant(item.getId())
of ModelRole.Key:
result = newQVariant(item.getId())
of ModelRole.Type:
result = newQVariant(item.getType())
of ModelRole.TokenCriteria:
result = newQVariant(item.getTokenCriteria())
of ModelRole.ChatList:
result = newQVariant(item.getChatList())
of ModelRole.IsPrivate:
result = newQVariant(item.getIsPrivate())
proc addItem*(self: TokenPermissionsModel, item: TokenPermissionItem) =
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginInsertRows(parentModelIndex, self.items.len, self.items.len)
self.items.add(item)
self.endInsertRows()
self.countChanged()
proc setItems*(self: TokenPermissionsModel, items: seq[TokenPermissionItem]) =
self.beginResetModel()
self.items = items
self.endResetModel()
self.countChanged()
proc getItems*(self: TokenPermissionsModel): seq[TokenPermissionItem] =
return self.items
proc findIndexById(self: TokenPermissionsModel, id: string): int =
for i in 0 ..< self.items.len:
if(self.items[i].getId() == id):
return i
return -1
proc removeItemWithId*(self: TokenPermissionsModel, permissionId: string) =
let idx = self.findIndexById(permissionId)
if(idx == -1):
return
let parentModelIndex = newQModelIndex()
defer: parentModelIndex.delete
self.beginRemoveRows(parentModelIndex, idx, idx)
self.items.delete(idx)
self.endRemoveRows()
self.countChanged()
proc updateItem*(self: TokenPermissionsModel, permissionId: string, item: TokenPermissionItem) =
let idx = self.findIndexById(permissionId)
if(idx == -1):
return
self.items[idx].id = permissionId
self.items[idx].`type` = item.`type`
self.items[idx].tokenCriteria = item.tokenCriteria
self.items[idx].isPrivate = item.isPrivate
let index = self.createIndex(idx, 0, nil)
self.dataChanged(index, index, @[
ModelRole.Id.int,
ModelRole.Key.int,
ModelRole.Type.int,
ModelRole.TokenCriteria.int,
ModelRole.IsPrivate.int
])

View File

@ -1,6 +1,6 @@
{.used.}
import json, sequtils, sugar, tables
import json, sequtils, sugar, tables, strutils, json_serialization
import ../../../../backend/communities
include ../../../common/json_utils
@ -29,6 +29,34 @@ type CommunitySettingsDto* = object
type CommunityAdminSettingsDto* = object
pinMessageAllMembersEnabled*: bool
type TokenPermissionType* {.pure.}= enum
Unknown = 0,
BecomeAdmin = 1,
BecomeMember = 2
type TokenCriteriaType* {.pure.}= enum
Unknown = 0,
ERC20 = 1,
ERC721 = 2,
ENS = 3
type TokenCriteriaDto* = object
contractAddresses* {.serializedFieldName("contract_addresses").}: Table[int, string]
`type`* {.serializedFieldName("type").}: TokenCriteriaType
symbol* {.serializedFieldName("symbol").}: string
name* {.serializedFieldName("name").}: string
amount* {.serializedFieldName("amount").}: string
decimals* {.serializedFieldName("decimals").}: int
tokenIds* {.serializedFieldName("tokenIds").}: seq[string]
ensPattern* {.serializedFieldName("ens_pattern").}: string
type CommunityTokenPermissionDto* = object
id*: string
`type`*: TokenPermissionType
tokenCriteria*: seq[TokenCriteriaDto]
chatIds*: seq[string]
isPrivate*: bool
type CommunityDto* = object
id*: string
admin*: bool
@ -60,6 +88,7 @@ type CommunityDto* = object
declinedRequestsToJoin*: seq[CommunityMembershipRequestDto]
encrypted*: bool
canceledRequestsToJoin*: seq[CommunityMembershipRequestDto]
tokenPermissions*: Table[string, CommunityTokenPermissionDto]
type CuratedCommunity* = object
available*: bool
@ -132,6 +161,62 @@ proc toDiscordImportTaskProgress*(jsonObj: JsonNode): DiscordImportTaskProgress
let importError = error.toDiscordImportError()
result.errors.add(importError)
proc toTokenCriteriaDto*(jsonObj: JsonNode): TokenCriteriaDto =
result = TokenCriteriaDto()
discard jsonObj.getProp("amount", result.amount)
discard jsonObj.getProp("decimals", result.decimals)
discard jsonObj.getProp("symbol", result.symbol)
discard jsonObj.getProp("name", result.name)
discard jsonObj.getProp("ens_pattern", result.ensPattern)
var typeInt: int
discard jsonObj.getProp("type", typeInt)
if (typeInt >= ord(low(TokenCriteriaType)) and typeInt <= ord(high(TokenCriteriaType))):
result.`type` = TokenCriteriaType(typeInt)
var contractAddressesObj: JsonNode
if(jsonObj.getProp("contractAddresses", contractAddressesObj) and contractAddressesObj.kind == JObject):
result.contractAddresses = initTable[int, string]()
for chainId, contractAddress in contractAddressesObj:
result.contractAddresses[parseInt(chainId)] = contractAddress.getStr
var tokenIdsObj: JsonNode
if(jsonObj.getProp("tokenIds", tokenIdsObj) and tokenIdsObj.kind == JArray):
for tokenId in tokenIdsObj:
result.tokenIds.add(tokenId.getStr)
# When `toTokenCriteriaDto` is called with data coming from
# the front-end, there's a key field we have to account for
if jsonObj.hasKey("key"):
if result.`type` == TokenCriteriaType.ENS:
discard jsonObj.getProp("key", result.ensPattern)
else:
discard jsonObj.getProp("key", result.symbol)
proc toCommunityTokenPermissionDto*(jsonObj: JsonNode): CommunityTokenPermissionDto =
result = CommunityTokenPermissionDto()
discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("isPrivate", result.isPrivate)
var tokenPermissionTypeInt: int
discard jsonObj.getProp("type", tokenPermissionTypeInt)
if (tokenPermissionTypeInt >= ord(low(TokenPermissionType)) or tokenPermissionTypeInt <= ord(high(TokenPermissionType))):
result.`type` = TokenPermissionType(tokenPermissionTypeInt)
var tokenCriteriaObj: JsonNode
if(jsonObj.getProp("token_criteria", tokenCriteriaObj)):
for tokenCriteria in tokenCriteriaObj:
result.tokenCriteria.add(tokenCriteria.toTokenCriteriaDto)
var chatIdsObj: JsonNode
if(jsonObj.getProp("chatIds", chatIdsObj) and chatIdsObj.kind == JArray):
for chatId in chatIdsObj:
result.chatIds.add(chatId.getStr)
# When `toTokenPermissionDto` is called with data coming from
# the front-end, there's a key field we have to account for
if jsonObj.hasKey("key"):
discard jsonObj.getProp("key", result.id)
proc toCommunityDto*(jsonObj: JsonNode): CommunityDto =
result = CommunityDto()
discard jsonObj.getProp("id", result.id)
@ -165,6 +250,12 @@ proc toCommunityDto*(jsonObj: JsonNode): CommunityDto =
if(jsonObj.getProp("permissions", permissionObj)):
result.permissions = toPermission(permissionObj)
var tokenPermissionsObj: JsonNode
if(jsonObj.getProp("tokenPermissions", tokenPermissionsObj) and tokenPermissionsObj.kind == JObject):
result.tokenPermissions = initTable[string, CommunityTokenPermissionDto]()
for tokenPermissionId, tokenPermission in tokenPermissionsObj:
result.tokenPermissions[tokenPermissionId] = toCommunityTokenPermissionDto(tokenPermission)
var adminSettingsObj: JsonNode
if(jsonObj.getProp("adminSettings", adminSettingsObj)):
result.adminSettings = toCommunityAdminSettingsDto(adminSettingsObj)

View File

@ -1,4 +1,5 @@
import NimQml, Tables, json, sequtils, std/sets, std/algorithm, strformat, strutils, chronicles, json_serialization, sugar
import json_serialization/std/tables as ser_tables
import ./dto/community as community_dto
@ -84,6 +85,15 @@ type
communityId*: string
categoryId*: string
CommunityTokenPermissionArgs* = ref object of Args
communityId*: string
tokenPermission*: CommunityTokenPermissionDto
error*: string
CommunityTokenPermissionRemovedArgs* = ref object of Args
communityId*: string
permissionId*: string
DiscordCategoriesAndChannelsArgs* = ref object of Args
categories*: seq[DiscordCategoryDto]
channels*: seq[DiscordChannelDto]
@ -140,11 +150,20 @@ const SIGNAL_COMMUNITY_HISTORY_ARCHIVES_DOWNLOAD_FINISHED* = "communityHistoryAr
const SIGNAL_DISCORD_CATEGORIES_AND_CHANNELS_EXTRACTED* = "discordCategoriesAndChannelsExtracted"
const SIGNAL_DISCORD_COMMUNITY_IMPORT_FINISHED* = "discordCommunityImportFinished"
const SIGNAL_DISCORD_COMMUNITY_IMPORT_PROGRESS* = "discordCommunityImportProgress"
const SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATED* = "communityTokenPermissionCreated"
const SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_FAILED* = "communityTokenPermissionCreationFailed"
const SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED* = "communityTokenPermissionUpdated"
const SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATE_FAILED* = "communityTokenPermissionUpdateFailed"
const SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETED* = "communityTokenPermissionDeleted"
const SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETION_FAILED* = "communityTokenPermissionDeletionFailed"
const SIGNAL_CURATED_COMMUNITIES_LOADING* = "curatedCommunitiesLoading"
const SIGNAL_CURATED_COMMUNITIES_LOADED* = "curatedCommunitiesLoaded"
const SIGNAL_CURATED_COMMUNITIES_LOADING_FAILED* = "curatedCommunitiesLoadingFailed"
const TOKEN_PERMISSIONS_ADDED = "tokenPermissionsAdded"
const TOKEN_PERMISSIONS_MODIFIED = "tokenPermissionsModified"
QtObject:
type
Service* = ref object of QObject
@ -319,6 +338,14 @@ QtObject:
return idx
return -1
proc findIndexBySymbol(symbol: string, tokenCriteria: seq[TokenCriteriaDto]): int =
var idx = -1
for tc in tokenCriteria:
inc idx
if(tc.symbol == symbol):
return idx
return -1
proc findIndexById(id: string, categories: seq[Category]): int =
var idx = -1
for category in categories:
@ -487,6 +514,49 @@ QtObject:
self.allCommunities[community.id] = community
self.events.emit(SIGNAL_COMMUNITIES_UPDATE, CommunitiesArgs(communities: @[community]))
# tokenPermission was added
if community.tokenPermissions.len > prev_community.tokenPermissions.len:
for id, tokenPermission in community.tokenPermissions:
if not prev_community.tokenPermissions.hasKey(id):
self.allCommunities[community.id].tokenPermissions[id] = tokenPermission
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATED,
CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: tokenPermission))
elif community.tokenPermissions.len < prev_community.tokenPermissions.len:
for id, prvTokenPermission in prev_community.tokenPermissions:
if not community.tokenPermissions.hasKey(id):
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETED,
CommunityTokenPermissionRemovedArgs(communityId: community.id, permissionId: id))
else:
for id, tokenPermission in community.tokenPermissions:
if not prev_community.tokenPermissions.hasKey(id):
continue
let prevTokenPermission = prev_community.tokenPermissions[id]
var permissionUpdated = false
if tokenPermission.tokenCriteria.len != prevTokenPermission.tokenCriteria.len or
tokenPermission.isPrivate != prevTokenPermission.isPrivate or
tokenPermission.`type` != prevTokenPermission.`type`:
permissionUpdated = true
for tc in tokenPermission.tokenCriteria:
let index = findIndexBySymbol(tc.symbol, prevTokenPermission.tokenCriteria)
if index == -1:
continue
let prevTc = prevTokenPermission.tokenCriteria[index]
if tc.amount != prevTc.amount or tc.ensPattern != prevTc.ensPattern:
permissionUpdated = true
break
if permissionUpdated:
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED,
CommunityTokenPermissionArgs(communityId: community.id, tokenPermission: tokenPermission))
if(not self.joinedCommunities.hasKey(community.id)):
if (community.joined and community.isMember):
self.joinedCommunities[community.id] = community
@ -568,6 +638,13 @@ QtObject:
proc getCuratedCommunities*(self: Service): seq[CuratedCommunity] =
return toSeq(self.curatedCommunities.values)
proc getCommunityByIdFromAllCommunities*(self: Service, communityId: string): CommunityDto =
if(not self.allCommunities.hasKey(communityId)):
error "error: requested community doesn't exists", communityId
return
return self.allCommunities[communityId]
proc getCommunityById*(self: Service, communityId: string): CommunityDto =
if(not self.joinedCommunities.hasKey(communityId)):
error "error: requested community doesn't exists", communityId
@ -1557,3 +1634,55 @@ QtObject:
except Exception as e:
error "Error extracting discord channels and categories", msg = e.msg
proc createOrEditCommunityTokenPermission*(self: Service, communityId: string, tokenPermission: CommunityTokenPermissionDto) =
try:
let editing = tokenPermission.id != ""
var response: RpcResponse[JsonNode]
if editing:
response = status_go.editCommunityTokenPermission(communityId, tokenPermission.id, int(tokenPermission.`type`), Json.encode(tokenPermission.tokenCriteria), tokenPermission.isPrivate)
else:
response = status_go.createCommunityTokenPermission(communityId, int(tokenPermission.`type`), Json.encode(tokenPermission.tokenCriteria), tokenPermission.isPrivate)
if response.result != nil and response.result.kind != JNull:
var changesField = TOKEN_PERMISSIONS_ADDED
if editing:
changesField = TOKEN_PERMISSIONS_MODIFIED
for permissionId, permission in response.result["communityChanges"].getElems()[0][changesField].pairs():
let p = permission.toCommunityTokenPermissionDto()
self.allCommunities[communityId].tokenPermissions[permissionId] = p
self.joinedCommunities[communityId].tokenPermissions[permissionId] = p
var signal = SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATED
if editing:
signal = SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATED
self.events.emit(signal, CommunityTokenPermissionArgs(communityId: communityId, tokenPermission: p))
return
var signal = SIGNAL_COMMUNITY_TOKEN_PERMISSION_CREATION_FAILED
if editing:
signal = SIGNAL_COMMUNITY_TOKEN_PERMISSION_UPDATE_FAILED
self.events.emit(signal, CommunityTokenPermissionArgs(communityId: communityId, tokenPermission: tokenPermission))
except Exception as e:
error "Error creating/editing community token permission", msg = e.msg
proc deleteCommunityTokenPermission*(self: Service, communityId: string, permissionId: string) =
try:
let response = status_go.deleteCommunityTokenPermission(communityId, permissionId)
if response.result != nil and response.result.kind != JNull:
for permissionId in response.result["communityChanges"].getElems()[0]["tokenPermissionsRemoved"].getElems():
if self.allCommunities[communityId].tokenPermissions.hasKey(permissionId.getStr()):
self.allCommunities[communityId].tokenPermissions.del(permissionId.getStr())
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETED,
CommunityTokenPermissionRemovedArgs(communityId: communityId, permissionId: permissionId.getStr))
return
var tokenPermission = CommunityTokenPermissionDto()
tokenPermission.id = permissionId
self.events.emit(SIGNAL_COMMUNITY_TOKEN_PERMISSION_DELETION_FAILED,
CommunityTokenPermissionArgs(communityId: communityId, tokenPermission: tokenPermission))
except Exception as e:
error "Error deleting community token permission", msg = e.msg

View File

@ -125,3 +125,10 @@ QtObject:
return parseCommunityTokens(response)
except RpcException:
error "Error getting community tokens", message = getCurrentExceptionMsg()
proc getCommunityTokenBySymbol*(self: Service, communityId: string, symbol: string): CommunityTokenDto =
let communityTokens = self.getCommunityTokens(communityId)
for token in communityTokens:
if token.symbol == symbol:
return token

View File

@ -47,6 +47,8 @@ QtObject:
threadpool: ThreadPool
networkService: network_service.Service
tokens: Table[int, seq[TokenDto]]
tokenList: seq[TokenDto]
tokensToAddressesMap: Table[string, Table[int, string]]
priceCache: TimedCache[float64]
proc updateCachedTokenPrice(self: Service, crypto: string, fiat: string, price: float64)
@ -67,6 +69,8 @@ QtObject:
result.networkService = networkService
result.tokens = initTable[int, seq[TokenDto]]()
result.priceCache = newTimedCache[float64]()
result.tokenList = @[]
result.tokensToAddressesMap = initTable[string, Table[int, string]]()
proc loadData*(self: Service) =
if(not singletonInstance.localAccountSensitiveSettings.getIsWalletEnabled()):
@ -92,6 +96,32 @@ QtObject:
self.tokens[network.chainId] = default_tokens.filter(
proc(x: TokenDto): bool = x.chainId == network.chainId
)
let nativeToken = newTokenDto(
name = network.nativeCurrencyName,
chainId = network.chainId,
address = Address.fromHex("0x0000000000000000000000000000000000000000"),
symbol = network.nativeCurrencySymbol,
decimals = network.nativeCurrencyDecimals,
hasIcon = false,
pegSymbol = ""
)
if not self.tokensToAddressesMap.hasKey(network.nativeCurrencySymbol):
self.tokenList.add(nativeToken)
self.tokensToAddressesMap[nativeToken.symbol] = initTable[int, string]()
if not self.tokensToAddressesMap[nativeToken.symbol].hasKey(nativeToken.chainId):
self.tokensToAddressesMap[nativeToken.symbol][nativeToken.chainId] = $nativeToken.address
for token in default_tokens:
if not self.tokensToAddressesMap.hasKey(token.symbol):
self.tokenList.add(token)
self.tokensToAddressesMap[token.symbol] = initTable[int, string]()
if not self.tokensToAddressesMap[token.symbol].hasKey(token.chainId):
self.tokensToAddressesMap[token.symbol][token.chainId] = $token.address
except Exception as e:
error "Tokens init error", errDesription = e.msg
@ -99,6 +129,16 @@ QtObject:
signalConnect(singletonInstance.localAccountSensitiveSettings, "isWalletEnabledChanged()", self, "onIsWalletEnabledChanged()", 2)
self.loadData()
proc getTokenList*(self: Service): seq[TokenDto] =
return self.tokenList
proc hasContractAddressesForToken*(self: Service, symbol: string): bool =
return self.tokensToAddressesMap.hasKey(symbol)
proc getContractAddressesForToken*(self: Service, symbol: string): Table[int, string] =
if self.hasContractAddressesForToken(symbol):
return self.tokensToAddressesMap[symbol]
proc onIsWalletEnabledChanged*(self: Service) {.slot.} =
self.loadData()

View File

@ -147,6 +147,13 @@ proc getAddress*(self: WalletTokenDto): string =
return ""
proc getTotalBalanceOfSupportedChains*(self: WalletTokenDto): float64 =
var sum = 0.0
for chainId, balanceDto in self.balancesPerChain:
sum += balanceDto.balance
return sum
proc getBalances*(self: WalletTokenDto, chainIds: seq[int]): seq[BalanceDto] =
for chainId in chainIds:
if self.balancesPerChain.hasKey(chainId):

View File

@ -828,4 +828,14 @@ QtObject:
if keycardsState.len == 0:
return
let data = KeycardActivityArgs(success: true)
self.events.emit(SIGNAL_KEYCARDS_SYNCHRONIZED, data)
self.events.emit(SIGNAL_KEYCARDS_SYNCHRONIZED, data)
proc allAccountsTokenBalance*(self: Service, symbol: string): float64 =
var totalTokenBalance = 0.0
for walletAccount in self.getWalletAccounts:
if walletAccount.walletType != WalletTypeWatch:
for token in walletAccount.tokens:
if token.symbol == symbol:
totalTokenBalance += token.getTotalBalanceOfSupportedChains()
return totalTokenBalance

View File

@ -174,6 +174,29 @@ proc requestImportDiscordCommunity*(
"encrypted": encrypted,
}])
proc createCommunityTokenPermission*(communityId: string, permissionType: int, tokenCriteria: string, isPrivate: bool): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("createCommunityTokenPermission".prefix, %*[{
"communityId": communityId,
"type": permissionType,
"tokenCriteria": parseJson(tokenCriteria),
"isPrivate": isPrivate
}])
proc editCommunityTokenPermission*(communityId: string, permissionId: string, permissionType: int, tokenCriteria: string, isPrivate: bool): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("editCommunityTokenPermission".prefix, %*[{
"communityId": communityId,
"permissionId": permissionId,
"type": permissionType,
"tokenCriteria": parseJson(tokenCriteria),
"isPrivate": isPrivate
}])
proc deleteCommunityTokenPermission*(communityId: string, permissionId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("deleteCommunityTokenPermission".prefix, %*[{
"communityId": communityId,
"permissionId": permissionId
}])
proc requestCancelDiscordCommunityImport*(communityId: string): RpcResponse[JsonNode] {.raises: [Exception].} =
result = callPrivateRPC("requestCancelDiscordCommunityImport".prefix, %*[communityId])

View File

@ -2,7 +2,7 @@ import QtQml 2.14
QtObject {
enum Type {
Asset, Collectible, Ens
Unknown, Asset, Collectible, Ens
}
enum Mode {

View File

@ -36,16 +36,16 @@ SettingsPageLayout {
readonly property string newPermissionViewState: "NEW_PERMISSION"
readonly property string permissionsViewState: "PERMISSIONS"
readonly property string editPermissionViewState: "EDIT_PERMISSION"
readonly property bool permissionsExist: store.permissionsModel.count > 0
readonly property bool permissionsExist: permissionsModel.count > 0
signal saveChanges
signal resetChanges
property string permissionKeyToEdit
property ListModel holdingsToEditModel: ListModel {}
property var holdingsToEditModel
property int permissionTypeToEdit: PermissionTypes.Type.None
property ListModel channelsToEditModel: ListModel {}
property var channelsToEditModel
property bool isPrivateToEditValue: false
onPermissionsExistChanged: {
@ -55,7 +55,7 @@ SettingsPageLayout {
}
}
readonly property string initialState: root.store.permissionsModel.count > 0
readonly property string initialState: root.rootStore.permissionsModel.count > 0
? d.permissionsViewState : d.welcomeViewState
function initializeData() {
@ -169,7 +169,7 @@ SettingsPageLayout {
channelsTracker.revision
communityNewPermissionView.dirtyValues.permissionType
communityNewPermissionView.dirtyValues.isPrivate
const model = root.store.permissionsModel
const model = root.rootStore.permissionsModel
const count = model.rowCount()
for (let i = 0; i < count; i++) {
@ -273,7 +273,7 @@ SettingsPageLayout {
store: root.store
function setInitialValuesFromIndex(index) {
const item = ModelUtils.get(root.store.permissionsModel, index)
const item = ModelUtils.get(root.rootStore.permissionsModel, index)
d.holdingsToEditModel = item.holdingsListModel
d.channelsToEditModel = item.channelsListModel
@ -284,7 +284,7 @@ SettingsPageLayout {
onEditPermissionRequested: {
setInitialValuesFromIndex(index)
d.permissionKeyToEdit = ModelUtils.get(
root.store.permissionsModel, index, "key")
root.rootStore.permissionsModel, index, "key")
root.state = d.editPermissionViewState
}
@ -294,7 +294,7 @@ SettingsPageLayout {
}
onRemovePermissionRequested: {
const key = ModelUtils.get(root.store.permissionsModel, index, "key")
const key = ModelUtils.get(root.rootStore.permissionsModel, index, "key")
root.store.removePermission(key)
}
}

View File

@ -7,11 +7,12 @@ import StatusQ.Core.Utils 0.1
QtObject {
id: root
property var mainModuleInst: mainModule
property var communitiesModuleInst: communitiesModule
readonly property bool isOwner: false
property var mintingModuleInst: mintingModule ?? null
property var permissionsModel: ListModel {} // Backend permissions list object model assignment. Please check the current expected data in qml defined in `createPermissions` method
property var permissionConflict: QtObject { // Backend conflicts object model assignment. Now mocked data.
property bool exists: false
property string holdings: qsTr("1 ETH")
@ -20,112 +21,8 @@ QtObject {
}
// TODO: Replace to real data, now dummy model
property var assetsModel: ListModel {
Component.onCompleted: {
append([
{
key: "socks",
iconSource: "qrc:imports/assets/png/tokens/SOCKS.png",
name: "Unisocks",
shortName: "SOCKS",
category: TokenCategories.Category.Community
},
{
key: "zrx",
iconSource: "qrc:imports/assets/png/tokens/ZRX.png",
name: "Ox",
shortName: "ZRX",
category: TokenCategories.Category.Own
},
{
key: "1inch",
iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png",
name: "1inch",
shortName: "ZRX",
category: TokenCategories.Category.Own
},
{
key: "Aave",
iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png",
name: "Aave",
shortName: "AAVE",
category: TokenCategories.Category.Own
},
{
key: "Amp",
iconSource: "qrc:imports/assets/png/tokens/CUSTOM-TOKEN.png",
name: "Amp",
shortName: "AMP",
category: TokenCategories.Category.Own
}
])
}
}
// TODO: Replace to real data, now dummy model
property var collectiblesModel: ListModel {
Component.onCompleted: {
append([
{
key: "Anniversary",
iconSource: "qrc:imports/assets/png/collectibles/Anniversary.png",
name: "Anniversary",
category: TokenCategories.Category.Community
},
{
key: "CryptoKitties",
iconSource: "qrc:imports/assets/png/collectibles/CryptoKitties.png",
name: "CryptoKitties",
category: TokenCategories.Category.Own,
subItems: [
{
key: "Kitty1",
iconSource: "qrc:imports/assets/png/collectibles/Furbeard.png",
imageSource: "qrc:imports/assets/png/collectibles/FurbeardBig.png",
name: "Furbeard"
},
{
key: "Kitty2",
iconSource: "qrc:imports/assets/png/collectibles/Magicat.png",
imageSource: "qrc:imports/assets/png/collectibles/MagicatBig.png",
name: "Magicat"
},
{
key: "Kitty3",
iconSource: "qrc:imports/assets/png/collectibles/HappyMeow.png",
imageSource: "qrc:imports/assets/png/collectibles/HappyMeowBig.png",
name: "Happy Meow"
},
{
key: "Kitty4",
iconSource: "qrc:imports/assets/png/collectibles/Furbeard.png",
imageSource: "qrc:imports/assets/png/collectibles/FurbeardBig.png",
name: "Furbeard-2"
},
{
key: "Kitty5",
iconSource: "qrc:imports/assets/png/collectibles/Magicat.png",
imageSource: "qrc:imports/assets/png/collectibles/MagicatBig.png",
name: "Magicat-3"
}
]
},
{
key: "SuperRare",
iconSource: "qrc:imports/assets/png/collectibles/SuperRare.png",
name: "SuperRare",
category: TokenCategories.Category.Own
},
{
key: "Custom",
iconSource: "qrc:imports/assets/png/collectibles/SNT.png",
name: "Custom Collectible",
category: TokenCategories.Category.General
}
])
}
}
property var assetsModel: chatCommunitySectionModule.tokenList
property var collectiblesModel: chatCommunitySectionModule.collectiblesModel
// TODO: Replace to real data, now dummy model
property var channelsModel: ListModel {
@ -151,29 +48,20 @@ QtObject {
}
function createPermission(holdings, permissionType, isPrivate, channels, index = null) {
// TO BE REPLACED: It shold just be a call to the backend sharing
// `holdings`, `permissions`, `channels` and `isPrivate` properties.
const permissionEntry = d.createPermissionEntry(
holdings, permissionType, isPrivate, channels)
permissionEntry.key = "" + d.keyCounter++
root.permissionsModel.append(permissionEntry)
chatCommunitySectionModule.createOrEditCommunityTokenPermission(root.mainModuleInst.activeSection.id, "", permissionEntry.permissionType, JSON.stringify(permissionEntry.holdingsListModel), permissionEntry.isPrivate)
}
function editPermission(key, holdings, permissionType, channels, isPrivate) {
// TO BE REPLACED: Call to backend
const permissionEntry = d.createPermissionEntry(
holdings, permissionType, isPrivate, channels)
const index = ModelUtils.indexOf(root.permissionsModel, "key", key)
root.permissionsModel.set(index, permissionEntry)
chatCommunitySectionModule.createOrEditCommunityTokenPermission(root.mainModuleInst.activeSection.id, key, permissionEntry.permissionType, JSON.stringify(permissionEntry.holdingsListModel), permissionEntry.isPrivate)
}
function removePermission(key) {
const index = ModelUtils.indexOf(root.permissionsModel, "key", key)
root.permissionsModel.remove(index)
chatCommunitySectionModule.deleteCommunityTokenPermission(root.mainModuleInst.activeSection.id, key)
}
// Minting tokens:

View File

@ -165,6 +165,10 @@ QtObject {
stickersModule: stickersModuleInst
}
property var permissionsModel: chatCommunitySectionModule.permissionsModel
property var assetsModel: chatCommunitySectionModule.tokenList
property var collectiblesModel: chatCommunitySectionModule.collectiblesModel
function sendSticker(channelId, hash, replyTo, pack, url) {
stickersModuleInst.send(channelId, hash, replyTo, pack, url)
}

View File

@ -53,7 +53,7 @@ StatusScrollView {
}
Repeater {
model: root.store.permissionsModel
model: root.rootStore.permissionsModel
delegate: PermissionItem {
Layout.preferredWidth: root.viewWidth

2
vendor/status-go vendored

@ -1 +1 @@
Subproject commit 7c7c3a1f1335ea166b7839217d9ec37b74ad0191
Subproject commit 596660c1106a5d991784a1372ba69a9f1e9b1f7e