feat(@desktop/wallet): Implement Transaction details as per new design
fixes #7214
This commit is contained in:
parent
cdfbb4ac87
commit
928e1999d9
|
@ -61,6 +61,9 @@ QtObject:
|
|||
proc hex2Eth*(self: Utils, value: string): string {.slot.} =
|
||||
return stripTrailingZeroes(conversion.wei2Eth(stint.fromHex(StUint[256], value)))
|
||||
|
||||
proc hex2Gwei*(self: Utils, value: string): string {.slot.} =
|
||||
return stripTrailingZeroes(conversion.wei2Eth(stint.fromHex(StUint[256], value)*1000000000))
|
||||
|
||||
proc gwei2Hex*(self: Utils, gwei: float): string {.slot.} =
|
||||
return "0x" & conversion.gwei2Wei(gwei).toHex()
|
||||
|
||||
|
|
|
@ -113,3 +113,6 @@ proc getChainIdForBrowser*(self: Controller): int =
|
|||
|
||||
proc getEstimatedTime*(self: Controller, chainId: int, maxFeePerGas: string): EstimatedTime =
|
||||
return self.transactionService.getEstimatedTime(chainId, maxFeePerGas)
|
||||
|
||||
proc getLastTxBlockNumber*(self: Controller): string =
|
||||
return self.transactionService.getLastTxBlockNumber(self.networkService.getNetworkForBrowser().chainId)
|
||||
|
|
|
@ -72,3 +72,6 @@ method getEstimatedTime*(self: AccessInterface, chainId: int, maxFeePerGas: stri
|
|||
# inheritance, which is not well supported in Nim.
|
||||
method viewDidLoad*(self: AccessInterface) {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getLastTxBlockNumber*(self: AccessInterface): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
|
|
@ -24,6 +24,9 @@ type
|
|||
txHash: string
|
||||
multiTransactionID: int
|
||||
isTimeStamp: bool
|
||||
baseGasFees: string
|
||||
totalFees: string
|
||||
maxTotalFees: string
|
||||
|
||||
proc initItem*(
|
||||
id: string,
|
||||
|
@ -47,7 +50,10 @@ proc initItem*(
|
|||
input: string,
|
||||
txHash: string,
|
||||
multiTransactionID: int,
|
||||
isTimeStamp: bool
|
||||
isTimeStamp: bool,
|
||||
baseGasFees: string,
|
||||
totalFees: string,
|
||||
maxTotalFees: string
|
||||
): Item =
|
||||
result.id = id
|
||||
result.typ = typ
|
||||
|
@ -71,6 +77,9 @@ proc initItem*(
|
|||
result.txHash = txHash
|
||||
result.multiTransactionID = multiTransactionID
|
||||
result.isTimeStamp = isTimeStamp
|
||||
result.baseGasFees = baseGasFees
|
||||
result.totalFees = totalFees
|
||||
result.maxTotalFees = maxTotalFees
|
||||
|
||||
proc `$`*(self: Item): string =
|
||||
result = fmt"""AllTokensItem(
|
||||
|
@ -96,6 +105,9 @@ proc `$`*(self: Item): string =
|
|||
txHash: {self.txHash},
|
||||
multiTransactionID: {self.multiTransactionID},
|
||||
isTimeStamp: {self.isTimeStamp},
|
||||
baseGasFees: {self.baseGasFees},
|
||||
totalFees: {self.totalFees},
|
||||
maxTotalFees: {self.maxTotalFees},
|
||||
]"""
|
||||
|
||||
proc getId*(self: Item): string =
|
||||
|
@ -163,3 +175,12 @@ proc getMultiTransactionID*(self: Item): int =
|
|||
|
||||
proc getIsTimeStamp*(self: Item): bool =
|
||||
return self.isTimeStamp
|
||||
|
||||
proc getBaseGasFees*(self: Item): string =
|
||||
return self.baseGasFees
|
||||
|
||||
proc getTotalFees*(self: Item): string =
|
||||
return self.totalFees
|
||||
|
||||
proc getMaxTotalFees*(self: Item): string =
|
||||
return self.maxTotalFees
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
import NimQml, Tables, strutils, strformat, sequtils, tables, sugar, algorithm, std/[times, os], stint
|
||||
import NimQml, Tables, strutils, strformat, sequtils, tables, sugar, algorithm, std/[times, os], stint, parseutils
|
||||
|
||||
import ./item
|
||||
import ../../../../../app_service/service/eth/utils as eth_service_utils
|
||||
|
@ -28,6 +28,9 @@ type
|
|||
TxHash
|
||||
MultiTransactionID
|
||||
IsTimeStamp
|
||||
BaseGasFees
|
||||
TotalFees
|
||||
MaxTotalFees
|
||||
|
||||
QtObject:
|
||||
type
|
||||
|
@ -88,7 +91,10 @@ QtObject:
|
|||
ModelRole.Input.int:"input",
|
||||
ModelRole.TxHash.int:"txHash",
|
||||
ModelRole.MultiTransactionID.int:"multiTransactionID",
|
||||
ModelRole.IsTimeStamp.int: "isTimeStamp"
|
||||
ModelRole.IsTimeStamp.int: "isTimeStamp",
|
||||
ModelRole.BaseGasFees.int: "baseGasFees",
|
||||
ModelRole.TotalFees.int: "totalFees",
|
||||
ModelRole.MaxTotalFees.int: "maxTotalFees"
|
||||
}.toTable
|
||||
|
||||
method data(self: Model, index: QModelIndex, role: int): QVariant =
|
||||
|
@ -146,6 +152,12 @@ QtObject:
|
|||
result = newQVariant(item.getMultiTransactionID())
|
||||
of ModelRole.IsTimeStamp:
|
||||
result = newQVariant(item.getIsTimeStamp())
|
||||
of ModelRole.BaseGasFees:
|
||||
result = newQVariant(item.getBaseGasFees())
|
||||
of ModelRole.TotalFees:
|
||||
result = newQVariant(item.getTotalFees())
|
||||
of ModelRole.MaxTotalFees:
|
||||
result = newQVariant(item.getMaxTotalFees())
|
||||
|
||||
proc setItems*(self: Model, items: seq[Item]) =
|
||||
self.beginResetModel()
|
||||
|
@ -206,7 +218,10 @@ QtObject:
|
|||
t.input,
|
||||
t.txHash,
|
||||
t.multiTransactionID,
|
||||
false
|
||||
false,
|
||||
t.baseGasFees,
|
||||
t.totalFees,
|
||||
t.maxTotalFees,
|
||||
))
|
||||
|
||||
var allTxs = self.items.concat(newTxItems)
|
||||
|
@ -219,7 +234,7 @@ QtObject:
|
|||
for tx in allTxs:
|
||||
let duration = fromUnix(tx.getTimestamp()) - tempTimeStamp
|
||||
if(duration.inDays != 0):
|
||||
itemsWithDateHeaders.add(initItem("", "", "", "", "", tx.getTimestamp(), "", "", "", "", "", "", "", "", "", 0, "", "", "", "", 0, true))
|
||||
itemsWithDateHeaders.add(initItem("", "", "", "", "", tx.getTimestamp(), "", "", "", "", "", "", "", "", "", 0, "", "", "", "", 0, true, "", "", ""))
|
||||
itemsWithDateHeaders.add(tx)
|
||||
tempTimeStamp = fromUnix(tx.getTimestamp())
|
||||
|
||||
|
|
|
@ -113,3 +113,6 @@ method getChainIdForBrowser*(self: Module): int =
|
|||
|
||||
method getEstimatedTime*(self: Module, chainId: int, maxFeePerGas: string): int =
|
||||
return self.controller.getEstimatedTime(chainId, maxFeePerGas).int
|
||||
|
||||
method getLastTxBlockNumber*(self: Module): string =
|
||||
return self.controller.getLastTxBlockNumber()
|
||||
|
|
|
@ -150,3 +150,6 @@ QtObject:
|
|||
|
||||
proc getEstimatedTime*(self: View, chainId: int, maxFeePerGas: string): int {.slot.} =
|
||||
return self.delegate.getEstimatedTime(chainId, maxFeePerGas)
|
||||
|
||||
proc getLastTxBlockNumber*(self: View): string {.slot.} =
|
||||
return self.delegate.getLastTxBlockNumber()
|
||||
|
|
|
@ -49,6 +49,21 @@ type
|
|||
input*: string
|
||||
txHash*: string
|
||||
multiTransactionID*: int
|
||||
baseGasFees*: string
|
||||
totalFees*: string
|
||||
maxTotalFees*: string
|
||||
|
||||
|
||||
proc getTotalFees(tip: string, baseFee: string, gasUsed: string, maxFee: string): string =
|
||||
var maxFees = stint.fromHex(Uint256, maxFee)
|
||||
var totalGasUsed = stint.fromHex(Uint256, tip) + stint.fromHex(Uint256, baseFee)
|
||||
if totalGasUsed > maxFees:
|
||||
totalGasUsed = maxFees
|
||||
var totalGasUsedInHex = (totalGasUsed * stint.fromHex(Uint256, gasUsed)).toHex
|
||||
return totalGasUsedInHex
|
||||
|
||||
proc getMaxTotalFees(maxFee: string, gasLimit: string): string =
|
||||
return (stint.fromHex(Uint256, maxFee) * stint.fromHex(Uint256, gasLimit)).toHex
|
||||
|
||||
proc toTransactionDto*(jsonObj: JsonNode): TransactionDto =
|
||||
result = TransactionDto()
|
||||
|
@ -73,6 +88,9 @@ proc toTransactionDto*(jsonObj: JsonNode): TransactionDto =
|
|||
discard jsonObj.getProp("input", result.input)
|
||||
discard jsonObj.getProp("txHash", result.txHash)
|
||||
discard jsonObj.getProp("multiTransactionID", result.multiTransactionID)
|
||||
discard jsonObj.getProp("base_gas_fee", result.baseGasFees)
|
||||
result.totalFees = getTotalFees(result.maxPriorityFeePerGas, result.baseGasFees, result.gasUsed, result.maxFeePerGas)
|
||||
result.maxTotalFees = getMaxTotalFees(result.maxFeePerGas, result.gasLimit)
|
||||
|
||||
proc cmpTransactions*(x, y: TransactionDto): int =
|
||||
# Sort proc to compare transactions from a single account.
|
||||
|
|
|
@ -422,3 +422,11 @@ QtObject:
|
|||
except Exception as e:
|
||||
error "Error estimating transaction time", message = e.msg
|
||||
return EstimatedTime.Unknown
|
||||
|
||||
proc getLastTxBlockNumber*(self: Service, chainId: int): string =
|
||||
try:
|
||||
let response = eth.getBlockByNumber(chainId, "latest")
|
||||
return response.result{"number"}.getStr
|
||||
except Exception as e:
|
||||
error "Error getting latest block number", message = e.msg
|
||||
return ""
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 7108ac87cffe529d011ec1c14473630e52980282
|
||||
Subproject commit c3bbb396ecd5ad25df565d64429aaba869df4b49
|
|
@ -54,6 +54,7 @@ Item {
|
|||
id: walletContainer
|
||||
RightTabView {
|
||||
store: root.store
|
||||
contactsStore: root.contactsStore
|
||||
sendModal: root.sendModal
|
||||
}
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@ import StatusQ.Controls 0.1
|
|||
import utils 1.0
|
||||
import shared.views 1.0
|
||||
|
||||
import "./"
|
||||
import "../stores"
|
||||
import "../panels"
|
||||
import "../views/collectibles"
|
||||
|
@ -15,6 +16,7 @@ Item {
|
|||
|
||||
property alias currentTabIndex: walletTabBar.currentIndex
|
||||
property var store
|
||||
property var contactsStore
|
||||
property var sendModal
|
||||
|
||||
ColumnLayout {
|
||||
|
@ -80,6 +82,10 @@ Item {
|
|||
}
|
||||
HistoryView {
|
||||
account: RootStore.currentAccount
|
||||
onLaunchTransactionDetail: {
|
||||
transactionDetailView.transaction = transaction
|
||||
stack.currentIndex = 3
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -94,6 +100,14 @@ Item {
|
|||
Layout.fillHeight: true
|
||||
onGoBack: stack.currentIndex = 0
|
||||
}
|
||||
TransactionDetailView {
|
||||
id: transactionDetailView
|
||||
Layout.fillWidth: true
|
||||
Layout.fillHeight: true
|
||||
sendModal: root.sendModal
|
||||
contactsStore: root.contactsStore
|
||||
onGoBack: stack.currentIndex = 0
|
||||
}
|
||||
}
|
||||
|
||||
WalletFooter {
|
||||
|
|
|
@ -26,6 +26,16 @@ Item {
|
|||
id: _internal
|
||||
property bool loading: false
|
||||
property string error: ""
|
||||
function saveAddress(name, address) {
|
||||
loading = true
|
||||
error = RootStore.createOrUpdateSavedAddress(name, address)
|
||||
loading = false
|
||||
}
|
||||
function deleteSavedAddress(address) {
|
||||
loading = true
|
||||
error = RootStore.deleteSavedAddress(address)
|
||||
loading = false
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
|
@ -65,155 +75,6 @@ Item {
|
|||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: delegateSavedAddress
|
||||
StatusListItem {
|
||||
id: savedAddress
|
||||
title: name
|
||||
objectName: name
|
||||
subTitle: name + " \u2022 " + Utils.getElidedCompressedPk(address)
|
||||
implicitWidth: parent.width
|
||||
color: "transparent"
|
||||
border.color: Theme.palette.baseColor5
|
||||
//TODO uncomment when #6456 is fixed
|
||||
//titleTextIcon: RootStore.favouriteAddress ? "star-icon" : ""
|
||||
statusListItemComponentsSlot.spacing: 0
|
||||
property bool showButtons: sensor.containsMouse
|
||||
|
||||
components: [
|
||||
StatusRoundButton {
|
||||
icon.color: savedAddress.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "send"
|
||||
onClicked: {
|
||||
root.sendModal.open(address);
|
||||
}
|
||||
},
|
||||
CopyToClipBoardButton {
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.color: savedAddress.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
store: RootStore
|
||||
textToCopy: address
|
||||
},
|
||||
//TODO uncomment when #6456 is fixed
|
||||
// StatusRoundButton {
|
||||
// icon.color: savedAddress.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
// type: StatusRoundButton.Type.Tertiary
|
||||
// icon.name: savedAddress.favouriteAddress ? "favourite" : "unfavourite"
|
||||
// onClicked: {
|
||||
// RootStore.setFavourite();
|
||||
// }
|
||||
// },
|
||||
StatusRoundButton {
|
||||
icon.color: savedAddress.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "more"
|
||||
onClicked: {
|
||||
editDeleteMenu.openMenu(name, address);
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
StatusPopupMenu {
|
||||
id: editDeleteMenu
|
||||
property string contactName
|
||||
property string contactAddress
|
||||
function openMenu(name, address) {
|
||||
contactName = name;
|
||||
contactAddress = address;
|
||||
popup();
|
||||
}
|
||||
onClosed: {
|
||||
contactName = "";
|
||||
contactAddress = "";
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: qsTr("Edit")
|
||||
objectName: "editSavedAddress"
|
||||
icon.name: "pencil-outline"
|
||||
onTriggered: {
|
||||
Global.openPopup(addEditSavedAddress,
|
||||
{
|
||||
edit: true,
|
||||
address: editDeleteMenu.contactAddress,
|
||||
name: editDeleteMenu.contactName
|
||||
})
|
||||
}
|
||||
}
|
||||
StatusMenuSeparator { }
|
||||
StatusMenuItem {
|
||||
text: qsTr("Delete")
|
||||
type: StatusMenuItem.Type.Danger
|
||||
icon.name: "delete"
|
||||
objectName: "deleteSavedAddress"
|
||||
onTriggered: {
|
||||
deleteAddressConfirm.name = editDeleteMenu.contactName;
|
||||
deleteAddressConfirm.address = editDeleteMenu.contactAddress;
|
||||
deleteAddressConfirm.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: addEditSavedAddress
|
||||
AddEditSavedAddressPopup {
|
||||
id: addEditModal
|
||||
anchors.centerIn: parent
|
||||
onClosed: destroy()
|
||||
contactsStore: root.contactsStore
|
||||
onSave: {
|
||||
_internal.loading = true
|
||||
_internal.error = RootStore.createOrUpdateSavedAddress(name, address)
|
||||
_internal.loading = false
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
id: deleteAddressConfirm
|
||||
property string address
|
||||
property string name
|
||||
// NOTE: the `text` property was created as a workaround because
|
||||
// setting StatusBaseText.text to `qsTr("...").arg("...")`
|
||||
// caused no text to render
|
||||
property string text: qsTr("Are you sure you want to remove '%1' from your saved addresses?").arg(name)
|
||||
anchors.centerIn: parent
|
||||
header.title: qsTr("Are you sure?")
|
||||
header.subTitle: name
|
||||
contentItem: StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
height: contentHeight + topPadding + bottomPadding
|
||||
text: deleteAddressConfirm.text
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
wrapMode: Text.Wrap
|
||||
topPadding: Style.current.padding
|
||||
rightPadding: Style.current.padding
|
||||
bottomPadding: Style.current.padding
|
||||
leftPadding: Style.current.padding
|
||||
}
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: deleteAddressConfirm.close()
|
||||
},
|
||||
StatusButton {
|
||||
type: StatusBaseButton.Type.Danger
|
||||
objectName: "confirmDeleteSavedAddress"
|
||||
text: qsTr("Delete")
|
||||
onClicked: {
|
||||
_internal.loading = true
|
||||
_internal.error = RootStore.deleteSavedAddress(deleteAddressConfirm.address)
|
||||
deleteAddressConfirm.close()
|
||||
_internal.loading = false
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
SavedAddressesError {
|
||||
id: errorMessage
|
||||
anchors.top: header.bottom
|
||||
|
@ -242,6 +103,32 @@ Item {
|
|||
visible: listView.count > 0
|
||||
spacing: 5
|
||||
model: RootStore.savedAddresses
|
||||
delegate: delegateSavedAddress
|
||||
delegate: SavedAddressesDelegate {
|
||||
name: model.name
|
||||
address: model.address
|
||||
store: RootStore
|
||||
contactsStore: root.contactsStore
|
||||
onOpenSendModal: root.sendModal.open(address);
|
||||
saveAddress: function(name, address) {
|
||||
_internal.saveAddress(name, address)
|
||||
}
|
||||
deleteSavedAddress: function(address) {
|
||||
_internal.deleteSavedAddress(address)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: addEditSavedAddress
|
||||
AddEditSavedAddressPopup {
|
||||
id: addEditModal
|
||||
anchors.centerIn: parent
|
||||
onClosed: destroy()
|
||||
contactsStore: root.contactsStore
|
||||
onSave: {
|
||||
_internal.saveAddress(name, address)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,176 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import utils 1.0
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
import shared.controls 1.0
|
||||
|
||||
import "../popups"
|
||||
import "../controls"
|
||||
|
||||
StatusListItem {
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property var contactsStore
|
||||
property string name
|
||||
property string address
|
||||
property var saveAddress: function (name, address) {}
|
||||
property var deleteSavedAddress: function (address) {}
|
||||
|
||||
signal openSendModal()
|
||||
|
||||
implicitWidth: parent.width
|
||||
|
||||
title: name
|
||||
objectName: name
|
||||
subTitle: name + " \u2022 " + Utils.getElidedCompressedPk(address)
|
||||
color: "transparent"
|
||||
border.color: Theme.palette.baseColor5
|
||||
//TODO uncomment when #6456 is fixed
|
||||
//titleTextIcon: RootStore.favouriteAddress ? "star-icon" : ""
|
||||
statusListItemComponentsSlot.spacing: 0
|
||||
property bool showButtons: sensor.containsMouse
|
||||
|
||||
components: [
|
||||
StatusRoundButton {
|
||||
icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "send"
|
||||
onClicked: openSendModal()
|
||||
},
|
||||
CopyToClipBoardButton {
|
||||
id: copyButton
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
store: root.store
|
||||
textToCopy: root.address
|
||||
},
|
||||
//TODO uncomment when #6456 is fixed
|
||||
// StatusRoundButton {
|
||||
// icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
// type: StatusRoundButton.Type.Tertiary
|
||||
// icon.name: root.favouriteAddress ? "favourite" : "unfavourite"
|
||||
// onClicked: {
|
||||
// RootStore.setFavourite();
|
||||
// }
|
||||
// },
|
||||
StatusRoundButton {
|
||||
visible: !!root.name
|
||||
icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "more"
|
||||
onClicked: {
|
||||
editDeleteMenu.openMenu(root.name, root.address);
|
||||
}
|
||||
},
|
||||
StatusRoundButton {
|
||||
visible: !root.name
|
||||
icon.color: root.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
icon.name: "add"
|
||||
onClicked: {
|
||||
Global.openPopup(addEditSavedAddress,
|
||||
{
|
||||
addAddress: true,
|
||||
address: root.address
|
||||
})
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
StatusPopupMenu {
|
||||
id: editDeleteMenu
|
||||
property string contactName
|
||||
property string contactAddress
|
||||
function openMenu(name, address) {
|
||||
contactName = name;
|
||||
contactAddress = address;
|
||||
popup();
|
||||
}
|
||||
onClosed: {
|
||||
contactName = "";
|
||||
contactAddress = "";
|
||||
}
|
||||
StatusMenuItem {
|
||||
text: qsTr("Edit")
|
||||
objectName: "editroot"
|
||||
assetSettings.name: "pencil-outline"
|
||||
onTriggered: {
|
||||
Global.openPopup(addEditSavedAddress,
|
||||
{
|
||||
edit: true,
|
||||
address: editDeleteMenu.contactAddress,
|
||||
name: editDeleteMenu.contactName
|
||||
})
|
||||
}
|
||||
}
|
||||
StatusMenuSeparator { }
|
||||
StatusMenuItem {
|
||||
text: qsTr("Delete")
|
||||
type: StatusMenuItem.Type.Danger
|
||||
assetSettings.name: "delete"
|
||||
objectName: "deleteSavedAddress"
|
||||
onTriggered: {
|
||||
deleteAddressConfirm.name = editDeleteMenu.contactName;
|
||||
deleteAddressConfirm.address = editDeleteMenu.contactAddress;
|
||||
deleteAddressConfirm.open()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: addEditSavedAddress
|
||||
AddEditSavedAddressPopup {
|
||||
id: addEditModal
|
||||
anchors.centerIn: parent
|
||||
onClosed: destroy()
|
||||
contactsStore: root.contactsStore
|
||||
onSave: {
|
||||
root.saveAddress(name, address)
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
id: deleteAddressConfirm
|
||||
property string address
|
||||
property string name
|
||||
anchors.centerIn: parent
|
||||
header.title: qsTr("Are you sure?")
|
||||
header.subTitle: name
|
||||
contentItem: StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
height: contentHeight + topPadding + bottomPadding
|
||||
text: qsTr("Are you sure you want to remove '%1' from your saved addresses?").arg(name)
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
wrapMode: Text.Wrap
|
||||
topPadding: Style.current.padding
|
||||
rightPadding: Style.current.padding
|
||||
bottomPadding: Style.current.padding
|
||||
leftPadding: Style.current.padding
|
||||
}
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
text: qsTr("Cancel")
|
||||
onClicked: deleteAddressConfirm.close()
|
||||
},
|
||||
StatusButton {
|
||||
type: StatusBaseButton.Type.Danger
|
||||
objectName: "confirmDeleteSavedAddress"
|
||||
text: qsTr("Delete")
|
||||
onClicked: {
|
||||
root.deleteSavedAddress(deleteAddressConfirm.address)
|
||||
deleteAddressConfirm.close()
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
|
@ -25,12 +25,13 @@ StatusListItem {
|
|||
property string resolvedSymbol: root.symbol != "" ? root.symbol : "ETH"
|
||||
property string savedAddressName
|
||||
|
||||
state: "normal"
|
||||
asset.isImage: true
|
||||
asset.name: Style.png("tokens/%1".arg(resolvedSymbol))
|
||||
statusListItemTitle.font.weight: Font.Medium
|
||||
title: isIncoming ? qsTr("Receive %1").arg(resolvedSymbol) : !!savedAddressName ?
|
||||
title: modelData !== undefined && !!modelData ?
|
||||
isIncoming ? qsTr("Receive %1").arg(resolvedSymbol) : !!savedAddressName ?
|
||||
qsTr("Send %1 to %2").arg(resolvedSymbol).arg(savedAddressName) :
|
||||
qsTr("Send %1 to %2").arg(resolvedSymbol).arg(Utils.compactAddress(modelData.to, 4))
|
||||
qsTr("Send %1 to %2").arg(resolvedSymbol).arg(Utils.compactAddress(modelData.to, 4)): ""
|
||||
subTitle: shortTimeStamp
|
||||
inlineTagModel: 1
|
||||
inlineTagDelegate: InformationTag {
|
||||
|
@ -60,8 +61,8 @@ StatusListItem {
|
|||
height: 18
|
||||
}
|
||||
StatusBaseText {
|
||||
id: cryptoValueText
|
||||
text: "%1 %2".arg(cryptoValue).arg(resolvedSymbol)
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
|
@ -92,4 +93,41 @@ StatusListItem {
|
|||
height: 10
|
||||
}
|
||||
}
|
||||
|
||||
states: [
|
||||
State {
|
||||
name: "normal"
|
||||
PropertyChanges {
|
||||
target: asset
|
||||
width: 40
|
||||
height: 40
|
||||
}
|
||||
PropertyChanges {
|
||||
target: statusListItemTitle
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 15
|
||||
}
|
||||
PropertyChanges {
|
||||
target: cryptoValueText
|
||||
font.pixelSize: 15
|
||||
}
|
||||
},
|
||||
State {
|
||||
name: "big"
|
||||
PropertyChanges {
|
||||
target: asset
|
||||
width: 50
|
||||
height: 50
|
||||
}
|
||||
PropertyChanges {
|
||||
target: statusListItemTitle
|
||||
font.weight: Font.Bold
|
||||
font.pixelSize: 17
|
||||
}
|
||||
PropertyChanges {
|
||||
target: cryptoValueText
|
||||
font.pixelSize: 17
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -27,3 +27,5 @@ InformationTile 1.0 InformationTile.qml
|
|||
SocialLinkPreview 1.0 SocialLinkPreview.qml
|
||||
AssetsDetailsHeader 1.0 AssetsDetailsHeader.qml
|
||||
InformationTag 1.0 InformationTag.qml
|
||||
TransactionDetailsHeader.qml 1.0 TransactionDetailsHeader.qml
|
||||
SavedAddressesDelegate 1.0 SavedAddressesDelegate.qml
|
||||
|
|
|
@ -0,0 +1,115 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQml.Models 2.14
|
||||
|
||||
import utils 1.0
|
||||
import shared.controls 1.0
|
||||
import shared.panels 1.0
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Controls.Validators 0.1
|
||||
import StatusQ.Popups.Dialog 0.1
|
||||
|
||||
import "../stores"
|
||||
|
||||
StatusDialog {
|
||||
id: root
|
||||
|
||||
property bool edit: false
|
||||
property bool addAddress: false
|
||||
property string address
|
||||
property alias name: nameInput.text
|
||||
property var contactsStore
|
||||
|
||||
signal save(string name, string address)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
property int validationMode: root.edit ?
|
||||
StatusInput.ValidationMode.Always
|
||||
: StatusInput.ValidationMode.OnlyWhenDirty
|
||||
property bool valid: addressInput.isValid && nameInput.valid // TODO: Add network preference and emoji
|
||||
property bool dirty: nameInput.input.dirty
|
||||
}
|
||||
|
||||
width: 574
|
||||
height: 490
|
||||
|
||||
header: StatusDialogHeader {
|
||||
headline.title: edit ? qsTr("Edit saved address") : qsTr("Add saved address")
|
||||
headline.subtitle: edit ? name : ""
|
||||
}
|
||||
|
||||
onOpened: {
|
||||
if(edit || addAddress) {
|
||||
addressInput.input.text = root.address
|
||||
}
|
||||
nameInput.input.edit.forceActiveFocus(Qt.MouseFocusReason)
|
||||
}
|
||||
|
||||
Column {
|
||||
width: parent.width
|
||||
height: childrenRect.height
|
||||
topPadding: Style.current.xlPadding
|
||||
|
||||
spacing: Style.current.bigPadding
|
||||
|
||||
StatusInput {
|
||||
id: nameInput
|
||||
implicitWidth: parent.width
|
||||
input.edit.objectName: "savedAddressNameInput"
|
||||
minimumHeight: 56
|
||||
maximumHeight: 56
|
||||
placeholderText: qsTr("Enter a name")
|
||||
label: qsTr("Name")
|
||||
validators: [
|
||||
StatusMinLengthValidator {
|
||||
minLength: 1
|
||||
errorMessage: qsTr("Name must not be blank")
|
||||
},
|
||||
StatusRegularExpressionValidator {
|
||||
regularExpression: /^[^<>]+$/
|
||||
errorMessage: qsTr("This is not a valid account name")
|
||||
}
|
||||
]
|
||||
charLimit: 40
|
||||
validationMode: d.validationMode
|
||||
}
|
||||
|
||||
// To-Do use StatusInput within the below component
|
||||
RecipientSelector {
|
||||
id: addressInput
|
||||
implicitWidth: parent.width
|
||||
inputWidth: implicitWidth
|
||||
accounts: RootStore.accounts
|
||||
contactsStore: root.contactsStore
|
||||
label: qsTr("Address")
|
||||
input.textField.objectName: "savedAddressAddressInput"
|
||||
input.placeholderText: qsTr("Enter ENS Name or Ethereum Address")
|
||||
labelFont.pixelSize: 15
|
||||
labelFont.weight: Font.Normal
|
||||
input.implicitHeight: 56
|
||||
input.textField.anchors.rightMargin: 0
|
||||
isSelectorVisible: false
|
||||
addContactEnabled: false
|
||||
onSelectedRecipientChanged: {
|
||||
root.address = selectedRecipient.address
|
||||
}
|
||||
readOnly: root.edit || root.addAddress
|
||||
wrongInputValidationError: qsTr("Please enter a valid ENS name OR Ethereum Address")
|
||||
}
|
||||
}
|
||||
|
||||
footer: StatusDialogFooter {
|
||||
rightButtons: ObjectModel {
|
||||
StatusButton {
|
||||
text: root.edit ? qsTr("Save") : qsTr("Add address")
|
||||
enabled: d.valid && d.dirty
|
||||
onClicked: root.save(name, address)
|
||||
objectName: "addSavedAddress"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -21,3 +21,4 @@ ProfilePopup 1.0 ProfilePopup.qml
|
|||
ImageCropWorkflow 1.0 ImageCropWorkflow.qml
|
||||
ImportCommunityPopup 1.0 ImportCommunityPopup.qml
|
||||
DisplayNamePopup 1.0 DisplayNamePopup.qml
|
||||
AddEditSavedAddressPopup 1.0 AddEditSavedAddressPopup.qml
|
||||
|
|
|
@ -38,6 +38,7 @@ QtObject {
|
|||
property var historyTransactions: walletSectionTransactions.model
|
||||
property bool isNonArchivalNode: history.isNonArchivalNode
|
||||
|
||||
property var currentAccount: walletSectionCurrent
|
||||
property var walletTokensModule: walletSectionAllTokens
|
||||
property var tokens: walletSectionAllTokens.all
|
||||
property var accounts: walletSectionAccounts.model
|
||||
|
@ -170,6 +171,10 @@ QtObject {
|
|||
return globalUtils.hex2Eth(value)
|
||||
}
|
||||
|
||||
function hex2Gwei(value) {
|
||||
return globalUtils.hex2Gwei(value)
|
||||
}
|
||||
|
||||
function findTokenSymbolByAddress(address) {
|
||||
return walletSectionAllTokens.findTokenSymbolByAddress(address)
|
||||
|
||||
|
@ -178,4 +183,20 @@ QtObject {
|
|||
function getNameForSavedWalletAddress(address) {
|
||||
return walletSectionSavedAddresses.getNameByAddress(address)
|
||||
}
|
||||
|
||||
function createOrUpdateSavedAddress(name, address) {
|
||||
return walletSectionSavedAddresses.createOrUpdateSavedAddress(name, address)
|
||||
}
|
||||
|
||||
function deleteSavedAddress(address) {
|
||||
return walletSectionSavedAddresses.deleteSavedAddress(address)
|
||||
}
|
||||
|
||||
function getLatestBlockNumber() {
|
||||
return walletSectionTransactions.getLastTxBlockNumber()
|
||||
}
|
||||
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
return profileSectionModule.ensUsernamesModule.getGasEthValue(gweiValue, gasLimit)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,6 +21,8 @@ ColumnLayout {
|
|||
property int pageSize: 20 // number of transactions per page
|
||||
property bool isLoading: false
|
||||
|
||||
signal launchTransactionDetail(var transaction)
|
||||
|
||||
function fetchHistory() {
|
||||
if (RootStore.isFetchingHistory(historyView.account.address)) {
|
||||
isLoading = true
|
||||
|
@ -99,7 +101,7 @@ ColumnLayout {
|
|||
StatusListItem {
|
||||
property var modelData
|
||||
height: 40
|
||||
title: Utils.formatShortDate(modelData.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat)
|
||||
title: modelData !== undefined && !!modelData ? Utils.formatShortDate(modelData.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat) : ""
|
||||
statusListItemTitle.color: Theme.palette.baseColor1
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
sensor.enabled: false
|
||||
|
@ -109,21 +111,18 @@ ColumnLayout {
|
|||
Component {
|
||||
id: transactionDelegate
|
||||
TransactionDelegate {
|
||||
isIncoming: modelData !== undefined ? modelData.to === account.address: false
|
||||
isIncoming: modelData !== undefined && !!modelData ? modelData.to === account.address: false
|
||||
currentCurrency: RootStore.currentCurrency
|
||||
cryptoValue: modelData !== undefined ? RootStore.hex2Eth(modelData.value) : ""
|
||||
cryptoValue: modelData !== undefined && !!modelData ? RootStore.hex2Eth(modelData.value) : ""
|
||||
fiatValue: RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency)
|
||||
networkIcon: modelData !== undefined ? RootStore.getNetworkIcon(modelData.chainId) : ""
|
||||
networkColor: modelData !== undefined ? RootStore.getNetworkColor(modelData.chainId) : ""
|
||||
networkName: modelData !== undefined ? RootStore.getNetworkShortName(modelData.chainId) : ""
|
||||
symbol: modelData !== undefined ? RootStore.findTokenSymbolByAddress(modelData.contract) : ""
|
||||
transferStatus: modelData !== undefined ? RootStore.hex2Dec(modelData.txStatus) : ""
|
||||
shortTimeStamp: modelData !== undefined ? Utils.formatShortTime(modelData.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat) : ""
|
||||
savedAddressName: modelData !== undefined ? RootStore.getNameForSavedWalletAddress(modelData.to) : ""
|
||||
onClicked: {
|
||||
transactionModal.transaction = modelData
|
||||
transactionModal.open()
|
||||
}
|
||||
networkIcon: modelData !== undefined && !!modelData ? RootStore.getNetworkIcon(modelData.chainId) : ""
|
||||
networkColor: modelData !== undefined && !!modelData ? RootStore.getNetworkColor(modelData.chainId) : ""
|
||||
networkName: modelData !== undefined && !!modelData ? RootStore.getNetworkShortName(modelData.chainId) : ""
|
||||
symbol: modelData !== undefined && !!modelData ? RootStore.findTokenSymbolByAddress(modelData.contract) : ""
|
||||
transferStatus: modelData !== undefined && !!modelData ? RootStore.hex2Dec(modelData.txStatus) : ""
|
||||
shortTimeStamp: modelData !== undefined && !!modelData ? Utils.formatShortTime(modelData.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat) : ""
|
||||
savedAddressName: modelData !== undefined && !!modelData ? RootStore.getNameForSavedWalletAddress(modelData.to) : ""
|
||||
onClicked: launchTransactionDetail(modelData)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -131,8 +130,4 @@ ColumnLayout {
|
|||
id: loadingImageComponent
|
||||
StatusLoadingIndicator {}
|
||||
}
|
||||
|
||||
TransactionModal {
|
||||
id: transactionModal
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,250 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Window 2.12
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import shared.controls 1.0
|
||||
import utils 1.0
|
||||
|
||||
import "../stores"
|
||||
import "../controls"
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property var currentAccount: RootStore.currentAccount
|
||||
property var contactsStore
|
||||
property var transaction
|
||||
property var sendModal
|
||||
|
||||
signal goBack()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property bool isIncoming: root.transaction !== undefined && !!root.transaction ? root.transaction.to === currentAccount.address : false
|
||||
readonly property string savedAddressNameTo: root.transaction !== undefined && !!root.transaction ? d.getNameForSavedWalletAddress(transaction.to) : ""
|
||||
readonly property string savedAddressNameFrom: root.transaction !== undefined && !!root.transaction ? d.getNameForSavedWalletAddress(transaction.from): ""
|
||||
readonly property string from: root.transaction !== undefined && !!root.transaction ? !!savedAddressNameFrom ? savedAddressNameFrom : Utils.compactAddress(transaction.from, 4): ""
|
||||
readonly property string to: root.transaction !== undefined && !!root.transaction ? !!savedAddressNameTo ? savedAddressNameTo : Utils.compactAddress(transaction.to, 4): ""
|
||||
|
||||
function getNameForSavedWalletAddress(address) {
|
||||
return RootStore.getNameForSavedWalletAddress(address)
|
||||
}
|
||||
}
|
||||
|
||||
StatusFlatButton {
|
||||
id: backButton
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
Layout.alignment: Qt.AlignTop
|
||||
anchors.topMargin: -Style.current.xlPadding
|
||||
anchors.leftMargin: -Style.current.xlPadding
|
||||
icon.name: "arrow-left"
|
||||
icon.width: 20
|
||||
icon.height: 20
|
||||
text: qsTr("Activity")
|
||||
size: StatusBaseButton.Size.Large
|
||||
onClicked: root.goBack()
|
||||
}
|
||||
|
||||
StatusScrollView {
|
||||
anchors.top: backButton.bottom
|
||||
anchors.left: parent.left
|
||||
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
contentHeight: column.height
|
||||
contentWidth: parent.width
|
||||
|
||||
Column {
|
||||
id: column
|
||||
width: parent.width - Style.current.xlPadding
|
||||
|
||||
spacing: Style.current.bigPadding
|
||||
|
||||
TransactionDelegate {
|
||||
width: parent.width
|
||||
|
||||
modelData: transaction
|
||||
isIncoming: d.isIncoming
|
||||
currentCurrency: RootStore.currentCurrency
|
||||
cryptoValue: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Eth(transaction.value): ""
|
||||
fiatValue: root.transaction !== undefined && !!root.transaction ? RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency): ""
|
||||
networkIcon: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkIcon(transaction.chainId): ""
|
||||
networkColor: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkColor(transaction.chainId): ""
|
||||
networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): ""
|
||||
symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): ""
|
||||
transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): ""
|
||||
shortTimeStamp: root.transaction !== undefined && !!root.transaction ? Utils.formatShortTime(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat): ""
|
||||
savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
|
||||
title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) :
|
||||
qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to)
|
||||
sensor.enabled: false
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
state: "big"
|
||||
}
|
||||
|
||||
SavedAddressesDelegate {
|
||||
width: parent.width
|
||||
|
||||
name: d.isIncoming ? d.savedAddressNameFrom : d.savedAddressNameTo
|
||||
address: root.transaction !== undefined && !!root.transaction ? d.isIncoming ? transaction.from : transaction.to : ""
|
||||
title: d.isIncoming ? d.from : d.to
|
||||
subTitle: root.transaction !== undefined && !!root.transaction ? d.isIncoming ? !!d.savedAddressNameFrom ? Utils.compactAddress(transaction.from, 4) : "" : !!d.savedAddressNameTo ? Utils.compactAddress(transaction.to, 4) : "": ""
|
||||
store: RootStore
|
||||
contactsStore: root.contactsStore
|
||||
onOpenSendModal: root.sendModal.open(address);
|
||||
saveAddress: function(name, address) {
|
||||
RootStore.createOrUpdateSavedAddress(name, address)
|
||||
}
|
||||
deleteSavedAddress: function(address) {
|
||||
RootStore.deleteSavedAddress(address)
|
||||
}
|
||||
}
|
||||
|
||||
StatusExpandableItem {
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
type: StatusExpandableItem.Type.Tertiary
|
||||
expandable: true
|
||||
primaryText: qsTr("Transaction summary")
|
||||
expandableComponent: transactionSummary
|
||||
separatorVisible: false
|
||||
expanded: true
|
||||
}
|
||||
|
||||
StatusExpandableItem {
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
type: StatusExpandableItem.Type.Tertiary
|
||||
expandable: true
|
||||
primaryText: qsTr("Fees")
|
||||
expandableComponent: fees
|
||||
expanded: true
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
id: data
|
||||
width: parent.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: Theme.palette.directColor8
|
||||
|
||||
statusListItemTitle.color: Theme.palette.baseColor1
|
||||
|
||||
title: qsTr("Data" )
|
||||
subTitle: root.transaction !== undefined && !!root.transaction ? root.transaction.input : ""
|
||||
components: [
|
||||
CopyToClipBoardButton {
|
||||
icon.width: 15
|
||||
icon.height: 15
|
||||
type: StatusRoundButton.Type.Tertiary
|
||||
color: "transparent"
|
||||
icon.color: data.showButtons ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
store: RootStore
|
||||
textToCopy: data.subTitle
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Component {
|
||||
id: transactionSummary
|
||||
Column {
|
||||
id: column
|
||||
width: parent.width
|
||||
spacing: 8
|
||||
TransactionDelegate {
|
||||
width: parent.width
|
||||
modelData: transaction
|
||||
isIncoming: d.isIncoming
|
||||
currentCurrency: RootStore.currentCurrency
|
||||
cryptoValue: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Eth(transaction.value): ""
|
||||
fiatValue: RootStore.getFiatValue(cryptoValue, resolvedSymbol, RootStore.currentCurrency)
|
||||
networkIcon: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkIcon(transaction.chainId) : ""
|
||||
networkColor: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkColor(transaction.chainId): ""
|
||||
networkName: root.transaction !== undefined && !!root.transaction ? RootStore.getNetworkShortName(transaction.chainId): ""
|
||||
symbol: root.transaction !== undefined && !!root.transaction ? RootStore.findTokenSymbolByAddress(transaction.contract): ""
|
||||
transferStatus: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(transaction.txStatus): ""
|
||||
shortTimeStamp: root.transaction !== undefined && !!root.transaction ? Utils.formatShortTime(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat): ""
|
||||
savedAddressName: root.transaction !== undefined && !!root.transaction ? RootStore.getNameForSavedWalletAddress(transaction.to): ""
|
||||
title: d.isIncoming ? qsTr("Received %1 %2 from %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.from) :
|
||||
qsTr("Sent %1 %2 to %3").arg(cryptoValue).arg(resolvedSymbol).arg(d.to)
|
||||
sensor.enabled: false
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
border.width: 1
|
||||
border.color: Theme.palette.directColor8
|
||||
}
|
||||
Row {
|
||||
spacing: 8
|
||||
InformationTile {
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("Time")
|
||||
secondaryText: root.transaction !== undefined && !!root.transaction ? qsTr("%1 <font color=\"#939BA1\">on</font> %2").
|
||||
arg(Utils.formatShortTime(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat)).
|
||||
arg(Utils.formatShortDate(transaction.timestamp * 1000, RootStore.accountSensitiveSettings.is24hTimeFormat)): ""
|
||||
}
|
||||
InformationTile {
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("Confirmations")
|
||||
secondaryText: {
|
||||
if(root.transaction !== undefined && !!root.transaction )
|
||||
return Math.abs(RootStore.getLatestBlockNumber() - RootStore.hex2Dec(root.transaction.blockNumber))
|
||||
else
|
||||
return ""
|
||||
}
|
||||
}
|
||||
InformationTile {
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("Nonce")
|
||||
secondaryText: root.transaction !== undefined && !!root.transaction ? RootStore.hex2Dec(root.transaction.nonce) : ""
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: fees
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: 8
|
||||
Row {
|
||||
spacing: 8
|
||||
InformationTile {
|
||||
id: baseFee
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("Base fee")
|
||||
secondaryText: root.transaction !== undefined && !!root.transaction ? qsTr("%1 Gwei").arg(RootStore.hex2Gwei(root.transaction.baseGasFees)) : ""
|
||||
}
|
||||
InformationTile {
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("Tip")
|
||||
secondaryText: root.transaction !== undefined && !!root.transaction ? qsTr("%1 Gwei <font color=\"#939BA1\">• Max: %2 Gwei</font>").
|
||||
arg(RootStore.hex2Gwei(root.transaction.maxPriorityFeePerGas)).
|
||||
arg(RootStore.hex2Gwei(root.transaction.maxFeePerGas)) : ""
|
||||
secondaryLabel.textFormat: Text.RichText
|
||||
}
|
||||
}
|
||||
InformationTile {
|
||||
maxWidth: parent.width
|
||||
primaryText: qsTr("Total fee")
|
||||
secondaryText: root.transaction !== undefined && !!root.transaction ? qsTr("%1 Gwei <font color=\"#939BA1\">• Max: %2 Gwei</font>").
|
||||
arg(Utils.stripTrailingZeros(RootStore.hex2Gwei(root.transaction.totalFees))).
|
||||
arg(Utils.stripTrailingZeros(RootStore.hex2Gwei(root.transaction.maxTotalFees))) : ""
|
||||
secondaryLabel.textFormat: Text.RichText
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -11,3 +11,4 @@ ProfileView 1.0 ProfileView.qml
|
|||
AssetsView 1.0 AssetsView.qml
|
||||
HistoryView 1.0 HistoryView.qml
|
||||
AssetsDetailView 1.0 AssetsDetailView.qml
|
||||
TransactionDetailView 1.0 TransactionDetailView.qml
|
||||
|
|
|
@ -1 +1 @@
|
|||
Subproject commit 65be6f2b96d72161bfa23a384e9d0f2ccfc85c6a
|
||||
Subproject commit 1485b3b4c808dd875d30f17e4be842fcc44c8d35
|
Loading…
Reference in New Issue