From 02b17091dd66f94e9615dafbad5d3502ba14d4f2 Mon Sep 17 00:00:00 2001 From: Emil Sawicki Date: Sun, 17 Nov 2024 20:51:35 +0100 Subject: [PATCH] feat: payment request nim input area model --- .../modules/main/activity_center/module.nim | 1 + .../chat_content/input_area/controller.nim | 13 +- .../chat_content/input_area/io_interface.nim | 5 +- .../chat_content/input_area/module.nim | 10 +- .../chat_content/input_area/view.nim | 26 +++- .../chat_content/messages/module.nim | 5 +- .../main/chat_section/chat_content/module.nim | 1 + src/app/modules/main/chat_section/module.nim | 1 + .../modules/shared_models/message_item.nim | 9 ++ .../modules/shared_models/message_model.nim | 4 + .../shared_models/payment_request_model.nim | 111 ++++++++++++++++++ src/app_service/service/chat/async_tasks.nim | 4 + src/app_service/service/chat/service.nim | 7 +- .../service/message/dto/message.nim | 8 +- .../service/message/dto/payment_request.nim | 35 ++++++ .../service/stickers/async_tasks.nim | 1 + src/backend/chat.nim | 4 + test/nim/message_model_test.nim | 1 + 18 files changed, 231 insertions(+), 15 deletions(-) create mode 100644 src/app/modules/shared_models/payment_request_model.nim create mode 100644 src/app_service/service/message/dto/payment_request.nim diff --git a/src/app/modules/main/activity_center/module.nim b/src/app/modules/main/activity_center/module.nim index 513889f7ffd..45f4c67b81f 100644 --- a/src/app/modules/main/activity_center/module.nim +++ b/src/app/modules/main/activity_center/module.nim @@ -160,6 +160,7 @@ proc createMessageItemFromDto(self: Module, message: MessageDto, communityId: st message.albumImagesCount, message.bridgeMessage, message.quotedMessage.bridgeMessage, + message.paymentRequests )) method convertToItems*( diff --git a/src/app/modules/main/chat_section/chat_content/input_area/controller.nim b/src/app/modules/main/chat_section/chat_content/input_area/controller.nim index d0843a34aab..2b2f0d7bcb4 100644 --- a/src/app/modules/main/chat_section/chat_content/input_area/controller.nim +++ b/src/app/modules/main/chat_section/chat_content/input_area/controller.nim @@ -7,6 +7,7 @@ import ../../../../../../app_service/service/contacts/service as contact_service import ../../../../../../app_service/service/community/service as community_service import ../../../../../../app_service/service/chat/service as chat_service import ../../../../../../app_service/service/message/dto/link_preview +import ../../../../../../app_service/service/message/dto/payment_request import ../../../../../../app_service/service/message/dto/urls_unfurling_plan import ../../../../../../app_service/service/settings/dto/settings import ../../../../../core/eventemitter @@ -128,7 +129,8 @@ proc sendImages*(self: Controller, msg: string, replyTo: string, preferredUsername: string = "", - linkPreviews: seq[LinkPreview]) = + linkPreviews: seq[LinkPreview], + paymentRequests: seq[PaymentRequest]) = self.resetLinkPreviews() self.chatService.asyncSendImages( self.chatId, @@ -136,7 +138,8 @@ proc sendImages*(self: Controller, msg, replyTo, preferredUsername, - linkPreviews + linkPreviews, + paymentRequests ) proc sendChatMessage*(self: Controller, @@ -144,14 +147,16 @@ proc sendChatMessage*(self: Controller, replyTo: string, contentType: int, preferredUsername: string = "", - linkPreviews: seq[LinkPreview]) = + linkPreviews: seq[LinkPreview], + paymentRequests: seq[PaymentRequest]) = self.resetLinkPreviews() self.chatService.asyncSendChatMessage(self.chatId, msg, replyTo, contentType, preferredUsername, - linkPreviews + linkPreviews, + paymentRequests ) proc requestAddressForTransaction*(self: Controller, fromAddress: string, amount: string, tokenAddress: string) = diff --git a/src/app/modules/main/chat_section/chat_content/input_area/io_interface.nim b/src/app/modules/main/chat_section/chat_content/input_area/io_interface.nim index 0f614d73924..b793158d6a4 100644 --- a/src/app/modules/main/chat_section/chat_content/input_area/io_interface.nim +++ b/src/app/modules/main/chat_section/chat_content/input_area/io_interface.nim @@ -2,6 +2,7 @@ import NimQml, tables import ../../../../../../app_service/service/gif/dto import ../../../../../../app_service/service/message/dto/link_preview +import ../../../../../../app_service/service/message/dto/payment_request import ../../../../../../app_service/service/contacts/dto/contact_details type @@ -19,10 +20,10 @@ method isLoaded*(self: AccessInterface): bool {.base.} = method getModuleAsVariant*(self: AccessInterface): QVariant {.base.} = raise newException(ValueError, "No implementation available") -method sendChatMessage*(self: AccessInterface, msg: string, replyTo: string, contentType: int, linkPreviews: seq[LinkPreview]) {.base.} = +method sendChatMessage*(self: AccessInterface, msg: string, replyTo: string, contentType: int, linkPreviews: seq[LinkPreview], paymentRequests: seq[PaymentRequest]) {.base.} = raise newException(ValueError, "No implementation available") -method sendImages*(self: AccessInterface, imagePathsJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview]) {.base.} = +method sendImages*(self: AccessInterface, imagePathsJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview], paymentRequests: seq[PaymentRequest]) {.base.} = raise newException(ValueError, "No implementation available") method requestAddressForTransaction*(self: AccessInterface, fromAddress: string, amount: string, tokenAddress: string) {.base.} = diff --git a/src/app/modules/main/chat_section/chat_content/input_area/module.nim b/src/app/modules/main/chat_section/chat_content/input_area/module.nim index 51a4a2001d6..a8d71ebe951 100644 --- a/src/app/modules/main/chat_section/chat_content/input_area/module.nim +++ b/src/app/modules/main/chat_section/chat_content/input_area/module.nim @@ -8,6 +8,7 @@ import ../../../../../core/eventemitter import ../../../../../../app_service/service/settings/service as settings_service import ../../../../../../app_service/service/message/service as message_service import ../../../../../../app_service/service/message/dto/link_preview +import ../../../../../../app_service/service/message/dto/payment_request import ../../../../../../app_service/service/chat/service as chat_service import ../../../../../../app_service/service/community/service as community_service import ../../../../../../app_service/service/contacts/service as contact_service @@ -65,17 +66,18 @@ method getModuleAsVariant*(self: Module): QVariant = proc getChatId*(self: Module): string = return self.controller.getChatId() -method sendImages*(self: Module, imagePathsAndDataJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview]) = - self.controller.sendImages(imagePathsAndDataJson, msg, replyTo, singletonInstance.userProfile.getPreferredName(), linkPreviews) +method sendImages*(self: Module, imagePathsAndDataJson: string, msg: string, replyTo: string, linkPreviews: seq[LinkPreview], paymentRequests: seq[PaymentRequest]) = + self.controller.sendImages(imagePathsAndDataJson, msg, replyTo, singletonInstance.userProfile.getPreferredName(), linkPreviews, paymentRequests) method sendChatMessage*( self: Module, msg: string, replyTo: string, contentType: int, - linkPreviews: seq[LinkPreview]) = + linkPreviews: seq[LinkPreview], + paymentRequests: seq[PaymentRequest]) = self.controller.sendChatMessage(msg, replyTo, contentType, - singletonInstance.userProfile.getPreferredName(), linkPreviews) + singletonInstance.userProfile.getPreferredName(), linkPreviews, paymentRequests) method requestAddressForTransaction*(self: Module, fromAddress: string, amount: string, tokenAddress: string) = self.controller.requestAddressForTransaction(fromAddress, amount, tokenAddress) diff --git a/src/app/modules/main/chat_section/chat_content/input_area/view.nim b/src/app/modules/main/chat_section/chat_content/input_area/view.nim index 004698836f8..35239897173 100644 --- a/src/app/modules/main/chat_section/chat_content/input_area/view.nim +++ b/src/app/modules/main/chat_section/chat_content/input_area/view.nim @@ -3,6 +3,7 @@ import ./io_interface import ./preserved_properties import ./urls_model import ../../../../../../app/modules/shared_models/link_preview_model as link_preview_model +import ../../../../../../app/modules/shared_models/payment_request_model as payment_request_model import ../../../../../../app/modules/shared_models/emoji_reactions_model as emoji_reactions_model QtObject: @@ -13,6 +14,8 @@ QtObject: preservedPropertiesVariant: QVariant linkPreviewModel: link_preview_model.Model linkPreviewModelVariant: QVariant + paymentRequestModel: payment_request_model.Model + paymentRequestModelVariant: QVariant urlsModel: urls_model.Model urlsModelVariant: QVariant sendingInProgress: bool @@ -28,6 +31,8 @@ QtObject: self.preservedProperties.delete self.linkPreviewModelVariant.delete self.linkPreviewModel.delete + self.paymentRequestModelVariant.delete + self.paymentRequestModel.delete self.urlsModelVariant.delete self.urlsModel.delete self.emojiReactionsModel.delete @@ -41,6 +46,8 @@ QtObject: result.preservedPropertiesVariant = newQVariant(result.preservedProperties) result.linkPreviewModel = newLinkPreviewModel() result.linkPreviewModelVariant = newQVariant(result.linkPreviewModel) + result.paymentRequestModel = newPaymentRequestModel() + result.paymentRequestModelVariant = newQVariant(result.paymentRequestModel) result.urlsModel = newUrlsModel() result.urlsModelVariant = newQVariant(result.urlsModel) result.askToEnableLinkPreview = false @@ -58,13 +65,13 @@ QtObject: # FIXME: Update this when `setText` is async. self.setSendingInProgress(true) self.delegate.setText(msg, false) - self.delegate.sendChatMessage(msg, replyTo, contentType, self.linkPreviewModel.getUnfuledLinkPreviews()) + self.delegate.sendChatMessage(msg, replyTo, contentType, self.linkPreviewModel.getUnfuledLinkPreviews(), self.payment_request_model.getPaymentRequests()) proc sendImages*(self: View, imagePathsAndDataJson: string, msg: string, replyTo: string) {.slot.} = # FIXME: Update this when `setText` is async. self.setSendingInProgress(true) self.delegate.setText(msg, false) - self.delegate.sendImages(imagePathsAndDataJson, msg, replyTo, self.linkPreviewModel.getUnfuledLinkPreviews()) + self.delegate.sendImages(imagePathsAndDataJson, msg, replyTo, self.linkPreviewModel.getUnfuledLinkPreviews(), self.payment_request_model.getPaymentRequests()) proc acceptAddressRequest*(self: View, messageId: string , address: string) {.slot.} = self.delegate.acceptRequestAddressForTransaction(messageId, address) @@ -90,6 +97,12 @@ QtObject: QtProperty[QVariant] preservedProperties: read = getPreservedProperties + proc getPaymentRequestModel*(self: View): QVariant {.slot.} = + return self.paymentRequestModelVariant + + QtProperty[QVariant] paymentRequestModel: + read = getPaymentRequestModel + proc getLinkPreviewModel*(self: View): QVariant {.slot.} = return self.linkPreviewModelVariant @@ -149,6 +162,15 @@ QtObject: proc removeLinkPreviewData*(self: View, index: int) {.slot.} = self.linkPreviewModel.removePreviewData(index) + proc addPaymentRequest*(self: View, receiver: string, amount: string, symbol: string, chainId: int) {.slot.} = + self.paymentRequestModel.addPaymentRequest(receiver, amount, symbol, chainId) + + proc removePaymentRequestPreviewData*(self: View, index: int) {.slot.} = + self.paymentRequestModel.removeItemWithIndex(index) + + proc removeAllPaymentRequestPreviewData(self: View) {.slot.} = + self.paymentRequestModel.clearItems() + proc urlsModelChanged(self: View) {.signal.} proc getUrlsModel*(self: View): QVariant {.slot.} = return self.urlsModelVariant diff --git a/src/app/modules/main/chat_section/chat_content/messages/module.nim b/src/app/modules/main/chat_section/chat_content/messages/module.nim index eb500cac346..ebfbe2b402e 100644 --- a/src/app/modules/main/chat_section/chat_content/messages/module.nim +++ b/src/app/modules/main/chat_section/chat_content/messages/module.nim @@ -208,7 +208,8 @@ proc createMessageItemsFromMessageDtos(self: Module, messages: seq[MessageDto], if (len(message.albumId) == 0): @[] else: @[message.id], message.albumImagesCount, message.bridgeMessage, - message.quotedMessage.bridgeMessage + message.quotedMessage.bridgeMessage, + message.paymentRequests ) self.updateLinkPreviewsContacts(item, requestFromMailserver = item.seen) @@ -290,6 +291,7 @@ proc createFetchMoreMessagesItem(self: Module): Item = albumImagesCount = 0, BridgeMessage(), BridgeMessage(), + paymentRequests = @[] ) proc createChatIdentifierItem(self: Module): Item = @@ -358,6 +360,7 @@ proc createChatIdentifierItem(self: Module): Item = albumImagesCount = 0, bridgeMessage = BridgeMessage(), quotedBridgeMessage = BridgeMessage(), + paymentRequests = @[] ) proc checkIfMessageLoadedAndScroll(self: Module) = diff --git a/src/app/modules/main/chat_section/chat_content/module.nim b/src/app/modules/main/chat_section/chat_content/module.nim index 39e6002eee2..5a889d64259 100644 --- a/src/app/modules/main/chat_section/chat_content/module.nim +++ b/src/app/modules/main/chat_section/chat_content/module.nim @@ -235,6 +235,7 @@ proc buildPinnedMessageItem(self: Module, message: MessageDto, actionInitiatedBy message.albumImagesCount, message.bridgeMessage, message.quotedMessage.bridgeMessage, + message.paymentRequests ) item.pinned = true item.pinnedBy = actionInitiatedBy diff --git a/src/app/modules/main/chat_section/module.nim b/src/app/modules/main/chat_section/module.nim index b0cb1f49c17..34c0d8d6ff0 100644 --- a/src/app/modules/main/chat_section/module.nim +++ b/src/app/modules/main/chat_section/module.nim @@ -216,6 +216,7 @@ proc buildCommunityMemberMessageItem(self: Module, message: MessageDto): member_ message.albumImagesCount, message.bridgeMessage, message.quotedMessage.bridgeMessage, + message.paymentRequests ) method delete*(self: Module) = diff --git a/src/app/modules/shared_models/message_item.nim b/src/app/modules/shared_models/message_item.nim index 2ced0adb1ee..bbaff6eac14 100644 --- a/src/app/modules/shared_models/message_item.nim +++ b/src/app/modules/shared_models/message_item.nim @@ -3,7 +3,9 @@ import ../../../app_service/common/types import ../../../app_service/service/contacts/dto/contact_details import ../../../app_service/service/message/dto/message import ../../../app_service/service/message/dto/link_preview +import ../../../app_service/service/message/dto/payment_request import ./link_preview_model as link_preview_model +import ./payment_request_model as payment_request_model import ./emoji_reactions_model as emoji_reactions_model export types.ContentType @@ -72,6 +74,7 @@ type albumMessageIds: seq[string] albumImagesCount: int bridgeName: string + paymentRequestModel: payment_request_model.Model proc initItem*( id, @@ -126,6 +129,7 @@ proc initItem*( albumImagesCount: int, bridgeMessage: BridgeMessage, quotedBridgeMessage: BridgeMessage, + paymentRequests: seq[PaymentRequest], ): Item = result = Item() result.id = id @@ -184,6 +188,7 @@ proc initItem*( result.albumMessageImages = albumMessageImages result.albumMessageIds = albumMessageIds result.albumImagesCount = albumImagesCount + result.paymentRequestModel = newPaymentRequestModel(paymentRequests) if quotedMessageContentType == ContentType.DiscordMessage: result.quotedMessageAuthorDisplayName = quotedMessageDiscordMessage.author.name @@ -281,6 +286,7 @@ proc initNewMessagesMarkerItem*(clock, timestamp: int64): Item = albumImagesCount = 0, bridgeMessage = BridgeMessage(), quotedBridgeMessage = BridgeMessage(), + paymentRequests = @[], ) proc `$`*(self: Item): string = @@ -508,6 +514,9 @@ proc `links=`*(self: Item, links: seq[string]) {.inline.} = proc linkPreviewModel*(self: Item): link_preview_model.Model {.inline.} = return self.linkPreviewModel +proc paymentRequestModel*(self: Item): payment_request_model.Model {.inline.} = + return self.paymentRequestModel + proc emojiReactionsModel*(self: Item): emoji_reactions_model.Model {.inline.} = return self.emojiReactionsModel diff --git a/src/app/modules/shared_models/message_model.nim b/src/app/modules/shared_models/message_model.nim index 5aea49fb7c6..e012195133a 100644 --- a/src/app/modules/shared_models/message_model.nim +++ b/src/app/modules/shared_models/message_model.nim @@ -75,6 +75,7 @@ type AlbumMessageImages AlbumImagesCount BridgeName + PaymentRequestModel QtObject: type @@ -182,6 +183,7 @@ QtObject: ModelRole.AlbumMessageImages.int: "albumMessageImages", ModelRole.AlbumImagesCount.int: "albumImagesCount", ModelRole.BridgeName.int: "bridgeName", + ModelRole.PaymentRequestModel.int: "paymentRequestModel", }.toTable method data(self: Model, index: QModelIndex, role: int): QVariant = @@ -358,6 +360,8 @@ QtObject: result = newQVariant(item.albumImagesCount) of ModelRole.BridgeName: result = newQVariant(item.bridgeName) + of ModelRole.PaymentRequestModel: + result = newQVariant(item.paymentRequestModel) proc updateItemAtIndex(self: Model, index: int) = let ind = self.createIndex(index, 0, nil) diff --git a/src/app/modules/shared_models/payment_request_model.nim b/src/app/modules/shared_models/payment_request_model.nim new file mode 100644 index 00000000000..121d83f6176 --- /dev/null +++ b/src/app/modules/shared_models/payment_request_model.nim @@ -0,0 +1,111 @@ +import NimQml, stew/shims/strformat, tables, sequtils +import ../../../app_service/service/message/dto/payment_request + +type + ModelRole {.pure.} = enum + Symbol = UserRole + 1 + Amount + ReceiverAddress + ChainId + +QtObject: + type + Model* = ref object of QAbstractListModel + items: seq[PaymentRequest] + + proc delete*(self: Model) = + self.items = @[] + self.QAbstractListModel.delete + + proc setup(self: Model) = + self.QAbstractListModel.setup + + proc newPaymentRequestModel*(paymentRequests: seq[PaymentRequest] = @[]): Model = + new(result, delete) + result.setup + result.items = paymentRequests + + proc newModel*(): Model = + new(result, delete) + result.setup + + proc `$`*(self: Model): string = + for i in 0 ..< self.items.len: + result &= fmt""" + [{i}]:({$self.items[i]}) + """ + + proc getPaymentRequests*(self: Model): seq[PaymentRequest] = + return self.items + + proc countChanged(self: Model) {.signal.} + + proc getCount*(self: Model): int {.slot.} = + self.items.len + + QtProperty[int] count: + read = getCount + notify = countChanged + + method rowCount(self: Model, index: QModelIndex = nil): int = + return self.items.len + + method roleNames(self: Model): Table[int, string] = + { + ModelRole.Symbol.int: "symbol", + ModelRole.Amount.int: "amount", + ModelRole.ReceiverAddress.int: "receiver", + ModelRole.ChainId.int: "chainId", + }.toTable + + method data(self: Model, 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.Symbol: + result = newQVariant(item.symbol) + of ModelRole.Amount: + result = newQVariant(item.amount) + of ModelRole.ReceiverAddress: + result = newQVariant(item.receiver) + of ModelRole.ChainId: + result = newQVariant(item.chainId) + else: + result = newQVariant() + + proc removeItemWithIndex*(self: Model, ind: int) = + if(ind < 0 or ind >= self.items.len): + return + + let parentModelIndex = newQModelIndex() + defer: parentModelIndex.delete + + self.beginRemoveRows(parentModelIndex, ind, ind) + self.items.delete(ind) + self.endRemoveRows() + + proc insertItem(self: Model, paymentRequest: PaymentRequest) = + let parentModelIndex = newQModelIndex() + defer: parentModelIndex.delete + + self.beginInsertRows(parentModelIndex, self.items.len, self.items.len) + self.items.add(paymentRequest) + self.endInsertRows() + self.countChanged() + + proc addPaymentRequest*(self: Model, receiver: string, amount: string, symbol: string, chainId: int) = + let paymentRequest = newPaymentRequest(receiver, amount, symbol, chainId) + self.insertItem(paymentRequest) + + proc clearItems*(self: Model) = + self.beginResetModel() + self.items = @[] + self.endResetModel() + self.countChanged() \ No newline at end of file diff --git a/src/app_service/service/chat/async_tasks.nim b/src/app_service/service/chat/async_tasks.nim index d181febd9d9..9261fdf3022 100644 --- a/src/app_service/service/chat/async_tasks.nim +++ b/src/app_service/service/chat/async_tasks.nim @@ -73,6 +73,7 @@ type communityId: string standardLinkPreviews: JsonNode statusLinkPreviews: JsonNode + paymentRequests: JsonNode const asyncSendMessageTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[AsyncSendMessageTaskArg](argEncoded) @@ -86,6 +87,7 @@ const asyncSendMessageTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} arg.preferredUsername, arg.standardLinkPreviews, arg.statusLinkPreviews, + arg.paymentRequests, arg.communityId) arg.finish(%* { @@ -109,6 +111,7 @@ type preferredUsername: string standardLinkPreviews: JsonNode statusLinkPreviews: JsonNode + paymentRequests: JsonNode const asyncSendImagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = let arg = decode[AsyncSendImagesTaskArg](argEncoded) @@ -129,6 +132,7 @@ const asyncSendImagesTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} = arg.preferredUsername, arg.standardLinkPreviews, arg.statusLinkPreviews, + arg.paymentRequests ) for imagePath in imagePaths: diff --git a/src/app_service/service/chat/service.nim b/src/app_service/service/chat/service.nim index e904e746ba2..3ec1d2b8e7a 100644 --- a/src/app_service/service/chat/service.nim +++ b/src/app_service/service/chat/service.nim @@ -5,6 +5,7 @@ import ../../../app/core/tasks/[qt, threadpool] import ./dto/chat as chat_dto import ../message/dto/message as message_dto import ../message/dto/[link_preview, standard_link_preview, status_link_preview] +import ../message/dto/payment_request import ../activity_center/dto/notification as notification_dto import ../community/dto/community as community_dto import ../contacts/service as contact_service @@ -430,7 +431,8 @@ QtObject: msg: string, replyTo: string, preferredUsername: string = "", - linkPreviews: seq[LinkPreview] = @[]) = + linkPreviews: seq[LinkPreview] = @[], + paymentRequests: seq[PaymentRequest] = @[]) = try: let (standardLinkPreviews, statusLinkPreviews) = extractLinkPreviewsLists(linkPreviews) @@ -446,6 +448,7 @@ QtObject: preferredUsername: preferredUsername, standardLinkPreviews: %standardLinkPreviews, statusLinkPreviews: %statusLinkPreviews, + paymentRequests: %paymentRequests, ) self.threadpool.start(arg) @@ -476,6 +479,7 @@ QtObject: contentType: int, preferredUsername: string = "", linkPreviews: seq[LinkPreview] = @[], + paymentRequests: seq[PaymentRequest] = @[], communityId: string = "") = try: let allKnownContacts = self.contactService.getContactsByGroup(ContactsGroup.AllKnownContacts) @@ -495,6 +499,7 @@ QtObject: communityId: communityId, # Only send a community ID for the community invites standardLinkPreviews: %standardLinkPreviews, statusLinkPreviews: %statusLinkPreviews, + paymentRequests: %paymentRequests, ) self.threadpool.start(arg) diff --git a/src/app_service/service/message/dto/message.nim b/src/app_service/service/message/dto/message.nim index 68195eae38b..905277d8051 100644 --- a/src/app_service/service/message/dto/message.nim +++ b/src/app_service/service/message/dto/message.nim @@ -2,7 +2,7 @@ import json, strutils, chronicles import ../../../common/types -import link_preview +import link_preview, payment_request include ../../../common/json_utils @@ -133,6 +133,7 @@ type MessageDto* = object transactionParameters*: TransactionParameters mentioned*: bool replied*: bool + paymentRequests*: seq[PaymentRequest] proc toParsedText*(jsonObj: JsonNode): ParsedText = result = ParsedText() @@ -314,6 +315,11 @@ proc toMessageDto*(jsonObj: JsonNode): MessageDto = for element in statusLinkPreviewsArr.getElems(): result.linkPreviews.add(element.toLinkPreview(false)) + var paymentRequestsArr: JsonNode + if jsonObj.getProp("paymentRequests", paymentRequestsArr): + for element in paymentRequestsArr.getElems(): + result.paymentRequests.add(element.toPaymentRequest()) + var parsedTextArr: JsonNode if(jsonObj.getProp("parsedText", parsedTextArr) and parsedTextArr.kind == JArray): for pTextObj in parsedTextArr: diff --git a/src/app_service/service/message/dto/payment_request.nim b/src/app_service/service/message/dto/payment_request.nim new file mode 100644 index 00000000000..349c7a9eb70 --- /dev/null +++ b/src/app_service/service/message/dto/payment_request.nim @@ -0,0 +1,35 @@ +import json, chronicles +import stew/shims/strformat +include ../../../common/json_utils + +type PaymentRequest* = ref object + receiver*: string + amount*: string + symbol*: string + chainId*: int + +proc newPaymentRequest*(receiver: string, amount: string, symbol: string, chainId: int): PaymentRequest = + result = PaymentRequest(receiver: receiver, amount: amount, symbol: symbol, chainId: chainId) + +proc toPaymentRequest*(jsonObj: JsonNode): PaymentRequest = + result = PaymentRequest() + discard jsonObj.getProp("receiver", result.receiver) + discard jsonObj.getProp("amount", result.amount) + discard jsonObj.getProp("symbol", result.symbol) + discard jsonObj.getProp("chainId", result.chainId) + +proc `%`*(self: PaymentRequest): JsonNode = + return %*{ + "receiver": self.receiver, + "amount": self.amount, + "symbol": self.symbol, + "chainId": self.chainId + } + +proc `$`*(self: PaymentRequest): string = + result = fmt"""PaymentRequest( + receiver: {self.receiver}, + amount: {self.amount}, + symbol: {self.symbol}, + chainId: {self.chainId}, + )""" \ No newline at end of file diff --git a/src/app_service/service/stickers/async_tasks.nim b/src/app_service/service/stickers/async_tasks.nim index 6ff9d32a346..ccdbc738f5b 100644 --- a/src/app_service/service/stickers/async_tasks.nim +++ b/src/app_service/service/stickers/async_tasks.nim @@ -89,6 +89,7 @@ const asyncSendStickerTask: Task = proc(argEncoded: string) {.gcsafe, nimcall.} arg.preferredUsername, standardLinkPreviews = JsonNode(), statusLinkPreviews = JsonNode(), + paymentRequests = JsonNode(), communityId = "", # communityId is not necessary when sending a sticker arg.stickerHash, arg.stickerPackId, diff --git a/src/backend/chat.nim b/src/backend/chat.nim index 822175d730a..8d464b7a856 100644 --- a/src/backend/chat.nim +++ b/src/backend/chat.nim @@ -58,6 +58,7 @@ proc sendChatMessage*( preferredUsername: string = "", standardLinkPreviews: JsonNode, statusLinkPreviews: JsonNode, + paymentRequests: JsonNode, communityId: string = "", stickerHash: string = "", stickerPack: string = "0", @@ -76,6 +77,7 @@ proc sendChatMessage*( "communityId": communityId, "linkPreviews": standardLinkPreviews, "statusLinkPreviews": statusLinkPreviews, + "payment_requests": paymentRequests, } ]) @@ -86,6 +88,7 @@ proc sendImages*(chatId: string, preferredUsername: string, standardLinkPreviews: JsonNode, statusLinkPreviews: JsonNode, + paymentRequests: JsonNode, ): RpcResponse[JsonNode] = let imagesJson = %* images.map(image => %* { @@ -97,6 +100,7 @@ proc sendImages*(chatId: string, "responseTo": replyTo, "linkPreviews": standardLinkPreviews, "statusLinkPreviews": statusLinkPreviews, + "payment_requests": paymentRequests, } ) callPrivateRPC("sendChatMessages".prefix, %* [imagesJson]) diff --git a/test/nim/message_model_test.nim b/test/nim/message_model_test.nim index 269247cb0dc..87c16af61be 100644 --- a/test/nim/message_model_test.nim +++ b/test/nim/message_model_test.nim @@ -62,6 +62,7 @@ proc createTestMessageItem(id: string, clock: int64): Item = albumImagesCount = 0, bridgeMessage = BridgeMessage(), quotedBridgeMessage = BridgeMessage(), + paymentRequests = @[], ) let message0_chatIdentifier = createTestMessageItem("chat-identifier", -2)