diff --git a/src/app/modules/main/activity_center/item.nim b/src/app/modules/main/activity_center/item.nim index 7b80d67dc5..f8bb9a66da 100644 --- a/src/app/modules/main/activity_center/item.nim +++ b/src/app/modules/main/activity_center/item.nim @@ -3,6 +3,7 @@ import ../../shared_models/message_item_qobject import ../../../../app_service/service/activity_center/dto/notification import ../../../../app_service/service/chat/dto/chat import ../../../../app_service/service/contacts/dto/contacts +import ./token_data_item const CONTACT_REQUEST_PENDING_STATE = 1 @@ -23,6 +24,7 @@ type Item* = ref object messageItem: MessageItem repliedMessageItem: MessageItem chatType: ChatType + tokenDataItem: TokenDataItem proc initItem*( id: string, @@ -40,7 +42,8 @@ proc initItem*( accepted: bool, messageItem: MessageItem, repliedMessageItem: MessageItem, - chatType: ChatType + chatType: ChatType, + tokenDataItem: TokenDataItem ): Item = result = Item() result.id = id @@ -59,6 +62,7 @@ proc initItem*( result.messageItem = messageItem result.repliedMessageItem = repliedMessageItem result.chatType = chatType + result.tokenDataItem = tokenDataItem proc `$`*(self: Item): string = result = fmt"""activity_center/Item( @@ -77,6 +81,7 @@ proc `$`*(self: Item): string = accepted: {$self.accepted}, # messageItem: {$self.messageItem}, # repliedMessageItem: {$self.repliedMessageItem}, + tokenData: {$self.tokenDataItem} ]""" proc id*(self: Item): string = @@ -129,3 +134,6 @@ proc messageItem*(self: Item): MessageItem = proc repliedMessageItem*(self: Item): MessageItem = return self.repliedMessageItem + +proc tokenDataItem*(self: Item): TokenDataItem = + return self.tokenDataItem \ No newline at end of file diff --git a/src/app/modules/main/activity_center/model.nim b/src/app/modules/main/activity_center/model.nim index 6c3fa5af31..c6ce6c99f7 100644 --- a/src/app/modules/main/activity_center/model.nim +++ b/src/app/modules/main/activity_center/model.nim @@ -20,6 +20,7 @@ type Author RepliedMessage ChatType + TokenData QtObject: type @@ -87,6 +88,7 @@ QtObject: of NotifRoles.Accepted: result = newQVariant(activityNotificationItem.accepted.bool) of NotifRoles.RepliedMessage: result = newQVariant(activityNotificationItem.repliedMessageItem) of NotifRoles.ChatType: result = newQVariant(activityNotificationItem.chatType.int) + of NotifRoles.TokenData: result = newQVariant(activityNotificationItem.tokenDataItem) method roleNames(self: Model): Table[int, string] = { @@ -106,7 +108,8 @@ QtObject: NotifRoles.Dismissed.int: "dismissed", NotifRoles.Accepted.int: "accepted", NotifRoles.RepliedMessage.int: "repliedMessage", - NotifRoles.ChatType.int: "chatType" + NotifRoles.ChatType.int: "chatType", + NotifRoles.TokenData.int: "tokenData" }.toTable proc markActivityCenterNotificationUnread*(self: Model, notificationId: string) = diff --git a/src/app/modules/main/activity_center/module.nim b/src/app/modules/main/activity_center/module.nim index 67ad7ff293..341a66762c 100644 --- a/src/app/modules/main/activity_center/module.nim +++ b/src/app/modules/main/activity_center/module.nim @@ -1,6 +1,6 @@ import NimQml, Tables, json, stint, sequtils -import ./io_interface, ./view, ./controller +import ./io_interface, ./view, ./controller, ./token_data_item import ../io_interface as delegate_interface import ./item as notification_item import ../../shared_models/message_item as msg_item @@ -175,6 +175,19 @@ method convertToItems*( if (notification.notificationType == ActivityCenterNotificationType.ContactVerification): repliedMessageItem = self.createMessageItemFromDto(notification.replyMessage, communityId, @[]) + var tokenDataItem = token_data_item.newTokenDataItem( + notification.tokenData.chainId, + notification.tokenData.txHash, + notification.tokenData.walletAddress, + notification.tokenData.isFirst, + notification.tokenData.communiyId, + notification.tokenData.amount, + notification.tokenData.name, + notification.tokenData.symbol, + notification.tokenData.imageUrl, + notification.tokenData.tokenType + ) + let chatDetails = self.controller.getChatDetails(notification.chatId) return notification_item.initItem( @@ -193,7 +206,8 @@ method convertToItems*( notification.accepted, messageItem, repliedMessageItem, - chatDetails.chatType + chatDetails.chatType, + tokenDataItem ) ) diff --git a/src/app/modules/main/activity_center/token_data_item.nim b/src/app/modules/main/activity_center/token_data_item.nim new file mode 100644 index 0000000000..c6d9aa3e5c --- /dev/null +++ b/src/app/modules/main/activity_center/token_data_item.nim @@ -0,0 +1,98 @@ +import NimQml, strutils, strformat + +QtObject: + type TokenDataItem* = ref object of QObject + chainId*: int + txHash*: string + walletAddress*: string + isFirst*: bool + communiyId*: string + amount*: string + name*: string + symbol*: string + imageUrl*: string + tokenType*: int + + proc setup(self: TokenDataItem) = + self.QObject.setup + + proc delete*(self: TokenDataItem) = + self.QObject.delete + + proc newTokenDataItem*( + chainId: int, + txHash: string, + walletAddress: string, + isFirst: bool, + communiyId: string, + amount: string, + name: string, + symbol: string, + imageUrl: string, + tokenType: int): TokenDataItem = + new(result, delete) + result.setup + result.chainId = chainId + result.txHash = txHash + result.walletAddress = walletAddress + result.isFirst = isFirst + result.communiyId = communiyId + result.amount = amount + result.name = name + result.symbol = symbol + result.imageUrl = imageUrl + result.tokenType = tokenType + + proc `$`*(self: TokenDataItem): string = + result = fmt""" + chainId: {self.chainId}, + txHash: {self.txHash}, + walletAddress: {self.walletAddress}, + isFirst: {self.isFirst}, + communiyId: {self.communiyId}, + amount: {self.amount}, + name: {self.name}, + symbol: {self.symbol}, + imageUrl: {self.imageUrl}, + tokenType: {self.tokenType} + """ + + proc chainId*(self: TokenDataItem): int {.slot.} = result = self.chainId + QtProperty[int] chainId: + read = chainId + + proc txHash*(self: TokenDataItem): string {.slot.} = result = self.txHash + QtProperty[string] txHash: + read = txHash + + proc walletAddress*(self: TokenDataItem): string {.slot.} = result = self.walletAddress + QtProperty[string] walletAddress: + read = walletAddress + + proc isFirst*(self: TokenDataItem): bool {.slot.} = result = self.isFirst + QtProperty[bool] isFirst: + read = isFirst + + proc communiyId*(self: TokenDataItem): string {.slot.} = result = self.communiyId + QtProperty[string] communiyId: + read = communiyId + + proc amount*(self: TokenDataItem): string {.slot.} = result = self.amount + QtProperty[string] amount: + read = amount + + proc name*(self: TokenDataItem): string {.slot.} = result = self.name + QtProperty[string] name: + read = name + + proc symbol*(self: TokenDataItem): string {.slot.} = result = self.symbol + QtProperty[string] symbol: + read = symbol + + proc imageUrl*(self: TokenDataItem): string {.slot.} = result = self.imageUrl + QtProperty[string] imageUrl: + read = imageUrl + + proc tokenType*(self: TokenDataItem): int {.slot.} = result = self.tokenType + QtProperty[int] tokenType: + read = tokenType \ No newline at end of file diff --git a/src/app/modules/main/communities/tokens/controller.nim b/src/app/modules/main/communities/tokens/controller.nim index 473111c247..de48791472 100644 --- a/src/app/modules/main/communities/tokens/controller.nim +++ b/src/app/modules/main/communities/tokens/controller.nim @@ -88,7 +88,7 @@ proc init*(self: Controller) = self.communityTokensModule.onOwnerTokenReceived(args.communityId, args.communityName, args.chainId, args.contractAddress) self.events.on(SIGNAL_COMMUNITY_TOKEN_RECEIVED) do(e: Args): let args = CommunityTokenReceivedArgs(e) - self.communityTokensModule.onCommunityTokenReceived(args.name, args.image, args.communityId, args.communityName, args.communityColor, $args.balance, args.chainId, args.txHash) + self.communityTokensModule.onCommunityTokenReceived(args.name, args.symbol, args.image, args.communityId, args.communityName, $args.amount, args.chainId, args.txHash, args.isFirst, args.tokenType, args.accountName) self.events.on(SIGNAL_SET_SIGNER_STATUS) do(e: Args): let args = SetSignerArgs(e) self.communityTokensModule.onSetSignerStateChanged(args.communityId, args.chainId, args.transactionHash, args.status) diff --git a/src/app/modules/main/communities/tokens/io_interface.nim b/src/app/modules/main/communities/tokens/io_interface.nim index 130e6e08ff..9e958b14b6 100644 --- a/src/app/modules/main/communities/tokens/io_interface.nim +++ b/src/app/modules/main/communities/tokens/io_interface.nim @@ -96,7 +96,7 @@ method removeCommunityToken*(self: AccessInterface, communityId: string, chainId method onOwnerTokenReceived*(self: AccessInterface, communityId: string, communityName: string, chainId: int, contractAddress: string) {.base.} = raise newException(ValueError, "No implementation available") -method onCommunityTokenReceived*(self: AccessInterface, name: string, image: string, communityId: string, communityName: string, communityColor: string, balance: string, chainId: int, txHash: string) {.base.} = +method onCommunityTokenReceived*(self: AccessInterface, name: string, symbol: string, image: string, communityId: string, communityName: string, balance: string, chainId: int, txHash: string, isFirst: bool, tokenType: int, accountName: string) {.base.} = raise newException(ValueError, "No implementation available") method onSendOwnerTokenStateChanged*(self: AccessInterface, chainId: int, transactionHash: string, tokenName: string, status: ContractTransactionStatus) {.base.} = diff --git a/src/app/modules/main/communities/tokens/module.nim b/src/app/modules/main/communities/tokens/module.nim index b6086af1eb..a39023c8a1 100644 --- a/src/app/modules/main/communities/tokens/module.nim +++ b/src/app/modules/main/communities/tokens/module.nim @@ -334,8 +334,8 @@ method onAirdropStateChanged*(self: Module, communityId: string, tokenName: stri method onOwnerTokenReceived*(self: Module, communityId: string, communityName: string, chainId: int, contractAddress: string) = self.view.emitOwnerTokenReceived(communityId, communityName, chainId, contractAddress) -method onCommunityTokenReceived*(self: Module, name: string, image: string, communityId: string, communityName: string, communityColor: string, balance: string, chainId: int, txHash: string) = - self.view.emitCommunityTokenReceived(name, image, communityId, communityName, communityColor, balance, chainId, txHash) +method onCommunityTokenReceived*(self: Module, name: string, symbol: string, image: string, communityId: string, communityName: string, balance: string, chainId: int, txHash: string, isFirst: bool, tokenType: int, accountName: string) = + self.view.emitCommunityTokenReceived(name, symbol, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, accountName) method onSetSignerStateChanged*(self: Module, communityId: string, chainId: int, transactionHash: string, status: ContractTransactionStatus) = let communityDto = self.controller.getCommunityById(communityId) diff --git a/src/app/modules/main/communities/tokens/view.nim b/src/app/modules/main/communities/tokens/view.nim index 89aae87589..c373300b67 100644 --- a/src/app/modules/main/communities/tokens/view.nim +++ b/src/app/modules/main/communities/tokens/view.nim @@ -55,7 +55,7 @@ QtObject: proc burnFeeUpdated*(self: View, ethCurrency: QVariant, fiatCurrency: QVariant, errorCode: int, responseId: string) {.signal.} proc setSignerFeeUpdated*(self: View, ethCurrency: QVariant, fiatCurrency: QVariant, errorCode: int, responseId: string) {.signal.} proc ownerTokenReceived*(self: View, communityId: string, communityName: string, chainId: int, contractAddress: string) {.signal.} - proc communityTokenReceived*(self: View, name: string, image: string, communityId: string, communityName: string, communityColor: string, balance: string, chainId: int, txHash: string) {.signal.} + proc communityTokenReceived*(self: View, name: string, symbol: string, image: string, communityId: string, communityName: string, balance: string, chainId: int, txHash: string, isFirst: bool, tokenType: int, accountName: string) {.signal.} proc setSignerStateChanged*(self: View, communityId: string, communityName: string, status: int, url: string) {.signal.} proc ownershipNodeLost*(self: View, communityId: string, communityName: string) {.signal.} proc sendOwnerTokenStateChanged*(self: View, tokenName: string, status: int, url: string) {.signal.} @@ -117,8 +117,8 @@ QtObject: proc emitOwnerTokenReceived*(self: View, communityId: string, communityName: string, chainId: int, contractAddress: string) = self.ownerTokenReceived(communityId, communityName, chainId, contractAddress) - proc emitCommunityTokenReceived*(self: View, name: string, image: string, communityId: string, communityName: string, communityColor: string, balance: string, chainId: int, txHash: string) = - self.communityTokenReceived(name, image, communityId, communityName, communityColor, balance, chainId, txHash) + proc emitCommunityTokenReceived*(self: View, name: string, symbol: string, image: string, communityId: string, communityName: string, balance: string, chainId: int, txHash: string, isFirst: bool, tokenType: int, accountName: string) = + self.communityTokenReceived(name, symbol, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, accountName) proc emitSetSignerStateChanged*(self: View, communityId: string, communityName: string, status: int, url: string) = self.setSignerStateChanged(communityId, communityName, status, url) diff --git a/src/app_service/service/activity_center/dto/notification.nim b/src/app_service/service/activity_center/dto/notification.nim index 3a5fbd24b8..e64ab91118 100644 --- a/src/app_service/service/activity_center/dto/notification.nim +++ b/src/app_service/service/activity_center/dto/notification.nim @@ -3,6 +3,7 @@ import json, strformat, strutils, stint, json_serialization import ../../message/dto/message import ../../contacts/dto/contacts +import token_data include ../../../common/json_utils include ../../../common/utils @@ -28,6 +29,7 @@ type ActivityCenterNotificationType* {.pure.}= enum SetSignerDeclined = 17 ShareAccounts = 18 CommunityTokenReceived = 19 + FirstCommunityTokenReceived = 20 type ActivityCenterGroup* {.pure.}= enum All = 0, @@ -70,6 +72,7 @@ type ActivityCenterNotificationDto* = ref object of RootObj dismissed*: bool deleted*: bool accepted*: bool + tokenData*: TokenDataDto proc `$`*(self: ActivityCenterNotificationDto): string = result = fmt"""ActivityCenterNotificationDto( @@ -85,8 +88,9 @@ proc `$`*(self: ActivityCenterNotificationDto): string = dismissed: {$self.dismissed}, deleted: {$self.deleted}, accepted: {$self.accepted}, - message: {self.message} - replyMessage: {self.replyMessage} + message: {self.message}, + replyMessage: {self.replyMessage}, + tokenData: {self.tokenData} )""" proc toActivityCenterNotificationDto*(jsonObj: JsonNode): ActivityCenterNotificationDto = @@ -138,6 +142,9 @@ proc toActivityCenterNotificationDto*(jsonObj: JsonNode): ActivityCenterNotifica for msg in jsonAlbum: result.albumMessages.add(toMessageDto(msg)) + if jsonObj.contains("tokenData") and jsonObj{"tokenData"}.kind != JNull: + result.tokenData = jsonObj["tokenData"].toTokenDataDto() + proc parseActivityCenterNotifications*(rpcResult: JsonNode): (string, seq[ActivityCenterNotificationDto]) = var notifs: seq[ActivityCenterNotificationDto] = @[] if rpcResult{"notifications"}.kind != JNull: @@ -166,7 +173,8 @@ proc activityCenterNotificationTypesByGroup*(group: ActivityCenterGroup) : seq[i ActivityCenterNotificationType.SetSignerDeclined.int, ActivityCenterNotificationType.OwnershipLost.int, ActivityCenterNotificationType.ShareAccounts.int, - ActivityCenterNotificationType.CommunityTokenReceived.int + ActivityCenterNotificationType.CommunityTokenReceived.int, + ActivityCenterNotificationType.FirstCommunityTokenReceived.int ] of ActivityCenterGroup.Mentions: return @[ActivityCenterNotificationType.Mention.int] @@ -190,4 +198,4 @@ proc activityCenterNotificationTypesByGroup*(group: ActivityCenterGroup) : seq[i of ActivityCenterGroup.IdentityVerification: return @[ActivityCenterNotificationType.ContactVerification.int] else: - return @[] + return @[] \ No newline at end of file diff --git a/src/app_service/service/activity_center/dto/token_data.nim b/src/app_service/service/activity_center/dto/token_data.nim new file mode 100644 index 0000000000..a65adddefc --- /dev/null +++ b/src/app_service/service/activity_center/dto/token_data.nim @@ -0,0 +1,52 @@ +{.used.} + +import json, strformat + +include ../../../common/json_utils +include ../../../common/utils + +include backend/collectibles_types + +type TokenDataDto* = object + chainId*: int + collectibleId*: CollectibleUniqueID + txHash*: string + walletAddress*: string + isFirst*: bool + communiyId*: string + amount*: string + name*: string + symbol*: string + imageUrl*: string + tokenType*: int + +proc `$`*(self: TokenDataDto): string = + result = fmt"""TokenDataDto( + chainId: {$self.chainId}, + collectibleId: {self.collectibleId}, + txHash: {self.txHash}, + walletAddress: {self.walletAddress}, + isFirst: {$self.isFirst}, + communiyId: {self.communiyId}, + amount: {self.amount}, + name: {self.name}, + symbol: {self.symbol}, + imageUrl: {self.imageUrl}, + tokenType: {$self.tokenType} + )""" + +proc toTokenDataDto*(jsonObj: JsonNode): TokenDataDto = + result = TokenDataDto() + discard jsonObj.getProp("chainId", result.chainId) + discard jsonObj.getProp("txHash", result.txHash) + discard jsonObj.getProp("walletAddress", result.walletAddress) + discard jsonObj.getProp("isFirst", result.isFirst) + discard jsonObj.getProp("communiyId", result.communiyId) + discard jsonObj.getProp("amount", result.amount) + discard jsonObj.getProp("name", result.name) + discard jsonObj.getProp("symbol", result.symbol) + discard jsonObj.getProp("imageUrl", result.imageUrl) + discard jsonObj.getProp("tokenType", result.tokenType) + + if jsonObj.contains("collectibleId") and jsonObj{"collectibleId"}.kind != JNull: + result.collectibleId = fromJson(jsonObj["collectibleId"], CollectibleUniqueID) \ No newline at end of file diff --git a/src/app_service/service/community_tokens/service.nim b/src/app_service/service/community_tokens/service.nim index ad21832fe1..bd11c9931e 100644 --- a/src/app_service/service/community_tokens/service.nim +++ b/src/app_service/service/community_tokens/service.nim @@ -1,4 +1,4 @@ -import NimQml, Tables, chronicles, json, stint, strutils, sugar, sequtils +import NimQml, Tables, chronicles, json, stint, strutils, sugar, sequtils, strformat import ../../../app/global/global_singleton import ../../../app/core/eventemitter import ../../../app/core/tasks/[qt, threadpool] @@ -174,12 +174,49 @@ type CommunityTokenReceivedArgs* = ref object of Args name*: string image*: string + collectibleId*: CollectibleUniqueID communityId*: string communityName*: string - communityColor*: string chainId*: int - balance*: int + amount*: float64 txHash*: string + symbol*: string + isFirst*: bool + tokenType*: int + accountAddress*: string + accountName*: string + +proc `$`*(self: CommunityTokenReceivedArgs): string = + return fmt"""CommunityTokenReceivedArgs( + name: {self.name} + image: {self.image} + communityId: {self.communityId} + communityName: {self.communityName} + chainId: {self.chainId} + amount: {self.amount} + txHash: {self.txHash} + symbol: {self.symbol} + isFirst: {self.isFirst} + tokenType: {self.tokenType} + accountAddress: {self.accountAddress} + accountName: {self.accountName} + )""" + +proc toTokenData*(self: CommunityTokenReceivedArgs): string = + var dataNode = %* { + "chainId": self.chainId, + "txHash": self.txHash, + "walletAddress": self.accountAddress, + "isFirst": self.isFirst, + "communityId": self.communityId, + "amount": $self.amount, + "name": self.name, + "symbol": self.symbol, + "tokenType": self.tokenType + } + if not self.collectibleId.isNil: + dataNode.add("collectibleId", %self.collectibleId) + return $dataNode type FinaliseOwnershipStatusArgs* = ref object of Args @@ -293,7 +330,7 @@ QtObject: result.tokenOwners1SecTimer.setSingleShot(true) signalConnect(result.tokenOwners1SecTimer, "timeout()", result, "onFetchTempTokenOwners()", 2) - proc processReceivedCollectiblesWalletEvent(self: Service, jsonMessage: string) = + proc processReceivedCollectiblesWalletEvent(self: Service, jsonMessage: string, accounts: seq[string]) = try: let dataMessageJson = parseJson(jsonMessage) let tokenDataPayload = fromJson(dataMessageJson, CommunityCollectiblesReceivedPayload) @@ -318,31 +355,81 @@ QtObject: let response = tokens_backend.registerOwnerTokenReceivedNotification(communityId) checkAndEmitACNotificationsFromResponse(self.events, response.result{"activityCenterNotifications"}) + elif privilegesLevel == PrivilegesLevel.Community: + var collectibleName, collectibleImage, txHash, accountName, accountAddress: string + var isFirst = false + var amount = float64(1.0) + if len(accounts) > 0: + accountAddress = accounts[0] + let res = self.walletAccountService.getAccountByAddress(accountAddress) + accountName = res.name + + if coll.isFirst.isSome(): + isFirst = coll.isFirst.get() + if coll.latestTxHash.isSome(): + txHash = coll.latestTxHash.get() + if coll.receivedAmount.isSome(): + amount = coll.receivedAmount.get() + + if coll.collectibleData.isSome(): + let collData = coll.collectibleData.get() + collectibleName = collData.name + if collData.imageUrl.isSome(): + collectibleImage = collData.imageUrl.get() + + let tokenReceivedArgs = CommunityTokenReceivedArgs( + collectibleId: id, + communityId: communityId, + communityName: communityData.name, + chainId: id.contractID.chainID, + txHash: txHash, + name: collectibleName, + amount: amount, + image: collectibleImage, + isFirst: isFirst, + tokenType: int(TokenType.ERC721), + accountAddress: accountAddress, + accountName: accountName + ) + self.events.emit(SIGNAL_COMMUNITY_TOKEN_RECEIVED, tokenReceivedArgs) + + let response = tokens_backend.registerReceivedCommunityTokenNotification(communityId, isFirst, tokenReceivedArgs.toTokenData()) + checkAndEmitACNotificationsFromResponse(self.events, response.result{"activityCenterNotifications"}) except Exception as e: - error "Error registering owner token received notification", msg=e.msg + error "Error registering collectibles token received notification", msg=e.msg - proc processReceivedCommunityTokenWalletEvent(self: Service, jsonMessage: string) = + proc processReceivedCommunityTokenWalletEvent(self: Service, jsonMessage: string, accounts: seq[string]) = try: let dataMessageJson = parseJson(jsonMessage) let tokenDataPayload = fromJson(dataMessageJson, CommunityTokenReceivedPayload) if len(tokenDataPayload.communityId) == 0: return + var accountName, accountAddress: string + if len(accounts) > 0: + accountAddress = accounts[0] + let res = self.walletAccountService.getAccountByAddress(accountAddress) + accountName = res.name + let communityId = tokenDataPayload.communityId let tokenReceivedArgs = CommunityTokenReceivedArgs( communityId: communityId, communityName: tokenDataPayload.communityName, - communityColor: tokenDataPayload.communityColor, chainId: tokenDataPayload.chainId, txHash: tokenDataPayload.txHash, name: tokenDataPayload.name, - balance: tokenDataPayload.balance, - image: tokenDataPayload.image + amount: tokenDataPayload.amount, + image: tokenDataPayload.image, + symbol: tokenDataPayload.symbol, + isFirst: tokenDataPayload.isFirst, + tokenType: int(TokenType.ERC20), + accountAddress: accountAddress, + accountName: accountName ) self.events.emit(SIGNAL_COMMUNITY_TOKEN_RECEIVED, tokenReceivedArgs) - let response = tokens_backend.registerReceivedCommunityTokenNotification(communityId) + let response = tokens_backend.registerReceivedCommunityTokenNotification(communityId, tokenDataPayload.isFirst, tokenReceivedArgs.toTokenData()) checkAndEmitACNotificationsFromResponse(self.events, response.result{"activityCenterNotifications"}) except Exception as e: error "Error registering community token received notification", msg=e.msg @@ -415,9 +502,9 @@ QtObject: self.events.on(SignalType.Wallet.event) do(e:Args): var data = WalletSignal(e) if data.eventType == collectibles_backend.eventCommunityCollectiblesReceived: - self.processReceivedCollectiblesWalletEvent(data.message) + self.processReceivedCollectiblesWalletEvent(data.message, data.accounts) elif data.eventType == tokens_backend.eventCommunityTokenReceived: - self.processReceivedCommunityTokenWalletEvent(data.message) + self.processReceivedCommunityTokenWalletEvent(data.message, data.accounts) self.events.on(PendingTransactionTypeDto.SetSignerPublicKey.event) do(e: Args): let receivedData = TransactionMinedArgs(e) diff --git a/src/backend/collectibles_types.nim b/src/backend/collectibles_types.nim index 1d401814ce..53d4855e36 100644 --- a/src/backend/collectibles_types.nim +++ b/src/backend/collectibles_types.nim @@ -60,6 +60,9 @@ type collectionData*: Option[CollectionData] communityData*: Option[CommunityData] ownership*: Option[seq[AccountBalance]] + isFirst*: Option[bool] + latestTxHash*: Option[string] + receivedAmount*: Option[float64] # Mirrors services/wallet/thirdparty/collectible_types.go TokenBalance CollectibleBalance* = ref object @@ -297,7 +300,9 @@ proc `$`*(self: Collectible): string = collectibleData:{self.collectibleData}, collectionData:{self.collectionData}, communityData:{self.communityData}, - ownership:{self.ownership} + ownership:{self.ownership}, + isFist:{self.isFirst}, + latestTxHash:{self.latestTxHash} )""" proc fromJson*(t: JsonNode, T: typedesc[Collectible]): Collectible {.inline.} = @@ -324,6 +329,21 @@ proc fromJson*(t: JsonNode, T: typedesc[Collectible]): Collectible {.inline.} = result.ownership = some(getAccountBalances(ownershipNode)) else: result.ownership = none(seq[AccountBalance]) + let isFirstNode = t{"is_first"} + if isFirstNode != nil and isFirstNode.kind != JNull: + result.isFirst = some(isFirstNode.getBool()) + else: + result.isFirst = none(bool) + let latestTxHashNode = t{"latest_tx_hash"} + if latestTxHashNode != nil and latestTxHashNode.kind != JNull: + result.latestTxHash = some(latestTxHashNode.getStr()) + else: + result.latestTxHash = none(string) + let receivedAmountNode = t{"received_amount"} + if receivedAmountNode != nil and receivedAmountNode.kind != JNull: + result.receivedAmount = some(receivedAmountNode.getFloat()) + else: + result.receivedAmount = none(float64) proc toIds(self: seq[Collectible]): seq[CollectibleUniqueID] = result = @[] diff --git a/src/backend/community_tokens.nim b/src/backend/community_tokens.nim index ee0ca48f20..d1d41e689f 100644 --- a/src/backend/community_tokens.nim +++ b/src/backend/community_tokens.nim @@ -150,3 +150,5 @@ proc getOwnerTokenOwnerAddress*(chainId: int, contractAddress: string): RpcRespo rpc(registerReceivedCommunityTokenNotification, "wakuext"): communityId: string + isFirst: bool + toTokenData: string diff --git a/src/backend/community_tokens_types.nim b/src/backend/community_tokens_types.nim index 45cd19dcda..21df931786 100644 --- a/src/backend/community_tokens_types.nim +++ b/src/backend/community_tokens_types.nim @@ -18,8 +18,9 @@ type communityName*: string communityColor*: string communityImage*: string - balance*: int + amount*: float txHash*: string + isFirst*: bool proc fromJson*(t: JsonNode, T: typedesc[CommunityTokenReceivedPayload]): CommunityTokenReceivedPayload {.inline.}= let addressField = "address" @@ -28,7 +29,8 @@ proc fromJson*(t: JsonNode, T: typedesc[CommunityTokenReceivedPayload]): Communi discard t.getProp("image", result.image) discard t.getProp("chainId", result.chainId) discard t.getProp("txHash", result.txHash) - result.balance = t{"balance"}.getInt() + discard t.getProp("isFirst", result.isFirst) + discard t.getProp("amount", result.amount) fromJson(t[addressField], addressField, result.address) diff --git a/storybook/pages/ActivityNotificationCommunityTokenReceivedPage.qml b/storybook/pages/ActivityNotificationCommunityTokenReceivedPage.qml index 7853e31b82..aaabcc5f4b 100644 --- a/storybook/pages/ActivityNotificationCommunityTokenReceivedPage.qml +++ b/storybook/pages/ActivityNotificationCommunityTokenReceivedPage.qml @@ -13,6 +13,9 @@ SplitView { orientation: Qt.Vertical + readonly property int assetType: 1 + readonly property int collectibleType: 2 + Logs { id: logs } Popups { @@ -70,7 +73,7 @@ SplitView { // Notification type related properties: isFirstTokenReceived: true - isAssetType: true + tokenType: root.assetType // Token related properties: tokenAmount: assetMock.amount @@ -97,7 +100,7 @@ SplitView { // Notification type related properties: isFirstTokenReceived: false - isAssetType: true + tokenType: root.assetType // Token related properties: tokenAmount: assetMock.amount @@ -124,7 +127,7 @@ SplitView { // Notification type related properties: isFirstTokenReceived: true - isAssetType: false + tokenType: root.assetType // Token related properties: tokenAmount: collectibleMock.amount @@ -151,7 +154,7 @@ SplitView { // Notification type related properties: isFirstTokenReceived: false - isAssetType: false + tokenType: root.collectibleType // Token related properties: tokenAmount: collectibleMock.amount diff --git a/ui/app/AppLayouts/Chat/stores/RootStore.qml b/ui/app/AppLayouts/Chat/stores/RootStore.qml index 7256022257..28096ef479 100644 --- a/ui/app/AppLayouts/Chat/stores/RootStore.qml +++ b/ui/app/AppLayouts/Chat/stores/RootStore.qml @@ -11,6 +11,7 @@ QtObject { property var contactsStore property var communityTokensStore + property var walletStore property var networkConnectionStore diff --git a/ui/app/mainui/AppMain.qml b/ui/app/mainui/AppMain.qml index 96bd8e2627..1c1aa447b4 100644 --- a/ui/app/mainui/AppMain.qml +++ b/ui/app/mainui/AppMain.qml @@ -1453,6 +1453,7 @@ Item { communityTokensStore: appMain.communityTokensStore emojiReactionsModel: appMain.rootStore.emojiReactionsModel openCreateChat: createChatView.opened + walletStore: WalletStore.RootStore chatCommunitySectionModule: appMain.rootStore.mainModuleInst.getChatSectionModule() } activityCenterStore: appMain.activityCenterStore diff --git a/ui/app/mainui/ToastsManager.qml b/ui/app/mainui/ToastsManager.qml index 98ef668cba..05c7c30670 100644 --- a/ui/app/mainui/ToastsManager.qml +++ b/ui/app/mainui/ToastsManager.qml @@ -129,7 +129,7 @@ QtObject { } // Community token received in the user wallet: - function onCommunityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName, symbol) { + function onCommunityTokenReceived(name, symbol, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName) { // Some error control: if(tokenType !== Constants.TokenType.ERC20 && tokenType !== Constants.TokenType.ERC721) { @@ -137,6 +137,15 @@ QtObject { return } + // Double check if balance is string, then strip ending zeros (e.g. 1.0 -> 1) + if (typeof balance === 'string' && balance.endsWith('0')) { + balance = parseFloat(balance) + if (isNaN(balance)) + balance = "1" + // Cast to Number to drop trailing zeros + balance = Number(balance).toString() + } + var data = { communityId: communityId, communityName: communityName, diff --git a/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml b/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml index 64357bfbb5..c53b136563 100644 --- a/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml +++ b/ui/app/mainui/activitycenter/popups/ActivityCenterPopup.qml @@ -292,6 +292,8 @@ Popup { communityName: community ? community.name : "" communityImage: community ? community.image : "" + store: root.store + filteredIndex: parent.filteredIndex notification: parent.notification onCloseActivityCenter: root.close() diff --git a/ui/app/mainui/activitycenter/views/ActivityNotificationCommunityTokenReceived.qml b/ui/app/mainui/activitycenter/views/ActivityNotificationCommunityTokenReceived.qml index bb17042197..3faf14bec8 100644 --- a/ui/app/mainui/activitycenter/views/ActivityNotificationCommunityTokenReceived.qml +++ b/ui/app/mainui/activitycenter/views/ActivityNotificationCommunityTokenReceived.qml @@ -13,24 +13,41 @@ import AppLayouts.Wallet 1.0 ActivityNotificationBase { id: root + property var community: null + property var store: null + + property var tokenData: root.notification.tokenData + // Community properties: required property string communityId required property string communityName required property string communityImage // Notification type related properties: - property bool isFirstTokenReceived: root.notification.isFirstTokenReceived - property bool isAssetType: root.notification.tokenType === Constants.TokenType.ERC20 + property bool isFirstTokenReceived: root.tokenData.isFirst + readonly property bool isAssetType: root.tokenType === Constants.TokenType.ERC20 // Token related properties: - property string tokenAmount: root.notification.tokenAmount - property string tokenName: root.notification.tokenName - property string tokenSymbol: root.notification.tokenSymbol - property string tokenImage: root.notification.tokenImage + property string tokenAmount: { + let amount = root.tokenData.amount + // Double check if balance is string, then strip ending zeros (e.g. 1.0 -> 1) + if (typeof amount === 'string' && amount.endsWith('0')) { + amount = parseFloat(root.tokenData.amount) + if (isNaN(amount)) + amount = "1" + // Cast to Number to drop trailing zeros + amount = Number(amount).toString() + } + return amount + } + property string tokenName: root.tokenData.name + property string tokenSymbol: root.tokenData.symbol + property string tokenImage: root.tokenData.imageUrl + property int tokenType: root.tokenData.tokenType // Wallet related: - property string walletAccountName: root.notification.walletAccountName - property string txHash: root.notification.txHash + property string walletAccountName: !!root.store ? root.store.walletStore.getNameForWalletAddress(root.tokenData.walletAddress) : "" + property string txHash: root.tokenData.txHash QtObject { id: d @@ -99,7 +116,7 @@ ActivityNotificationBase { root.tokenSymbol, root.tokenName, root.tokenAmount, - root.notification.tokenType, + root.tokenType, root.tokenImage); } else { diff --git a/ui/imports/shared/stores/CommunityTokensStore.qml b/ui/imports/shared/stores/CommunityTokensStore.qml index 276225e322..2da54790a9 100644 --- a/ui/imports/shared/stores/CommunityTokensStore.qml +++ b/ui/imports/shared/stores/CommunityTokensStore.qml @@ -34,12 +34,11 @@ QtObject { signal communityOwnershipDeclined(string communityName) signal sendOwnerTokenStateChanged(string tokenName, int status, string url) signal ownerTokenReceived(string communityId, string communityName) - signal communityTokenReceived(string name, string image, + signal communityTokenReceived(string name, string symbol, string image, string communityId, string communityName, string balance, int chainId, string txHash, bool isFirst, - int tokenType, string walletAccountName, - string symbol) + int tokenType, string walletAccountName) // Minting tokens: function deployCollectible(communityId, collectibleItem) @@ -137,18 +136,8 @@ QtObject { root.ownerTokenReceived(communityId, communityName) } - function onCommunityTokenReceived(name, image, communityId, communityName, communityColor /*Unused, can be removed*/, balance, chainId, txHash/*, isFirst, tokenType, walletAccountName, symbol*/) { - // TODO BACKEND: #13250 - // ** `isFirst` property will be true if it's the first time the user receives a community asset and a community collectible - // ** `tokenType` property will determine if the received minted token is an ERC20 or an ERC720 - // ** `walletAccountName` property will provide the wallet account name where the token was received - // ** `symbol` property will provide the token symbol - - var isFirst = false - var tokenType = Constants.TokenType.ERC20 - var walletAccountName = "Status account" - var symbol = "NON" - root.communityTokenReceived(name, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName, symbol) + function onCommunityTokenReceived(name, symbol, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName) { + root.communityTokenReceived(name, symbol, image, communityId, communityName, balance, chainId, txHash, isFirst, tokenType, walletAccountName) } function onSetSignerStateChanged(communityId, communityName, status, url) {