fix(@desktop/chat): enable transactions over chat

fixes #4610
This commit is contained in:
Khushboo Mehta 2022-02-09 01:04:49 +01:00 committed by Khushboo-dev-cpp
parent 39157adea4
commit 52e96e904b
34 changed files with 577 additions and 572 deletions

View File

@ -135,8 +135,6 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
result.chatService = chat_service.newService(statusFoundation.events, result.contactsService)
result.communityService = community_service.newService(statusFoundation.events,
statusFoundation.threadpool, result.chatService)
result.messageService = message_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.contactsService)
result.activityCenterService = activity_center_service.newService(statusFoundation.events,
statusFoundation.threadpool, result.chatService)
result.tokenService = token_service.newService(
@ -147,6 +145,8 @@ proc newAppController*(statusFoundation: StatusFoundation): AppController =
statusFoundation.events, result.settingsService, result.accountsService, result.tokenService,
result.networkService,
)
result.messageService = message_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.contactsService, result.ethService, result.tokenService, result.walletAccountService)
result.transactionService = transaction_service.newService(statusFoundation.events, statusFoundation.threadpool,
result.walletAccountService, result.ethService, result.networkService, result.settingsService)
result.bookmarkService = bookmark_service.newService()

View File

@ -4,6 +4,7 @@ import ./io_interface, ./view, ./controller
import ./item as notification_item
import ../../shared_models/message_item as message_item
import ../../shared_models/message_item_qobject as message_item_qobject
import ../../shared_models/message_transaction_parameters_item
import ../../../global/global_singleton
import ../../../core/eventemitter
import ../../../../app_service/service/activity_center/service as activity_center_service
@ -91,6 +92,7 @@ method convertToItems*[T](
self.controller.decodeContentHash(n.message.sticker.hash),
n.message.sticker.pack,
n.message.links,
initTransactionParametersItem("","","","","","",-1,""),
))
return notification_item.initItem(

View File

@ -9,6 +9,7 @@ import ../../../../../app_service/service/chat/service as chat_service
import ../../../../../app_service/service/community/service as community_service
import ../../../../../app_service/service/message/service as message_service
import ../../../../../app_service/service/eth/utils as eth_utils
import ../../../../../app_service/service/wallet_account/service as wallet_account_service
import ../../../../core/signals/types
import ../../../../core/eventemitter
@ -180,6 +181,11 @@ method getCurrentFleet*(self: Controller): string =
method getRenderedText*(self: Controller, parsedTextArray: seq[ParsedText]): string =
return self.messageService.getRenderedText(parsedTextArray)
method decodeContentHash*(self: Controller, hash: string): string =
return eth_utils.decodeContentHash(hash)
method getTransactionDetails*(self: Controller, message: MessageDto): (string,string) =
return self.messageService.getTransactionDetails(message)
method getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAccountDto] =
return self.messageService.getWalletAccounts()

View File

@ -3,6 +3,7 @@ import ../../../../../app_service/service/message/dto/[message, reaction]
import ../../../../../app_service/service/community/dto/[community]
import ../../../../../app_service/service/chat/dto/[chat]
import ../../../../../app_service/service/contacts/service
import ../../../../../app_service/service/wallet_account/[dto]
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -72,3 +73,9 @@ method getRenderedText*(self: AccessInterface, parsedTextArray: seq[ParsedText])
method decodeContentHash*(self: AccessInterface, hash: string): string {.base.} =
raise newException(ValueError, "No implementation available")
method getTransactionDetails*(self: AccessInterface, message: MessageDto): (string,string) {.base.} =
raise newException(ValueError, "No implementation available")
method getWalletAccounts*(self: AccessInterface): seq[WalletAccountDto] =
raise newException(ValueError, "No implementation available")

View File

@ -7,6 +7,7 @@ import ../../../../../../app_service/service/community/service as community_serv
import ../../../../../../app_service/service/chat/service as chat_service
import ../../../../../../app_service/service/message/service as message_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/eth/utils as eth_utils
import ../../../../../core/signals/types
import ../../../../../core/eventemitter
@ -234,3 +235,9 @@ method requestMoreMessages*(self: Controller) =
method fillGaps*(self: Controller, messageId: string) =
self.mailserversService.fillGaps(self.chatId, messageId)
method getTransactionDetails*(self: Controller, message: MessageDto): (string,string) =
return self.messageService.getTransactionDetails(message)
method getWalletAccounts*(self: Controller): seq[wallet_account_service.WalletAccountDto] =
return self.messageService.getWalletAccounts()

View File

@ -2,6 +2,7 @@ import ../../../../../../app_service/service/contacts/dto/[contacts, contact_det
import ../../../../../../app_service/service/community/dto/[community]
import ../../../../../../app_service/service/chat/dto/[chat]
import ../../../../../../app_service/service/message/dto/[message, reaction]
import ../../../../../../app_service/service/wallet_account/[dto]
type
AccessInterface* {.pure inheritable.} = ref object of RootObj
@ -95,3 +96,9 @@ method requestMoreMessages*(self: AccessInterface) {.base.} =
method fillGaps*(self: AccessInterface, messageId: string) {.base.} =
raise newException(ValueError, "No implementation available")
method getTransactionDetails*(self: AccessInterface, message: MessageDto): (string,string) {.base.} =
raise newException(ValueError, "No implementation available")
method getWalletAccounts*(self: AccessInterface): seq[WalletAccountDto] =
raise newException(ValueError, "No implementation available")

View File

@ -5,6 +5,7 @@ import view, controller
import ../../../../shared_models/message_model
import ../../../../shared_models/message_item
import ../../../../shared_models/message_reaction_item
import ../../../../shared_models/message_transaction_parameters_item
import ../../../../../global/global_singleton
import ../../../../../core/eventemitter
import ../../../../../../app_service/service/contacts/service as contact_service
@ -90,6 +91,7 @@ proc createFetchMoreMessagesItem(self: Module): Item =
sticker = "",
stickerPack = -1,
@[],
initTransactionParametersItem("","","","","","",-1,""),
)
proc createChatIdentifierItem(self: Module): Item =
@ -120,6 +122,7 @@ proc createChatIdentifierItem(self: Module): Item =
sticker = "",
stickerPack = -1,
@[],
initTransactionParametersItem("","","","","","",-1,""),
)
proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module): bool =
@ -135,6 +138,15 @@ proc checkIfMessageLoadedAndScrollToItIfItIs(self: Module): bool =
return true
return false
method currentUserWalletContainsAddress(self: Module, address: string): bool =
if (address.len == 0):
return false
let accounts = self.controller.getWalletAccounts()
for acc in accounts:
if (acc.address == address):
return true
return false
method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: seq[ReactionDto],
pinnedMessages: seq[PinnedMessageDto]) =
var viewItems: seq[Item]
@ -144,6 +156,13 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
let sender = self.controller.getContactDetails(m.`from`)
let renderedMessageText = self.controller.getRenderedText(m.parsedText)
var transactionContract = m.transactionParameters.contract
var transactionValue = m.transactionParameters.value
var isCurrentUser = sender.isCurrentUser
if(m.contentType.ContentType == ContentType.Transaction):
(transactionContract, transactionValue) = self.controller.getTransactionDetails(m)
if m.transactionParameters.fromAddress != "":
isCurrentUser = self.currentUserWalletContainsAddress(m.transactionParameters.fromAddress)
var item = initItem(
m.id,
m.responseTo,
@ -152,7 +171,7 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
sender.details.localNickname,
sender.icon,
sender.isIdenticon,
sender.isCurrentUser,
isCurrentUser,
m.outgoingStatus,
renderedMessageText,
m.image,
@ -164,7 +183,15 @@ method newMessagesLoaded*(self: Module, messages: seq[MessageDto], reactions: se
sticker = self.controller.decodeContentHash(m.sticker.hash),
m.sticker.pack,
m.links,
)
initTransactionParametersItem(m.transactionParameters.id,
m.transactionParameters.fromAddress,
m.transactionParameters.address,
transactionContract,
transactionValue,
m.transactionParameters.transactionHash,
m.transactionParameters.commandState,
m.transactionParameters.signature),
)
for r in reactions:
if(r.messageId == m.id):
@ -207,6 +234,18 @@ method messageAdded*(self: Module, message: MessageDto) =
let sender = self.controller.getContactDetails(message.`from`)
let renderedMessageText = self.controller.getRenderedText(message.parsedText)
var transactionContract = message.transactionParameters.contract
var transactionValue = message.transactionParameters.value
var isCurrentUser = sender.isCurrentUser
if message.contentType.ContentType == ContentType.Transaction:
(transactionContract, transactionValue) = self.controller.getTransactionDetails(message)
if message.transactionParameters.fromAddress != "":
isCurrentUser = self.currentUserWalletContainsAddress(message.transactionParameters.fromAddress)
# remove a message which has replace parameters filled
let index = self.view.model().findIndexForMessageId(message.replace)
if(index != -1):
self.view.model().removeItem(message.replace)
var item = initItem(
message.id,
message.responseTo,
@ -215,7 +254,7 @@ method messageAdded*(self: Module, message: MessageDto) =
sender.details.localNickname,
sender.icon,
sender.isIdenticon,
sender.isCurrentUser,
isCurrentUser,
message.outgoingStatus,
renderedMessageText,
message.image,
@ -226,7 +265,15 @@ method messageAdded*(self: Module, message: MessageDto) =
message.messageType,
sticker = self.controller.decodeContentHash(message.sticker.hash),
message.sticker.pack,
message.links
message.links,
initTransactionParametersItem(message.transactionParameters.id,
message.transactionParameters.fromAddress,
message.transactionParameters.address,
transactionContract,
transactionValue,
message.transactionParameters.transactionHash,
message.transactionParameters.commandState,
message.transactionParameters.signature),
)
self.view.model().insertItemBasedOnTimestamp(item)

View File

@ -4,6 +4,7 @@ import ../io_interface as delegate_interface
import view, controller
import ../../../shared_models/message_model as pinned_msg_model
import ../../../shared_models/message_item as pinned_msg_item
import ../../../shared_models/message_transaction_parameters_item
import ../../../shared_models/message_reaction_item as pinned_msg_reaction_item
import ../../../../global/global_singleton
import ../../../../core/eventemitter
@ -130,6 +131,15 @@ method getMessagesModule*(self: Module): QVariant =
method getUsersModule*(self: Module): QVariant =
return self.usersModule.getModuleAsVariant()
method currentUserWalletContainsAddress(self: Module, address: string): bool =
if (address.len == 0):
return false
let accounts = self.controller.getWalletAccounts()
for acc in accounts:
if (acc.address == address):
return true
return false
proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy: string, item: var pinned_msg_item.Item):
bool =
let (m, reactions, err) = self.controller.getMessageDetails(messageId)
@ -138,6 +148,13 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy:
let contactDetails = self.controller.getContactDetails(m.`from`)
var transactionContract = m.transactionParameters.contract
var transactionValue = m.transactionParameters.value
var isCurrentUser = contactDetails.isCurrentUser
if(m.contentType.ContentType == ContentType.Transaction):
(transactionContract, transactionValue) = self.controller.getTransactionDetails(m)
if m.transactionParameters.fromAddress != "":
isCurrentUser = self.currentUserWalletContainsAddress(m.transactionParameters.fromAddress)
item = pinned_msg_item.initItem(
m.id,
m.responseTo,
@ -146,7 +163,7 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy:
contactDetails.details.localNickname,
contactDetails.icon,
contactDetails.isIdenticon,
contactDetails.isCurrentUser,
isCurrentUser,
m.outgoingStatus,
self.controller.getRenderedText(m.parsedText),
m.image,
@ -158,6 +175,14 @@ proc buildPinnedMessageItem(self: Module, messageId: string, actionInitiatedBy:
self.controller.decodeContentHash(m.sticker.hash),
m.sticker.pack,
m.links,
initTransactionParametersItem(m.transactionParameters.id,
m.transactionParameters.fromAddress,
m.transactionParameters.address,
transactionContract,
transactionValue,
m.transactionParameters.transactionHash,
m.transactionParameters.commandState,
m.transactionParameters.signature)
)
item.pinned = true
item.pinnedBy = actionInitiatedBy

View File

@ -98,3 +98,21 @@ QtObject:
self.items = items
self.endResetModel()
self.countChanged()
proc getAccountNameByAddress*(self: Model, address: string): string =
for account in self.items:
if(account.getAddress() == address):
return account.getName()
return ""
proc getAccountIconColorByAddress*(self: Model, address: string): string =
for account in self.items:
if(account.getAddress() == address):
return account.getColor()
return ""
proc getAccountAssetsByAddress*(self: Model, address: string): QVariant =
for account in self.items:
if(account.getAddress() == address):
return newQVariant(account.getAssets())
return nil

View File

@ -10,6 +10,7 @@ QtObject:
delegate: io_interface.AccessInterface
model: Model
modelVariant: QVariant
tmpAddress: string
proc delete*(self: View) =
self.model.delete
@ -52,3 +53,15 @@ QtObject:
proc deleteAccount*(self: View, address: string) {.slot.} =
self.delegate.deleteAccount(address)
proc getAccountNameByAddress*(self: View, address: string): string {.slot.} =
return self.model.getAccountNameByAddress(address)
proc getAccountIconColorByAddress*(self: View, address: string): string {.slot.} =
return self.model.getAccountIconColorByAddress(address)
proc setAddressForAssets*(self: View, address: string) {.slot.} =
self.tmpAddress = address
proc getAccountAssetsByAddress*(self: View): QVariant {.slot.} =
return self.model.getAccountAssetsByAddress(self.tmpAddress)

View File

@ -61,6 +61,9 @@ method init*(self: Controller) =
let args = TransactionsLoadedArgs(e)
self.delegate.setTrxHistoryResult(args.transactions, args.address, args.wasFetchMore)
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
self.delegate.transactionWasSent(TransactionSentArgs(e).result)
method checkPendingTransactions*(self: Controller) =
self.transactionService.checkPendingTransactions()

View File

@ -54,6 +54,9 @@ method transferTokens*(self: AccessInterface, from_addr: string, to_addr: string
uuid: string): bool {.base.} =
raise newException(ValueError, "No implementation available")
method transactionWasSent*(self: AccessInterface, result: string) {.base.} =
raise newException(ValueError, "No implementation available")
# View Delegate Interface
# Delegate for the view must be declared here due to use of QtObject and multi
# inheritance, which is not well supported in Nim.

View File

@ -99,3 +99,7 @@ method transferTokens*(self: Module, from_addr: string, to_addr: string, contrac
maxFeePerGas: string, password: string, uuid: string): bool =
result = self.controller.transferTokens(from_addr, to_addr, contractAddress, value, gas, gasPrice,
maxPriorityFeePerGas, maxFeePerGas, password, uuid)
method transactionWasSent*(self: Module, result: string) =
self.view.transactionWasSent(result)

View File

@ -107,6 +107,11 @@ QtObject:
result = self.delegate.estimateGas(from_addr, to, assetAddress, value, data)
result = self.delegate.estimateGas(from_addr, to, assetAddress, value, data)
proc transactionSent*(self: View, txResult: string) {.signal.}
proc transactionWasSent*(self: View,txResult: string) {.slot} =
self.transactionSent(txResult)
proc transferEth*(self: View, from_addr: string, to_addr: string, value: string, gas: string,
gasPrice: string, maxPriorityFeePerGas: string, maxFeePerGas: string, password: string,
uuid: string): bool {.slot.} =

View File

@ -2,7 +2,7 @@ import json, strformat
import ../../../app_service/common/types
export types.ContentType
import message_reaction_model, message_reaction_item
import message_reaction_model, message_reaction_item, message_transaction_parameters_item
type
Item* = ref object
@ -32,6 +32,7 @@ type
editMode: bool
isEdited: bool
links: seq[string]
transactionParameters: TransactionParametersItem
proc initItem*(
id,
@ -53,6 +54,7 @@ proc initItem*(
sticker: string,
stickerPack: int,
links: seq[string],
transactionParameters: TransactionParametersItem,
): Item =
result = Item()
result.id = id
@ -78,6 +80,7 @@ proc initItem*(
result.editMode = false
result.isEdited = false
result.links = links
result.transactionParameters = transactionParameters
proc `$`*(self: Item): string =
result = fmt"""Item(
@ -99,8 +102,9 @@ proc `$`*(self: Item): string =
pinnedBy:{$self.pinnedBy},
messageReactions: [{$self.reactionsModel}],
editMode:{$self.editMode},
isEdited:{$self.isEdited}
links:{$self.links}
isEdited:{$self.isEdited},
links:{$self.links},
transactionParameters:{$self.transactionParameters},
)"""
proc id*(self: Item): string {.inline.} =
@ -206,6 +210,9 @@ proc removeReaction*(self: Item, emojiId: EmojiId, reactionId: string, didIRemov
proc links*(self: Item): seq[string] {.inline.} =
self.links
proc transactionParameters*(self: Item): TransactionParametersItem {.inline.} =
self.transactionParameters
proc toJsonNode*(self: Item): JsonNode =
result = %* {
"id": self.id,

View File

@ -1,6 +1,6 @@
import NimQml, Tables, json, strutils, strformat
import message_item, message_reaction_item
import message_item, message_reaction_item, message_transaction_parameters_item
type
ModelRole {.pure.} = enum
@ -31,6 +31,7 @@ type
EditMode
IsEdited
Links
TransactionParameters
QtObject:
type
@ -93,6 +94,7 @@ QtObject:
ModelRole.EditMode.int: "editMode",
ModelRole.IsEdited.int: "isEdited",
ModelRole.Links.int: "links",
ModelRole.TransactionParameters.int: "transactionParameters",
}.toTable
method data(self: Model, index: QModelIndex, role: int): QVariant =
@ -158,6 +160,17 @@ QtObject:
result = newQVariant(item.isEdited)
of ModelRole.Links:
result = newQVariant(item.links.join(" "))
of ModelRole.TransactionParameters:
result = newQVariant($(%*{
"id": item.transactionParameters.id,
"fromAddress": item.transactionParameters.fromAddress,
"address": item.transactionParameters.address,
"contract": item.transactionParameters.contract,
"value": item.transactionParameters.value,
"transactionHash": item.transactionParameters.transactionHash,
"commandState": item.transactionParameters.commandState,
"signature": item.transactionParameters.signature
}))
proc findIndexForMessageId*(self: Model, messageId: string): int =
for i in 0 ..< self.items.len:

View File

@ -0,0 +1,109 @@
import Nimqml, json, strformat
QtObject:
type
TransactionParametersItem* = ref object of QObject
id: string
fromAddress: string
address: string
contract: string
value: string
transactionHash: string
commandState: int
signature: string
proc initTransactionParametersItem*(
id: string,
fromAddress: string,
address: string,
contract: string,
value: string,
transactionHash: string,
commandState: int,
signature: string,
): TransactionParametersItem =
result = TransactionParametersItem()
result.id = id
result.fromAddress = fromAddress
result.address = address
result.contract = contract
result.value = value
result.transactionHash = transactionHash
result.commandState = commandState
result.signature = signature
proc `$`*(self: TransactionParametersItem): string =
result = fmt"""TransactionParametersItem(
id: {$self.id},
fromAddress: {$self.fromAddress},
address: {$self.address},
contract: {$self.contract},
value: {$self.value},
transactionHash: {$self.transactionHash},
commandState: {$self.commandState},
signature: {$self.signature},
)"""
proc idChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[string] id:
read = id
notify = idChanged
proc id*(self: TransactionParametersItem): string {.inline.} =
self.id
proc fromAddressChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[string] fromAddress:
read = fromAddress
notify = fromAddressChanged
proc fromAddress*(self: TransactionParametersItem): string {.inline.} =
self.fromAddress
proc addressChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[string] address:
read = address
notify = addressChanged
proc address*(self: TransactionParametersItem): string {.inline.} =
self.address
proc contractChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[string] contract:
read = contract
notify = contractChanged
proc contract*(self: TransactionParametersItem): string {.inline.} =
self.contract
proc valueChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[string] value:
read = value
notify = valueChanged
proc value*(self: TransactionParametersItem): string {.inline.} =
self.value
proc transactionHashChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[string] transactionHash:
read = transactionHash
notify = transactionHashChanged
proc transactionHash*(self: TransactionParametersItem): string {.inline.} =
self.transactionHash
proc commandStateChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[int] commandState:
read = commandState
notify = commandStateChanged
proc commandState*(self: TransactionParametersItem): int {.inline.} =
self.commandState
proc signatureChanged*(self: TransactionParametersItem) {.signal.}
QtProperty[string] signature:
read = signature
notify = signatureChanged
proc signature*(self: TransactionParametersItem): string {.inline.} =
self.signature

View File

@ -36,6 +36,16 @@ type GapParameters* = object
`from`*: int64
to*: int64
type TransactionParameters* = object
id*: string
fromAddress*: string
address*: string
contract*: string
value*: string
transactionHash*: string
commandState*: int
signature*: string
type MessageDto* = object
id*: string
whisperTimestamp*: int64
@ -63,6 +73,7 @@ type MessageDto* = object
messageType*: int
links*: seq[string]
editedAt*: int
transactionParameters*: TransactionParameters
proc toParsedText*(jsonObj: JsonNode): ParsedText =
result = ParsedText()
@ -95,6 +106,17 @@ proc toGapParameters*(jsonObj: JsonNode): GapParameters =
discard jsonObj.getProp("from", result.from)
discard jsonObj.getProp("to", result.to)
proc toTransactionParameters*(jsonObj: JsonNode): TransactionParameters =
result = TransactionParameters()
discard jsonObj.getProp("id", result.id)
discard jsonObj.getProp("from", result.fromAddress)
discard jsonObj.getProp("address", result.address)
discard jsonObj.getProp("contract", result.contract)
discard jsonObj.getProp("value", result.value)
discard jsonObj.getProp("transactionHash", result.transactionHash)
discard jsonObj.getProp("commandState", result.commandState)
discard jsonObj.getProp("signature", result.signature)
proc toMessageDto*(jsonObj: JsonNode): MessageDto =
result = MessageDto()
discard jsonObj.getProp("id", result.id)
@ -141,6 +163,10 @@ proc toMessageDto*(jsonObj: JsonNode): MessageDto =
for pTextObj in parsedTextArr:
result.parsedText.add(toParsedText(pTextObj))
var transactionParametersObj: JsonNode
if(jsonObj.getProp("commandParameters", transactionParametersObj)):
result.transactionParameters = toTransactionParameters(transactionParametersObj)
proc containsContactMentions*(self: MessageDto): bool =
for pText in self.parsedText:
for child in pText.children:

View File

@ -6,6 +6,9 @@ import ../../../app/core/eventemitter
import ../../../app/global/global_singleton
import ../../../backend/messages as status_go
import ../contacts/service as contact_service
import ../eth/service as eth_service
import ../token/service as token_service
import ../wallet_account/service as wallet_account_service
import ./dto/message as message_dto
import ./dto/pinned_message as pinned_msg_dto
import ./dto/reaction as reaction_dto
@ -14,6 +17,11 @@ import ./dto/pinned_message_update as pinned_msg_update_dto
import ./dto/removed_message as removed_msg_dto
import ../../common/message as message_common
import ../../common/conversion as service_conversion
from ../../common/account_constants import ZERO_ADDRESS
import web3/conversions
export message_dto
export pinned_msg_dto
@ -96,6 +104,9 @@ QtObject:
events: EventEmitter
threadpool: ThreadPool
contactService: contact_service.Service
ethService: eth_service.ServiceInterface
tokenService: token_service.Service
walletAccountService: wallet_account_service.ServiceInterface
msgCursor: Table[string, string]
lastUsedMsgCursor: Table[string, string]
pinnedMsgCursor: Table[string, string]
@ -105,12 +116,15 @@ QtObject:
proc delete*(self: Service) =
self.QObject.delete
proc newService*(events: EventEmitter, threadpool: ThreadPool, contactService: contact_service.Service): Service =
proc newService*(events: EventEmitter, threadpool: ThreadPool, contactService: contact_service.Service, ethService: eth_service.ServiceInterface, tokenService: token_service.Service, walletAccountService: wallet_account_service.ServiceInterface): Service =
new(result, delete)
result.QObject.setup
result.events = events
result.threadpool = threadpool
result.contactService = contactService
result.ethService = ethService
result.tokenService = tokenService
result.walletAccountService = walletAccountService
result.msgCursor = initTable[string, string]()
result.lastUsedMsgCursor = initTable[string, string]()
result.pinnedMsgCursor = initTable[string, string]()
@ -230,6 +244,16 @@ QtObject:
return self.pinnedMsgCursor[chatId]
proc getTransactionDetails*(self: Service, message: MessageDto): (string, string) =
let allContracts = self.ethService.allErc20Contracts()
let ethereum = newErc20Contract("Ethereum", Mainnet, parseAddress(ZERO_ADDRESS), "ETH", 18, true)
let tokenContract = if message.transactionParameters.contract == "" : ethereum else: self.ethService.findByAddress(allContracts, parseAddress(message.transactionParameters.contract))
let tokenContractStr = if tokenContract == nil: "{}" else: $(Json.encode(tokenContract))
var weiStr = if tokenContract == nil: "0" else: service_conversion.wei2Eth(message.transactionParameters.value, tokenContract.decimals)
weiStr.trimZeros()
return (tokenContractStr, weiStr)
proc onAsyncLoadMoreMessagesForChat*(self: Service, response: string) {.slot.} =
let responseObj = response.parseJson
if (responseObj.kind != JObject):
@ -688,3 +712,6 @@ proc switchTo*(self: Service, sectionId: string, chatId: string, messageId: stri
## section and/or chat and/or message
let data = ActiveSectionChatArgs(sectionId: sectionId, chatId: chatId, messageId: messageId)
self.events.emit(SIGNAL_MAKE_SECTION_CHAT_ACTIVE, data)
proc getWalletAccounts*(self: Service): seq[wallet_account_service.WalletAccountDto] =
return self.walletAccountService.getWalletAccounts()

View File

@ -29,6 +29,7 @@ include ../../common/json_utils
# Signals which may be emitted by this service:
const SIGNAL_TRANSACTIONS_LOADED* = "transactionsLoaded"
const SIGNAL_TRANSACTION_SENT* = "transactionSent"
type
TransactionMinedArgs* = ref object of Args
@ -43,6 +44,10 @@ type
address*: string
wasFetchMore*: bool
type
TransactionSentArgs* = ref object of Args
result*: string
QtObject:
type Service* = ref object of QObject
events: EventEmitter
@ -275,6 +280,9 @@ QtObject:
if response.error != nil:
raise newException(Exception, response.error.message)
let output = %* { "result": %response.result.getStr, "success": %(response.error == nil), "uuid": %uuid }
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
self.trackPendingTransaction(response.result.getStr, from_addr, to_addr,
$PendingTransactionTypeDto.WalletTransfer, data = "")
except Exception as e:
@ -314,6 +322,9 @@ QtObject:
let transferMethod = contract.getMethod("transfer")
let response = transferMethod.send(tx, transfer, password, success)
let output = %* { "result": %response, "success": %success, "uuid": %uuid }
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(result: $output))
self.trackPendingTransaction(response, from_addr, to_addr,
$PendingTransactionTypeDto.WalletTransfer, data = "")
except Exception as e:

View File

@ -116,8 +116,8 @@ StatusModal {
id: txtAmount
selectedAccount: selectFromAccount.selectedAccount
currentCurrency: root.store.currentCurrency
getFiatValue: root.store.getFiatValue
// Not Refactored Yet
// getFiatValue: root.store.walletModelInst.balanceView.getFiatValue
// getCryptoValue: root.store.walletModelInst.balanceView.getCryptoValue
validateBalance: !root.isRequested
width: stack.width
@ -188,9 +188,3 @@ StatusModal {
]
}
/*##^##
Designer {
D{i:0;autoSize:true;height:480;width:640}
}
##^##*/

View File

@ -132,6 +132,7 @@ ModalPopup {
reactionsModel: model.reactions
linkUrls: model.links
isInPinnedPopup: true
transactionParams: model.transactionParameters
// This is possible since we have all data loaded before we load qml.
// When we fetch messages to fulfill a gap we have to set them at once.

View File

@ -1,388 +0,0 @@
import QtQuick 2.13
import QtQuick.Controls 2.13
import QtQuick.Layouts 1.13
import QtQuick.Dialogs 1.3
import utils 1.0
import shared.controls 1.0
import StatusQ.Popups 0.1
import StatusQ.Controls 0.1
import shared.views 1.0
import shared.panels 1.0
import shared.popups 1.0
import "../../Wallet/"
//TODO remove dynamic scoping
StatusModal {
id: root
//% "Send"
header.title: qsTrId("command-button-send")
height: 540
property var store
property var contactsStore
property var selectedAccount
property var selectedRecipient
property var selectedAsset
property var selectedAmount
property var selectedFiatAmount
property bool outgoing: true
property string trxData: ""
property alias transactionSigner: transactionSigner
property var sendTransaction: function(selectedGasLimit, selectedGasPrice, selectedTipLimit, selectedOveralLimit, enteredPassword) {
let success = false
// Not Refactored Yet
// if(root.selectedAsset.address == Constants.zeroAddress){
// success = root.store.walletModelInst.transactionsView.transferEth(
// selectFromAccount.selectedAccount.address,
// selectRecipient.selectedRecipient.address,
// root.selectedAmount,
// selectedGasLimit,
// gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
// gasSelector.selectedTipLimit,
// gasSelector.selectedOverallLimit,
// enteredPassword,
// stack.uuid)
// } else {
// success = root.store.walletModelInst.transactionsView.transferTokens(
// selectFromAccount.selectedAccount.address,
// selectRecipient.selectedRecipient.address,
// root.selectedAsset.address,
// root.selectedAmount,
// selectedGasLimit,
// gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
// gasSelector.selectedTipLimit,
// gasSelector.selectedOverallLimit,
// enteredPassword,
// stack.uuid)
// }
// if(!success){
// //% "Invalid transaction parameters"
// sendingError.text = qsTrId("invalid-transaction-parameters")
// sendingError.open()
// }
}
property MessageDialog sendingError: MessageDialog {
id: sendingError
//% "Error sending the transaction"
title: qsTrId("error-sending-the-transaction")
icon: StandardIcon.Critical
standardButtons: StandardButton.Ok
}
onClosed: {
stack.pop(groupPreview, StackView.Immediate)
}
contentItem: Item {
width: root.width
height: childrenRect.height
TransactionStackView {
id: stack
anchors.leftMargin: Style.current.padding
anchors.rightMargin: Style.current.padding
initialItem: groupPreview
isLastGroup: stack.currentGroup === groupSignTx
onGroupActivated: {
header.title = group.headerText
btnNext.text = group.footerText
}
TransactionFormGroup {
id: groupSelectAcct
headerText: {
// Not Refactored Yet
// if(trxData.startsWith("0x095ea7b3")){
// const approveData = JSON.parse(root.store.walletModelInst.tokensView.decodeTokenApproval(selectedRecipient.address, trxData))
// if(approveData.symbol)
// //% "Authorize %1 %2"
// return qsTrId("authorize--1--2").arg(approveData.amount).arg(approveData.symbol)
// }
return qsTrId("command-button-send");
}
//% "Continue"
footerText: qsTrId("continue")
showNextBtn: false
onBackClicked: function() {
if(validate()) {
stack.pop()
}
}
StatusAccountSelector {
id: selectFromAccount
// Not Refactored Yet
// accounts: root.store.walletModelInst.accountsView.accounts
// currency: root.store.walletModelInst.balanceView.defaultCurrency
width: stack.width
selectedAccount: root.selectedAccount
//% "Choose account"
label: qsTrId("choose-account")
showBalanceForAssetSymbol: root.selectedAsset.symbol
minRequiredAssetBalance: parseFloat(root.selectedAmount)
onSelectedAccountChanged: if (isValid) { gasSelector.estimateGas() }
}
RecipientSelector {
id: selectRecipient
visible: false
// Not Refactored Yet
// accounts: root.store.walletModelInst.accountsView.accounts
contactsStore: root.contactsStore
selectedRecipient: root.selectedRecipient
readOnly: true
}
}
TransactionFormGroup {
id: groupSelectGas
//% "Network fee"
headerText: qsTrId("network-fee")
footerText: qsTr("Continue")
showNextBtn: false
onBackClicked: function() {
stack.pop()
}
GasSelector {
id: gasSelector
anchors.topMargin: Style.current.padding
// Not Refactored Yet
// gasPrice: parseFloat(root.store.walletModelInst.gasView.gasPrice)
// getGasEthValue: root.store.walletModelInst.gasView.getGasEthValue
// getFiatValue: root.store.walletModelInst.balanceView.getFiatValue
// defaultCurrency: root.store.walletModelInst.balanceView.defaultCurrency
width: stack.width
property var estimateGas: Backpressure.debounce(gasSelector, 600, function() {
// Not Refactored Yet
// if (!(selectFromAccount.selectedAccount && selectFromAccount.selectedAccount.address &&
// selectRecipient.selectedRecipient && selectRecipient.selectedRecipient.address &&
// root.selectedAsset && root.selectedAsset.address &&
// root.selectedAmount)) {
// selectedGasLimit = 250000
// defaultGasLimit = selectedGasLimit
// return
// }
// let gasEstimate = JSON.parse(root.store.walletModelInst.gasView.estimateGas(
// selectFromAccount.selectedAccount.address,
// selectRecipient.selectedRecipient.address,
// root.selectedAsset.address,
// root.selectedAmount,
// trxData))
// if (!gasEstimate.success) {
// //% "Error estimating gas: %1"
// let message = qsTrId("error-estimating-gas---1").arg(gasEstimate.error.message)
// //% ". The transaction will probably fail."
// gasEstimateErrorPopup.confirmationText = message + qsTrId("--the-transaction-will-probably-fail-")
// gasEstimateErrorPopup.open()
// return
// }
// selectedGasLimit = gasEstimate.result
// defaultGasLimit = selectedGasLimit
})
}
GasValidator {
id: gasValidator
anchors.top: gasSelector.bottom
selectedAccount: selectFromAccount.selectedAccount
selectedAmount: parseFloat(root.selectedAmount)
selectedAsset: root.selectedAsset
selectedGasEthValue: gasSelector.selectedGasEthValue
}
}
TransactionFormGroup {
id: groupPreview
//% "Transaction preview"
headerText: qsTrId("transaction-preview")
//% "Sign with password"
footerText: qsTrId("sign-with-password")
showBackBtn: false
onNextClicked: function() {
stack.push(groupSignTx, StackView.Immediate)
}
isValid: groupSelectAcct.isValid && groupSelectGas.isValid && pvwTransaction.isValid
TransactionPreview {
id: pvwTransaction
width: stack.width
fromAccount: selectFromAccount.selectedAccount
gas: {
"value": gasSelector.selectedGasEthValue,
"symbol": "ETH",
"fiatValue": gasSelector.selectedGasFiatValue
}
toAccount: selectRecipient.selectedRecipient
asset: root.selectedAsset
amount: { "value": root.selectedAmount, "fiatValue": root.selectedFiatAmount }
// Not Refactored Yet
// currency: root.store.walletModelInst.balanceView.defaultCurrency
isFromEditable: false
trxData: root.trxData
isGasEditable: true
fromValid: balanceValidator.isValid
gasValid: gasValidator.isValid
onFromClicked: { stack.push(groupSelectAcct, StackView.Immediate) }
onGasClicked: { stack.push(groupSelectGas, StackView.Immediate) }
}
BalanceValidator {
id: balanceValidator
anchors.top: pvwTransaction.bottom
anchors.horizontalCenter: parent.horizontalCenter
account: selectFromAccount.selectedAccount
amount: !!root.selectedAmount ? parseFloat(root.selectedAmount) : 0.0
asset: root.selectedAsset
}
GasValidator {
id: gasValidator2
anchors.top: balanceValidator.visible ? balanceValidator.bottom : pvwTransaction.bottom
anchors.topMargin: balanceValidator.visible ? 5 : 0
anchors.horizontalCenter: parent.horizontalCenter
selectedAccount: selectFromAccount.selectedAccount
selectedAmount: parseFloat(root.selectedAmount)
selectedAsset: root.selectedAsset
selectedGasEthValue: gasSelector.selectedGasEthValue
}
}
TransactionFormGroup {
id: groupSignTx
//% "Sign with password"
headerText: qsTrId("sign-with-password")
//% "Send %1 %2"
footerText: qsTrId("send--1--2").arg(root.selectedAmount).arg(!!root.selectedAsset ? root.selectedAsset.symbol : "")
onBackClicked: function() {
stack.pop()
}
TransactionSigner {
id: transactionSigner
width: stack.width
// Not Refactored Yet
// signingPhrase: root.store.walletModelInst.utilsView.signingPhrase
}
}
}
}
leftButtons: [
StatusRoundButton {
id: btnBack
icon.name: "arrow-right"
icon.width: 20
icon.height: 16
icon.rotation: 180
visible: stack.currentGroup.showBackBtn
enabled: stack.currentGroup.isValid || stack.isLastGroup
onClicked: {
if (typeof stack.currentGroup.onBackClicked === "function") {
return stack.currentGroup.onBackClicked()
}
stack.back()
}
}
]
rightButtons: [
StatusButton {
id: btnNext
//% "Next"
text: qsTrId("next")
enabled: stack.currentGroup.isValid && !stack.currentGroup.isPending
visible: stack.currentGroup.showNextBtn
onClicked: {
const validity = stack.currentGroup.validate()
if (validity.isValid && !validity.isPending) {
if (stack.isLastGroup) {
return root.sendTransaction(gasSelector.selectedGasLimit,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword)
}
if(gasSelector.eip1599Enabled && stack.currentGroup === groupSelectGas && gasSelector.advancedMode){
if(gasSelector.showPriceLimitWarning || gasSelector.showTipLimitWarning){
Global.openPopup(transactionSettingsConfirmationPopupComponent, {
currentBaseFee: gasSelector.latestBaseFeeGwei,
currentMinimumTip: gasSelector.perGasTipLimitFloor,
currentAverageTip: gasSelector.perGasTipLimitAverage,
tipLimit: gasSelector.selectedTipLimit,
suggestedTipLimit: gasSelector.perGasTipLimitFloor, // TODO:
priceLimit: gasSelector.selectedOverallLimit,
suggestedPriceLimit: gasSelector.latestBaseFeeGwei + gasSelector.perGasTipLimitFloor,
showPriceLimitWarning: gasSelector.showPriceLimitWarning,
showTipLimitWarning: gasSelector.showTipLimitWarning,
onConfirm: function(){
stack.next();
}
})
return
}
}
if (typeof stack.currentGroup.onNextClicked === "function") {
return stack.currentGroup.onNextClicked()
}
stack.next()
}
}
}
]
Component {
id: transactionSettingsConfirmationPopupComponent
TransactionSettingsConfirmationPopup {
}
}
// Not Refactored Yet
// Connections {
// target: root.store.walletModelInst.transactionsView
// onTransactionWasSent: {
// try {
// let response = JSON.parse(txResult)
// if (response.uuid !== stack.uuid)
// return
// let transactionId = response.result
// if (!response.success) {
// if (Utils.isInvalidPasswordMessage(transactionId)){
// //% "Wrong password"
// transactionSigner.validationError = qsTrId("wrong-password")
// return
// }
// sendingError.text = transactionId
// return sendingError.open()
// }
// // Not Refactored Yet
//// chatsModel.transactions.acceptRequestTransaction(transactionId,
//// messageId,
//// userProfile.pubKey + transactionId.substr(2))
// //% "Transaction pending..."
// toastMessage.title = qsTrId("ens-transaction-pending")
// toastMessage.source = Style.svg("loading")
// toastMessage.iconColor = Style.current.primary
// toastMessage.iconRotates = true
// toastMessage.link = `${root.store.walletModelInst.utilsView.etherscanLink}/${transactionId}`
// toastMessage.open()
// root.close()
// } catch (e) {
// console.error('Error parsing the response', e)
// }
// }
// }
}

View File

@ -71,10 +71,16 @@ QtObject {
property var accounts: walletSectionAccounts.model
property var currentAccount: walletSectionCurrent
property var currentCurrency: walletSection.currentCurrency
property string currentCurrency: walletSection.currentCurrency
property string signingPhrase: walletSection.signingPhrase
property string gasPrice: profileSectionModule.ensUsernamesModule.gasPrice
property ListModel addToGroupContacts: ListModel {}
property var walletSectionTransactionsInst: walletSectionTransactions
function reCalculateAddToGroupContacts(channel) {
const contacts = getContactListObject()
@ -355,4 +361,63 @@ QtObject {
callback: result.callback
}
}
function getPubkey() {
return userProfile.getPubKey()
}
function getFiatValue(balance, cryptoSymbo, fiatSymbol) {
return profileSectionModule.ensUsernamesModule.getFiatValue(balance, cryptoSymbo, fiatSymbol)
}
function acceptRequestTransaction(transactionHash, messageId, signature) {
return currentChatContentModule().inputAreaModule.acceptRequestTransaction(transactionHash, messageId, signature)
}
function acceptAddressRequest(messageId, address) {
currentChatContentModule().inputAreaModule.acceptAddressRequest(messageId, address)
}
function declineAddressRequest(messageId) {
currentChatContentModule().inputAreaModule.declineAddressRequest(messageId)
}
function declineRequest(messageId) {
currentChatContentModule().inputAreaModule.declineRequest(messageId)
}
function getGasEthValue(gweiValue, gasLimit) {
return profileSectionModule.ensUsernamesModule.getGasEthValue(gweiValue, gasLimit)
}
function estimateGas(from_addr, to, assetAddress, value, data) {
return walletSectionTransactions.estimateGas(from_addr, to, assetAddress, value, data)
}
function transferEth(from, to, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, uuid) {
return walletSectionTransactions.transferEth(from, to, amount, gasLimit, gasPrice, tipLimit,
overallLimit, password, uuid);
}
function transferTokens(from, to, address, amount, gasLimit, gasPrice, tipLimit, overallLimit, password, uuid) {
return walletSectionTransactions.transferTokens(from, to, address, amount, gasLimit,
gasPrice, tipLimit, overallLimit, password, uuid);
}
function getAccountNameByAddress(address) {
return walletSectionAccounts.getAccountNameByAddress(address)
}
function getAccountIconColorByAddress(address) {
return walletSectionAccounts.getAccountIconColorByAddress(address)
}
function getAccountAssetsByAddress(address) {
walletSectionAccounts.setAddressForAssets(address)
return walletSectionAccounts.getAccountAssetsByAddress()
}
function fetchGasPrice() {
profileSectionModule.ensUsernamesModule.fetchGasPrice()
}
}

View File

@ -92,7 +92,6 @@ Item {
chatContentModule.inputAreaModule.requestAddress(address,
amount,
tokenAddress)
txModalLoader.close()
}
function requestTransaction(address, amount, tokenAddress, tokenDecimals = 18) {
amount = globalUtils.eth2Wei(amount.toString(), tokenDecimals)
@ -254,7 +253,8 @@ Item {
alias: chatContentModule.chatDetails.name, // Do we need the alias for real or name works?
identicon: chatContentModule.chatDetails.icon,
name: chatContentModule.chatDetails.name,
type: RecipientSelector.Type.Contact
type: RecipientSelector.Type.Contact,
ensVerified: true
}
}
selectRecipient.selectedType: RecipientSelector.Type.Contact

View File

@ -324,6 +324,7 @@ Item {
editModeOn: model.editMode
isEdited: model.isEdited
linkUrls: model.links
transactionParams: model.transactionParameters
// This is possible since we have all data loaded before we load qml.
// When we fetch messages to fulfill a gap we have to set them at once.

View File

@ -50,6 +50,8 @@ QtObject {
property real volume: !!localAccountSensitiveSettings ? localAccountSensitiveSettings.volume : 0.0
property bool notificationSoundsEnabled: !!localAccountSensitiveSettings ? localAccountSensitiveSettings.notificationSoundsEnabled : false
property var walletSectionTransactionsInst: walletSectionTransactions
function createCommunity(communityName, communityDescription, checkedMembership, ensOnlySwitchChecked, communityColor, communityImage, imageCropperModalaX, imageCropperModalaY, imageCropperModalbX, imageCropperModalbY) {
communitiesModuleInst.createCommunity(communityName, communityDescription, checkedMembership, ensOnlySwitchChecked, communityColor, communityImage, imageCropperModalaX, imageCropperModalaY, imageCropperModalbX, imageCropperModalbY);
}

View File

@ -54,7 +54,7 @@ Item {
if (!selectedContact) {
return root.isValid
}
let isValidAddress = Utils.isValidAddress(selectedContact.publicKey)
let isValidAddress = Utils.isValidAddress(selectedContact.address)
let isDefaultValue = selectedContact.alias === selectAContact
let isValid = (selectedContact.ensVerified && isValidAddress) || isPending || isValidAddress
select.validationError = ""
@ -147,12 +147,12 @@ Item {
onResolved: {
root.isResolvedAddress = true
var selectedContact = root.selectedContact
selectedContact.publicKey = resolvedAddress
selectedContact.address = resolvedAddress
root.selectedContact = selectedContact
}
onIsPendingChanged: {
if (isPending) {
root.selectedContact.publicKey = ""
root.selectedContact.address = ""
}
}
}
@ -197,7 +197,7 @@ Item {
height: 16
}
StatusBaseText {
text: currentContact.publicKey
text: currentContact.address
width: 85
elide: Text.ElideMiddle
color: Theme.palette.baseColor1

View File

@ -28,45 +28,58 @@ StatusModal {
property var selectedAsset
property var selectedAmount
property var selectedFiatAmount
property var selectedType: RecipientSelector.Type.Address
property bool outgoing: true
property string msgId: ""
property string trxData: ""
property alias transactionSigner: transactionSigner
property var sendTransaction: function(selectedGasLimit, selectedGasPrice, selectedTipLimit, selectedOveralLimit, enteredPassword) {
// Not Refactored Yet
// let success = false
// if(root.selectedAsset.address == Constants.zeroAddress){
// success = root.store.walletModelInst.transactionsView.transferEth(
// selectFromAccount.selectedAccount.address,
// selectRecipient.selectedRecipient.address,
// root.selectedAmount,
// selectedGasLimit,
// gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
// gasSelector.selectedTipLimit,
// gasSelector.selectedOverallLimit,
// enteredPassword,
// stack.uuid)
// } else {
// success = root.store.walletModelInst.transactionsView.transferTokens(
// selectFromAccount.selectedAccount.address,
// selectRecipient.selectedRecipient.address,
// root.selectedAsset.address,
// root.selectedAmount,
// selectedGasLimit,
// gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
// gasSelector.selectedTipLimit,
// gasSelector.selectedOverallLimit,
// enteredPassword,
// stack.uuid)
// }
property var sendTransaction: function() {
stack.currentGroup.isPending = true
let success = false
if(root.selectedAsset.address === "" || root.selectedAsset.address === Constants.zeroAddress){
success = root.store.transferEth(
selectFromAccount.selectedAccount.address,
selectRecipient.selectedRecipient.address,
root.selectedAmount,
gasSelector.selectedGasLimit,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
} else {
success = root.store.transferTokens(
selectFromAccount.selectedAccount.address,
selectRecipient.selectedRecipient.address,
root.selectedAsset.address,
root.selectedAmount,
gasSelector.selectedGasLimit,
gasSelector.eip1599Enabled ? "" : gasSelector.selectedGasPrice,
gasSelector.selectedTipLimit,
gasSelector.selectedOverallLimit,
transactionSigner.enteredPassword,
stack.uuid)
}
// if(!success){
// //% "Invalid transaction parameters"
// sendingError.text = qsTrId("invalid-transaction-parameters")
// sendingError.open()
// }
if(!success){
//% "Invalid transaction parameters"
sendingError.text = qsTrId("invalid-transaction-parameters")
sendingError.open()
} else {
// TODO remove this else once the thread and connection are back
stack.currentGroup.isPending = false
//% "Transaction pending..."
Global.toastMessage.title = qsTrId("ens-transaction-pending")
Global.toastMessage.source = Style.svg("loading")
Global.toastMessage.iconColor = Style.current.primary
Global.toastMessage.iconRotates = true
// Refactor this
// Global.toastMessage.link = `${walletModel.utilsView.etherscanLink}/${response.result}`
Global.toastMessage.open()
root.close()
}
}
property MessageDialog sendingError: MessageDialog {
@ -92,7 +105,7 @@ StatusModal {
initialItem: groupPreview
isLastGroup: stack.currentGroup === groupSignTx
onGroupActivated: {
root.title = group.headerText
root.header.title = group.headerText
btnNext.text = group.footerText
}
TransactionFormGroup {
@ -117,8 +130,7 @@ StatusModal {
}
StatusAccountSelector {
id: selectFromAccount
// Not Refactored Yet
// accounts: root.store.walletModelInst.accountsView.accounts
accounts: root.store.accounts
currency: root.store.currentCurrency
width: stack.width
selectedAccount: root.selectedAccount
@ -131,10 +143,10 @@ StatusModal {
RecipientSelector {
id: selectRecipient
visible: false
// Not Refactored Yet
// accounts: root.store.walletModelInst.accountsView.accounts
accounts: root.store.accounts
contactsStore: root.contactsStore
selectedRecipient: root.selectedRecipient
selectedType: root.selectedType
readOnly: true
}
}
@ -334,44 +346,31 @@ StatusModal {
TransactionSettingsConfirmationPopup { }
}
// Not Refactored Yet
// Connections {
// target: root.store.walletModelInst.transactionsView
// onTransactionWasSent: {
// try {
// let response = JSON.parse(txResult)
// if (response.uuid !== stack.uuid)
// return
Connections {
target: root.store.walletSectionTransactionsInst
onTransactionSent: {
try {
let response = JSON.parse(txResult)
if (response.uuid !== stack.uuid)
return
// let transactionId = response.result
let transactionId = response.result
// if (!response.success) {
// if (Utils.isInvalidPasswordMessage(transactionId)){
// //% "Wrong password"
// transactionSigner.validationError = qsTrId("wrong-password")
// return
// }
// sendingError.text = transactionId
// return sendingError.open()
// }
// // Not Refactored Yet
// root.store.chatsModelInst.transactions.acceptRequestTransaction(transactionId, msgId,
// root.store.profileModelInst.profile.pubKey + transactionId.substr(2))
// //% "Transaction pending..."
// Global.toastMessage.title = qsTrId("ens-transaction-pending")
// Global.toastMessage.source = Style.svg("loading")
// Global.toastMessage.iconColor = Style.current.primary
// Global.toastMessage.iconRotates = true
// Global.toastMessage.link = `${root.store.walletModelInst.utilsView.etherscanLink}/${transactionId}`
// Global.toastMessage.open()
// root.close()
// } catch (e) {
// console.error('Error parsing the response', e)
// }
// }
// }
if (!response.success) {
if (Utils.isInvalidPasswordMessage(transactionId)){
//% "Wrong password"
transactionSigner.validationError = qsTrId("wrong-password")
return
}
sendingError.text = transactionId
return sendingError.open()
}
root.store.acceptRequestTransaction(transactionId, msgId, root.store.getPubkey() + transactionId.substr(2))
root.close()
} catch (e) {
console.error('Error parsing the response', e)
}
}
}
}

View File

@ -161,7 +161,7 @@ Item {
}
PropertyChanges {
target: idtToContact
source: root.toAccount.identicon
image.source: root.toAccount.identicon
visible: true
}
PropertyChanges {
@ -263,6 +263,7 @@ Item {
anchors.verticalCenter: parent.verticalCenter
image.width: 32
image.height: 32
image.isIdenticon: true
}
SVGImage {
id: toInvalid

View File

@ -16,10 +16,10 @@ Item {
property var store
property var contactsStore
property var commandParametersObject
property var token
property string tokenAmount
property string fiatValue
property var selectedRecipient
property int state: Constants.addressRequested
Separator {
@ -80,13 +80,11 @@ Item {
anchors.fill: parent
cursorShape: Qt.PointingHandCursor
onClicked: {
// Not Refactored Yet
// if (root.state === Constants.addressRequested) {
// root.store.chatsModelInst.transactions.declineAddressRequest(messageId)
// } else if (root.state === Constants.transactionRequested) {
// root.store.chatsModelInst.transactions.declineRequest(messageId)
// }
if (root.state === Constants.addressRequested) {
root.store.declineAddressRequest(messageId)
} else if (root.state === Constants.transactionRequested) {
root.store.declineRequest(messageId)
}
}
}
}
@ -102,32 +100,19 @@ Item {
Component {
id: signTxComponent
SignTransactionModal {
anchors.centerIn: parent
store: root.store
contactsStore: root.contactsStore
msgId: messageId
onOpened: {
// Not Refactored Yet
// root.store.walletModelInst.gasView.getGasPrice()
}
onClosed: {
destroy();
}
onOpened: root.store.fetchGasPrice()
onClosed: destroy()
onOpenGasEstimateErrorPopup: {
gasEstimateErrorPopup.confirmationText = message + qsTrId("--the-transaction-will-probably-fail-");
gasEstimateErrorPopup.open();
return;
}
selectedAccount: {}
selectedRecipient: {
return {
address: commandParametersObject.address,
// Not Refactored Yet
// identicon: root.store.chatsModelInst.channelView.activeChannel.identicon,
// name: root.store.chatsModelInst.channelView.activeChannel.name,
type: RecipientSelector.Type.Contact
}
}
selectedRecipient: root.selectedRecipient
selectedAsset: token
selectedAmount: tokenAmount
selectedFiatAmount: fiatValue
@ -136,19 +121,12 @@ Item {
SelectAccountModal {
id: selectAccountModal
// Not Refactored Yet
// accounts: root.store.walletModelInst.accountsView.accounts
// currency: root.store.walletModelInst.balanceView.defaultCurrency
anchors.centerIn: parent
accounts: root.store.accounts
currency: root.store.currentCurrency
onSelectAndShareAddressButtonClicked: {
// Not Refactored Yet
// root.store.chatsModelInst.transactions.acceptAddressRequest(messageId, accountSelector.selectedAccount.address)
// selectAccountModal.close()
root.store.acceptAddressRequest(messageId, accountSelector.selectedAccount.address)
selectAccountModal.close()
}
}
}
/*##^##
Designer {
D{i:0;formeditorColor:"#ffffff";formeditorZoom:1.25}
}
##^##*/

View File

@ -57,6 +57,8 @@ Item {
property bool editModeOn: false
property string linkUrls: ""
property var transactionParams
signal openStickerPackPopup(string stickerPackId)
signal addEmoji(bool isProfileClick, bool isSticker, bool isImage , var image, bool emojiOnly, bool hideEmojiPicker)
signal clickMessage(bool isProfileClick, bool isSticker, bool isImage, var image, bool emojiOnly, bool hideEmojiPicker, bool isReply, bool isRightClickOnImage, string imageSource)
@ -621,7 +623,8 @@ Item {
anchors.topMargin: active ? (chatName.visible ? 4 : 6) : 0
sourceComponent: Component {
TransactionBubbleView {
//store: rootStore
transactionParams: root.transactionParams
store: root.store
contactsStore: root.contactsStore
}
}

View File

@ -41,6 +41,7 @@ Column {
property var reactionsModel: []
property string linkUrls: ""
property bool isInPinnedPopup: false // The pinned popup limits the number of buttons shown
property var transactionParams
property int prevMessageIndex: -1
property var prevMessageAsJsonObj
@ -360,6 +361,8 @@ Column {
linkUrls: root.linkUrls
isInPinnedPopup: root.isInPinnedPopup
transactionParams: root.transactionParams
onAddEmoji: {
root.clickMessage(isProfileClick, isSticker, isImage , image, emojiOnly, hideEmojiPicker)
}

View File

@ -5,6 +5,7 @@ import shared.panels 1.0
import shared.popups 1.0
import shared.views.chat 1.0
import shared.controls.chat 1.0
import shared.controls 1.0
Item {
id: root
@ -14,12 +15,14 @@ Item {
property var store
property var contactsStore
property var commandParametersObject: {
property var transactionParams
property var transactionParamsObject: {
try {
return JSON.parse(commandParameters)
return JSON.parse(transactionParams)
} catch (e) {
console.error('Error parsing command parameters')
console.error('JSON:', commandParameters)
console.error('JSON:', transactionParams)
console.error('Error:', e)
return {
id: "",
@ -34,28 +37,46 @@ Item {
}
}
property var token: JSON.parse(commandParametersObject.contract) // TODO: handle {}
property string tokenAmount: commandParametersObject.value
property var token:{
try {
return JSON.parse(transactionParamsObject.contract)
} catch (e) {
console.error('Error parsing command parameters')
console.error('JSON:', transactionParamsObject.contract)
console.error('Error:', e)
return ""
}
}
property var selectedRecipient: {
return {
address: transactionParamsObject.address,
identicon: senderIcon,
name: senderDisplayName,
type: RecipientSelector.Type.Contact,
alias: senderDisplayName
}
}
property string tokenAmount: transactionParamsObject.value
property string tokenSymbol: token.symbol || ""
property string fiatValue: {
if (!tokenAmount || !token.symbol) {
return "0"
}
// Not Refactored Yet
// var defaultFiatSymbol = root.store.walletModelInst.balanceView.defaultCurrency
// return root.store.walletModelInst.balanceView.getFiatValue(tokenAmount, token.symbol, defaultFiatSymbol) + " " + defaultFiatSymbol.toUpperCase()
return "0"
var defaultFiatSymbol = root.store.currentCurrency
return root.store.getFiatValue(tokenAmount, token.symbol, defaultFiatSymbol) + " " + defaultFiatSymbol.toUpperCase()
}
property int state: commandParametersObject.commandState
property int state: transactionParamsObject.commandState
// Any transaction where isCurrentUser is true is actually outgoing transaction.
property bool outgoing: isCurrentUser
property int innerMargin: 12
property bool isError: commandParametersObject.contract === "{}"
property bool isError: transactionParamsObject.contract === "{}"
onTokenSymbolChanged: {
if (!!tokenSymbol) {
tokenImage.source = `../../../../img/tokens/${root.tokenSymbol}.png`
tokenImage.source = Style.png("tokens/"+root.tokenSymbol)
}
}
@ -189,7 +210,7 @@ Item {
token: root.token
fiatValue: root.fiatValue
tokenAmount: root.tokenAmount
commandParametersObject: root.commandParametersObject
selectedRecipient: root.selectedRecipient
}
}
@ -197,31 +218,18 @@ Item {
id: signAndSendComponent
SendTransactionButton {
// outgoing: root.outgoing
// Not Refactored Yet
// acc: root.store.walletModelInst.accountsView.focusedAccount
selectedAsset: token
selectedAmount: tokenAmount
selectedFiatAmount: fiatValue
fromAddress: commandParametersObject.fromAddress
selectedRecipient: {
return {
address: commandParametersObject.address,
// Not Refactored Yet
// identicon: root.store.chatsModelInst.channelView.activeChannel.identicon,
// name: root.store.chatsModelInst.channelView.activeChannel.name,
type: RecipientSelector.Type.Contact
}
}
fromAddress: transactionParamsObject.fromAddress
selectedRecipient: root.selectedRecipient
onSendTransaction: {
// Not Refactored Yet
// root.store.walletModelInst.accountsView.setFocusedAccountByAddress(fromAddress);
// Global.openPopup(signTxComponent, {selectedAccount: {
// name: acc.name,
// address: fromAddress,
// iconColor: acc.iconColor,
// assets: acc.assets
// }})
Global.openPopup(signTxComponent, {selectedAccount: {
name: root.store.getAccountNameByAddress(fromAddress),
address: fromAddress,
color: root.store.getAccountIconColorByAddress(fromAddress),
assets: root.store.getAccountAssetsByAddress(fromAddress)
}})
}
}
}
@ -229,19 +237,17 @@ Item {
Component {
id: signTxComponent
SignTransactionModal {
anchors.centerIn: parent
store: root.store
contactsStore: root.contactsStore
selectedAsset: root.selectedAsset
selectedAmount: root.selectedAmount
selectedAsset: root.token
selectedAmount: root.tokenAmount
selectedRecipient: root.selectedRecipient
selectedFiatAmount: root.selectedFiatAmount
onOpened: {
// Not Refactored Yet
// root.store.walletModelInst.gasView.getGasPrice();
}
onClosed: {
destroy();
}
selectedFiatAmount: root.fiatValue
selectedType: RecipientSelector.Type.Contact
onOpened: root.store.fetchGasPrice()
onClosed: destroy()
msgId: messageId
}
}