parent
f84404c956
commit
17aaec2d53
|
@ -85,6 +85,10 @@ method getFiatValue*(self: AccessInterface, cryptoBalance: string, cryptoSymbol:
|
|||
{.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getCryptoValue*(self: AccessInterface, fiatAmount: string, cryptoSymbol: string, fiatSymbol: string): string
|
||||
{.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
method getGasEthValue*(self: AccessInterface, gweiValue: string, gasLimit: string): string {.base.} =
|
||||
raise newException(ValueError, "No implementation available")
|
||||
|
||||
|
|
|
@ -339,6 +339,20 @@ method getFiatValue*(self: Module, cryptoBalance: string, cryptoSymbol: string,
|
|||
let value = floatCryptoBalance * price
|
||||
return fmt"{value}"
|
||||
|
||||
method getCryptoValue*(self: Module, fiatAmount: string, cryptoSymbol: string, fiatSymbol: string): string =
|
||||
var fiatAmountBalance: float = 0
|
||||
try:
|
||||
fiatAmountBalance = parseFloat(fiatAmount)
|
||||
except ValueError:
|
||||
return "0.00"
|
||||
|
||||
if (fiatAmount == "" or cryptoSymbol == "" or fiatSymbol == ""):
|
||||
return "0.00"
|
||||
|
||||
let price = self.controller.getPrice(cryptoSymbol, fiatSymbol)
|
||||
let value = fiatAmountBalance / price
|
||||
return fmt"{value}"
|
||||
|
||||
method getGasEthValue*(self: Module, gweiValue: string, gasLimit: string): string {.slot.} =
|
||||
var gasLimitInt:int
|
||||
|
||||
|
|
|
@ -126,6 +126,9 @@ QtObject:
|
|||
proc getFiatValue*(self: View, cryptoBalance: string, cryptoSymbol: string, fiatSymbol: string): string {.slot.} =
|
||||
return self.delegate.getFiatValue(cryptoBalance, cryptoSymbol, fiatSymbol)
|
||||
|
||||
proc getCryptoValue*(self: View, fiatAmount: string, cryptoSymbol: string, fiatSymbol: string): string {.slot.} =
|
||||
return self.delegate.getCryptoValue(fiatAmount, cryptoSymbol, fiatSymbol)
|
||||
|
||||
proc getGasEthValue*(self: View, gweiValue: string, gasLimit: string): string {.slot.} =
|
||||
return self.delegate.getGasEthValue(gweiValue, gasLimit)
|
||||
|
||||
|
|
|
@ -62,6 +62,39 @@ proc getFeesTotal*(paths: seq[TransactionPathDto]): Fees =
|
|||
fees.totalTime += path.estimatedTime
|
||||
return fees
|
||||
|
||||
proc getTotalAmountToReceive*(paths: seq[TransactionPathDto]): UInt256 =
|
||||
var totalAmountToReceive: UInt256 = stint.u256(0)
|
||||
for path in paths:
|
||||
totalAmountToReceive += path.amountOut
|
||||
|
||||
return totalAmountToReceive
|
||||
|
||||
proc getToNetworksList*(paths: seq[TransactionPathDto]): seq[SendToNetwork] =
|
||||
var networkMap: Table[int, SendToNetwork] = initTable[int, SendToNetwork]()
|
||||
for path in paths:
|
||||
if(networkMap.hasKey(path.toNetwork.chainId)):
|
||||
networkMap[path.toNetwork.chainId].amountOut = networkMap[path.toNetwork.chainId].amountOut + path.amountOut
|
||||
else:
|
||||
networkMap[path.toNetwork.chainId] = SendToNetwork(chainId: path.toNetwork.chainId, chainName: path.toNetwork.chainName, iconUrl: path.toNetwork.iconURL, amountOut: path.amountOut)
|
||||
return toSeq(networkMap.values)
|
||||
|
||||
proc addFirstSimpleBridgeTxFlag(paths: seq[TransactionPathDto]) : seq[TransactionPathDto] =
|
||||
let txPaths = paths
|
||||
var firstSimplePath: bool = false
|
||||
var firstBridgePath: bool = false
|
||||
|
||||
for path in txPaths:
|
||||
if path.bridgeName == "Simple":
|
||||
if not firstSimplePath:
|
||||
firstSimplePath = true
|
||||
path.isFirstSimpleTx = true
|
||||
else:
|
||||
if not firstBridgePath:
|
||||
firstBridgePath = false
|
||||
path.isFirstBridgeTx = true
|
||||
|
||||
return txPaths
|
||||
|
||||
const getSuggestedRoutesTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall.} =
|
||||
let arg = decode[GetSuggestedRoutesTaskArg](argEncoded)
|
||||
|
||||
|
@ -86,16 +119,17 @@ const getSuggestedRoutesTask*: Task = proc(argEncoded: string) {.gcsafe, nimcall
|
|||
bestPaths.sort(sortAsc[TransactionPathDto])
|
||||
let output = %*{
|
||||
"suggestedRoutes": SuggestedRoutesDto(
|
||||
best: bestPaths,
|
||||
candidates: response["Candidates"].getElems().map(x => x.toTransactionPathDto()),
|
||||
gasTimeEstimate: getFeesTotal(bestPaths)),
|
||||
best: addFirstSimpleBridgeTxFlag(bestPaths),
|
||||
gasTimeEstimate: getFeesTotal(bestPaths),
|
||||
amountToReceive: getTotalAmountToReceive(bestPaths),
|
||||
toNetworks: getToNetworksList(bestPaths)),
|
||||
"error": ""
|
||||
}
|
||||
arg.finish(output)
|
||||
|
||||
except Exception as e:
|
||||
let output = %* {
|
||||
"suggestedRoutes": SuggestedRoutesDto(best: @[], candidates: @[], gasTimeEstimate: Fees()),
|
||||
"suggestedRoutes": SuggestedRoutesDto(best: @[], gasTimeEstimate: Fees(), amountToReceive: stint.u256(0), toNetworks: @[]),
|
||||
"error": fmt"Error getting suggested routes: {e.msg}"
|
||||
}
|
||||
arg.finish(output)
|
||||
|
|
|
@ -164,7 +164,8 @@ type
|
|||
cost*: float
|
||||
estimatedTime*: int
|
||||
amountInLocked*: bool
|
||||
|
||||
isFirstSimpleTx*: bool
|
||||
isFirstBridgeTx*: bool
|
||||
|
||||
proc `$`*(self: TransactionPathDto): string =
|
||||
return fmt"""TransactionPath(
|
||||
|
@ -179,7 +180,9 @@ proc `$`*(self: TransactionPathDto): string =
|
|||
bonderFees:{self.bonderFees},
|
||||
cost:{self.cost},
|
||||
estimatedTime:{self.estimatedTime},
|
||||
amountInLocked:{self.amountInLocked}
|
||||
amountInLocked:{self.amountInLocked},
|
||||
isFirstSimpleTx:{self.isFirstSimpleTx},
|
||||
isFirstBridgeTx:{self.isFirstBridgeTx}
|
||||
)"""
|
||||
|
||||
proc toTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
|
||||
|
@ -197,6 +200,8 @@ proc toTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
|
|||
result.estimatedTime = jsonObj{"EstimatedTime"}.getInt
|
||||
discard jsonObj.getProp("GasAmount", result.gasAmount)
|
||||
discard jsonObj.getProp("AmountInLocked", result.amountInLocked)
|
||||
result.isFirstSimpleTx = false
|
||||
result.isFirstBridgeTx = false
|
||||
|
||||
proc convertToTransactionPathDto*(jsonObj: JsonNode): TransactionPathDto =
|
||||
result = TransactionPathDto()
|
||||
|
@ -219,8 +224,16 @@ type
|
|||
totalTokenFees*: float
|
||||
totalTime*: int
|
||||
|
||||
type
|
||||
SendToNetwork* = ref object
|
||||
chainId*: int
|
||||
chainName*: string
|
||||
iconUrl*: string
|
||||
amountOut*: UInt256
|
||||
|
||||
type
|
||||
SuggestedRoutesDto* = ref object
|
||||
best*: seq[TransactionPathDto]
|
||||
candidates*: seq[TransactionPathDto]
|
||||
gasTimeEstimate*: Fees
|
||||
amountToReceive*: UInt256
|
||||
toNetworks*: seq[SendToNetwork]
|
||||
|
|
|
@ -157,7 +157,7 @@ Item {
|
|||
\qmlproperty real StatusBaseInput::leftPadding
|
||||
This property sets the leftComponentLoader's left padding.
|
||||
*/
|
||||
property real leftPadding: leftComponentLoader.item ? 8 : 16
|
||||
property real leftPadding: leftComponentLoader.item ? 6 : 16
|
||||
/*!
|
||||
\qmlproperty real StatusBaseInput::rightPadding
|
||||
This property sets the right padding.
|
||||
|
@ -308,7 +308,7 @@ Item {
|
|||
spacing: 2
|
||||
anchors {
|
||||
fill: parent
|
||||
leftMargin: root.leftPadding ? root.leftPadding : leftComponentLoader.item ? 6 : 16
|
||||
leftMargin: root.leftPadding
|
||||
rightMargin: root.rightPadding
|
||||
}
|
||||
|
||||
|
|
|
@ -122,6 +122,12 @@ QtObject {
|
|||
return ensUsernamesModule.getFiatValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function getCryptoValue(balance, cryptoSymbol, fiatSymbol) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
return ensUsernamesModule.getCryptoValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
if(!root.ensUsernamesModule)
|
||||
return ""
|
||||
|
|
|
@ -5,6 +5,8 @@ import StatusQ.Controls 0.1
|
|||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
StatusInput {
|
||||
id: cursorInput
|
||||
|
||||
|
@ -16,8 +18,8 @@ StatusInput {
|
|||
placeholderText: ""
|
||||
input.edit.objectName: "amountInput"
|
||||
input.edit.cursorVisible: true
|
||||
input.edit.font.pixelSize: 32
|
||||
input.placeholderFont.pixelSize: 32
|
||||
input.edit.font.pixelSize: Utils.getFontSizeBasedOnLetterCount(text)
|
||||
input.placeholderFont.pixelSize: 34
|
||||
input.leftPadding: 0
|
||||
input.rightPadding: 0
|
||||
input.topPadding: 0
|
||||
|
|
|
@ -43,7 +43,10 @@ Item {
|
|||
id: listItem
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
width: parent.width
|
||||
asset.name: index == 0 ? "tiny/gas" : ""
|
||||
asset.name: "tiny/gas"
|
||||
asset.color: Theme.palette.directColor1
|
||||
statusListItemIcon.active: true
|
||||
statusListItemIcon.opacity: modelData.isFirstSimpleTx
|
||||
title: qsTr("%1 transaction fee").arg(modelData.fromNetwork.chainName)
|
||||
subTitle: "%1 eth".arg(LocaleUtils.numberToLocaleString(parseFloat(totalGasAmount)))
|
||||
property string totalGasAmount : {
|
||||
|
@ -69,12 +72,16 @@ Item {
|
|||
|
||||
// Bridge
|
||||
Repeater {
|
||||
id: bridgeRepeater
|
||||
model: root.bestRoutes
|
||||
StatusListItem {
|
||||
delegate: StatusListItem {
|
||||
id: listItem2
|
||||
color: Theme.palette.statusListItem.backgroundColor
|
||||
width: parent.width
|
||||
asset.name: index == 0 ? "tiny/bridge" : ""
|
||||
asset.name: "tiny/bridge"
|
||||
asset.color: Theme.palette.directColor1
|
||||
statusListItemIcon.active: true
|
||||
statusListItemIcon.opacity: modelData.isFirstBridgeTx
|
||||
title: qsTr("%1 -> %2 bridge").arg(modelData.fromNetwork.chainName).arg(modelData.toNetwork.chainName)
|
||||
subTitle: "%1 %2".arg(LocaleUtils.numberToLocaleString(modelData.tokenFees)).arg(root.selectedTokenSymbol)
|
||||
visible: modelData.bridgeName !== "Simple"
|
||||
|
|
|
@ -12,6 +12,7 @@ import StatusQ.Components 0.1
|
|||
import StatusQ.Core.Backpressure 1.0
|
||||
|
||||
import shared.controls 1.0
|
||||
import utils 1.0
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
@ -51,6 +52,7 @@ Item {
|
|||
property string iconSource: ""
|
||||
property string text: ""
|
||||
property string searchString
|
||||
property bool isTokenSelected: !!root.selectedAsset
|
||||
|
||||
readonly property var updateSearchText: Backpressure.debounce(root, 1000, function(inputText) {
|
||||
d.searchString = inputText
|
||||
|
@ -60,8 +62,8 @@ Item {
|
|||
StatusComboBox {
|
||||
id: comboBox
|
||||
objectName: "assetSelectorButton"
|
||||
width: control.width
|
||||
height: parent.height
|
||||
width: d.isTokenSelected ? rowLayout.implicitWidth : 116
|
||||
height: 34
|
||||
|
||||
control.padding: 4
|
||||
control.popup.width: 342
|
||||
|
@ -86,30 +88,17 @@ Item {
|
|||
|
||||
control.background: Rectangle {
|
||||
color: "transparent"
|
||||
border.width: 1
|
||||
border.color: comboBox.control.hovered ? Theme.palette.primaryColor2 : Theme.palette.directColor8
|
||||
radius: 16
|
||||
width: rowLayout.width
|
||||
implicitHeight: 48
|
||||
border.width: d.isTokenSelected ? 0 : 1
|
||||
border.color: d.isTokenSelected ? "transparent" : Theme.palette.directColor7
|
||||
radius: 12
|
||||
}
|
||||
|
||||
contentItem: RowLayout {
|
||||
id: rowLayout
|
||||
spacing: 8
|
||||
StatusBaseText {
|
||||
Layout.leftMargin: 8
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
font.pixelSize: 15
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: !!root.selectedAsset ? Theme.palette.directColor1: Theme.palette.baseColor1
|
||||
font.weight: Font.Medium
|
||||
text: !!root.selectedAsset ? d.text : placeholderText
|
||||
}
|
||||
StatusRoundedImage {
|
||||
Layout.preferredWidth: 40
|
||||
Layout.preferredHeight: 40
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
Layout.preferredWidth: 21
|
||||
Layout.preferredHeight: 21
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
visible: !!d.iconSource
|
||||
image.source: d.iconSource
|
||||
image.onStatusChanged: {
|
||||
|
@ -118,9 +107,34 @@ Item {
|
|||
}
|
||||
}
|
||||
}
|
||||
Item {
|
||||
width: 8
|
||||
height: 0
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
font.pixelSize: 28
|
||||
elide: Text.ElideRight
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.miscColor1
|
||||
text: d.text
|
||||
visible: d.isTokenSelected
|
||||
}
|
||||
StatusIcon {
|
||||
Layout.leftMargin: -3
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
icon: "chevron-down"
|
||||
width: 16
|
||||
height: 16
|
||||
color: Theme.palette.miscColor1
|
||||
visible: d.isTokenSelected
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.maximumWidth: comboBox.width - Style.current.padding
|
||||
Layout.alignment: Qt.AlignCenter
|
||||
visible: !d.isTokenSelected
|
||||
font.pixelSize: 15
|
||||
font.weight: Font.Medium
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.baseColor1
|
||||
elide: Qt.ElideRight
|
||||
text: placeholderText
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,11 +229,9 @@ Item {
|
|||
placeholderText: qsTr("Search for token or enter token address")
|
||||
onTextChanged: Qt.callLater(d.updateSearchText, text)
|
||||
input.clearable: true
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
input.rightComponent: StatusIcon {
|
||||
width: 24
|
||||
height: 24
|
||||
width: 16
|
||||
height: 16
|
||||
color: Theme.palette.baseColor1
|
||||
icon: "search"
|
||||
}
|
||||
|
|
|
@ -60,7 +60,7 @@ StatusDialog {
|
|||
popup.selectedAccount.address,
|
||||
recipientAddress,
|
||||
assetSelector.selectedAsset.symbol,
|
||||
amountToSendInput.text,
|
||||
amountToSendInput.cryptoValueToSend,
|
||||
d.uuid,
|
||||
JSON.stringify(popup.bestRoutes)
|
||||
)
|
||||
|
@ -69,7 +69,7 @@ StatusDialog {
|
|||
property var recalculateRoutesAndFees: Backpressure.debounce(popup, 600, function() {
|
||||
if(!!popup.selectedAccount && !!assetSelector.selectedAsset && d.recipientReady) {
|
||||
popup.isLoading = true
|
||||
let amount = parseFloat(amountToSendInput.text) * Math.pow(10, assetSelector.selectedAsset.decimals)
|
||||
let amount = Math.round(parseFloat(amountToSendInput.cryptoValueToSend) * Math.pow(10, assetSelector.selectedAsset.decimals))
|
||||
popup.store.suggestedRoutes(popup.selectedAccount.address, amount.toString(16), assetSelector.selectedAsset.symbol,
|
||||
store.disabledChainIdsFromList, store.disabledChainIdsToList,
|
||||
store.preferredChainIds, popup.sendType, store.lockedInAmounts)
|
||||
|
@ -78,13 +78,15 @@ StatusDialog {
|
|||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property double maxFiatBalance: assetSelector.selectedAsset ? assetSelector.selectedAsset.totalBalance: 0
|
||||
readonly property double maxFiatBalance: !!assetSelector.selectedAsset ? (amountToSendInput.cryptoFiatFlipped ?
|
||||
assetSelector.selectedAsset.totalCurrencyBalance :
|
||||
assetSelector.selectedAsset.totalBalance): 0
|
||||
onMaxFiatBalanceChanged: {
|
||||
floatValidator.top = maxFiatBalance
|
||||
amountToSendInput.validate()
|
||||
amountToSendInput.floatValidator.top = maxFiatBalance
|
||||
amountToSendInput.input.validate()
|
||||
}
|
||||
readonly property bool isReady: amountToSendInput.valid && !amountToSendInput.pending && recipientReady
|
||||
readonly property bool errorMode: popup.isLoading || !isReady ? false : (networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0) || networkSelector.errorMode || isNaN(amountToSendInput.text)
|
||||
readonly property bool isReady: amountToSendInput.input.valid && !amountToSendInput.input.pending && recipientReady
|
||||
readonly property bool errorMode: popup.isLoading || !isReady ? false : (networkSelector.bestRoutes && networkSelector.bestRoutes.length <= 0) || networkSelector.errorMode || isNaN(amountToSendInput.input.text)
|
||||
readonly property bool recipientReady: (isAddressValid || isENSValid) && !recipientSelector.isPending
|
||||
property bool isAddressValid: Utils.isValidAddress(popup.addressText)
|
||||
property bool isENSValid: false
|
||||
|
@ -97,6 +99,7 @@ StatusDialog {
|
|||
property string totalTimeEstimate
|
||||
property string totalFeesInEth
|
||||
property string totalFeesInFiat
|
||||
property double totalAmountToReceive: 0
|
||||
|
||||
property Timer waitTimer: Timer {
|
||||
interval: 1500
|
||||
|
@ -124,14 +127,14 @@ StatusDialog {
|
|||
store.setDefaultPreferredDisabledChains()
|
||||
}
|
||||
|
||||
amountToSendInput.input.edit.forceActiveFocus()
|
||||
amountToSendInput.input.input.edit.forceActiveFocus()
|
||||
|
||||
if(!!popup.preSelectedAsset) {
|
||||
assetSelector.selectedAsset = popup.preSelectedAsset
|
||||
}
|
||||
|
||||
if(!!popup.preDefinedAmountToSend) {
|
||||
amountToSendInput.text = popup.preDefinedAmountToSend
|
||||
amountToSendInput.input.text = popup.preDefinedAmountToSend
|
||||
}
|
||||
|
||||
if(!!popup.preSelectedRecipient) {
|
||||
|
@ -190,63 +193,30 @@ StatusDialog {
|
|||
anchors.leftMargin: Style.current.xlPadding
|
||||
anchors.rightMargin: Style.current.xlPadding
|
||||
z: 1
|
||||
spacing: 16
|
||||
|
||||
Row {
|
||||
spacing: 16
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
spacing: 8
|
||||
StatusBaseText {
|
||||
id: modalHeader
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
text: popup.isBridgeTx ? qsTr("Bridge") : qsTr("Send")
|
||||
font.pixelSize: 15
|
||||
font.pixelSize: 28
|
||||
lineHeight: 38
|
||||
lineHeightMode: Text.FixedHeight
|
||||
font.letterSpacing: -0.4
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
StatusListItemTag {
|
||||
bgColor: d.errorMode ? Theme.palette.dangerColor2 : Theme.palette.primaryColor3
|
||||
height: 22
|
||||
width: childrenRect.width
|
||||
title: d.maxFiatBalance > 0 ? qsTr("Max: %1").arg(LocaleUtils.numberToLocaleString(d.maxFiatBalance)) : qsTr("No balances active")
|
||||
closeButtonVisible: false
|
||||
titleText.font.pixelSize: 12
|
||||
titleText.color: d.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
Item {
|
||||
width: parent.width
|
||||
height: amountToSendInput.height
|
||||
AmountInputWithCursor {
|
||||
id: amountToSendInput
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: -Style.current.padding
|
||||
width: parent.width - assetSelector.width
|
||||
placeholderText: assetSelector.selectedAsset ? "%1 %2".arg(LocaleUtils.numberToLocaleString(0, 2)).arg(assetSelector.selectedAsset.symbol) : LocaleUtils.numberToLocaleString(0, 2)
|
||||
input.edit.color: d.errorMode ? Theme.palette.dangerColor1 : Theme.palette.directColor1
|
||||
input.edit.readOnly: !popup.interactive
|
||||
validators: [
|
||||
StatusFloatValidator{
|
||||
id: floatValidator
|
||||
bottom: 0
|
||||
top: d.maxFiatBalance
|
||||
errorMessage: ""
|
||||
}
|
||||
]
|
||||
Keys.onReleased: {
|
||||
let amount = amountToSendInput.text.trim()
|
||||
|
||||
if (!Utils.containsOnlyDigits(amount) || isNaN(amount)) {
|
||||
return
|
||||
}
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
Layout.maximumWidth: contentWidth
|
||||
}
|
||||
StatusAssetSelector {
|
||||
id: assetSelector
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
Layout.fillWidth: true
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignLeft
|
||||
enabled: popup.interactive
|
||||
assets: popup.selectedAccount && popup.selectedAccount.assets ? popup.selectedAccount.assets : []
|
||||
defaultToken: Style.png("tokens/DEFAULT-TOKEN@3x")
|
||||
placeholderText: popup.isBridgeTx ? qsTr("Select token to bridge") : qsTr("Select token to send")
|
||||
placeholderText: qsTr("Select token")
|
||||
getCurrencyBalanceString: function (currencyBalance) {
|
||||
return "%1 %2".arg(Utils.toLocaleString(currencyBalance.toFixed(2), popup.store.locale, {"currency": true})).arg(popup.store.currentCurrency.toUpperCase())
|
||||
}
|
||||
|
@ -260,59 +230,48 @@ StatusDialog {
|
|||
return ""
|
||||
}
|
||||
onSelectedAssetChanged: {
|
||||
if (!assetSelector.selectedAsset) {
|
||||
return
|
||||
}
|
||||
if (amountToSendInput.text === "" || isNaN(amountToSendInput.text)) {
|
||||
if (!assetSelector.selectedAsset || !!amountToSendInput.input.text || isNaN(amountToSendInput.input.text)) {
|
||||
return
|
||||
}
|
||||
popup.recalculateRoutesAndFees()
|
||||
}
|
||||
}
|
||||
}
|
||||
StatusInput {
|
||||
id: txtFiatBalance
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: -12
|
||||
leftPadding: 0
|
||||
rightPadding: 0
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 13
|
||||
input.placeholderFont.pixelSize: 13
|
||||
input.leftPadding: 0
|
||||
input.rightPadding: 0
|
||||
input.topPadding: 0
|
||||
input.bottomPadding: 0
|
||||
input.edit.padding: 0
|
||||
input.background.color: "transparent"
|
||||
input.background.border.width: 0
|
||||
input.edit.color: txtFiatBalance.input.edit.activeFocus ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
input.edit.readOnly: true
|
||||
text: {
|
||||
if(!!assetSelector.selectedAsset) {
|
||||
let fiatValue = popup.store.getFiatValue(amountToSendInput.text, assetSelector.selectedAsset.symbol, popup.store.currentCurrency)
|
||||
return parseFloat(fiatValue) === 0 ? LocaleUtils.numberToLocaleString(parseFloat(fiatValue), 2) : LocaleUtils.numberToLocaleString(parseFloat(fiatValue))
|
||||
}
|
||||
return LocaleUtils.numberToLocaleString(0, 2)
|
||||
}
|
||||
input.implicitHeight: Style.current.bigPadding
|
||||
implicitWidth: txtFiatBalance.input.edit.contentWidth + 50
|
||||
input.rightComponent: StatusBaseText {
|
||||
id: currencyText
|
||||
text: popup.store.currentCurrency.toUpperCase()
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
Keys.onReleased: {
|
||||
let balance = txtFiatBalance.text.trim()
|
||||
if (balance === "" || isNaN(balance)) {
|
||||
return
|
||||
}
|
||||
// To-Do Not refactored yet
|
||||
// amountToSendInput.text = root.getCryptoValue(balance, popup.store.currentCurrency, assetSelector.selectedAsset.symbol)
|
||||
StatusListItemTag {
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
Layout.preferredHeight: 22
|
||||
title: d.maxFiatBalance > 0 ? qsTr("Max: %1").arg(LocaleUtils.numberToLocaleString(d.maxFiatBalance)) : qsTr("No balances active")
|
||||
closeButtonVisible: false
|
||||
titleText.font.pixelSize: 12
|
||||
bgColor: d.errorMode ? Theme.palette.dangerColor2 : Theme.palette.primaryColor3
|
||||
titleText.color: d.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
width: parent.width
|
||||
AmountToSend {
|
||||
id: amountToSendInput
|
||||
Layout.fillWidth:true
|
||||
isBridgeTx: popup.isBridgeTx
|
||||
interactive: popup.interactive
|
||||
store: popup.store
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
errorMode: d.errorMode
|
||||
maxFiatBalance: d.maxFiatBalance
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
|
||||
}
|
||||
AmountToReceive {
|
||||
id: amountToReceive
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.fillWidth:true
|
||||
visible: popup.bestRoutes !== undefined && popup.bestRoutes.length > 0
|
||||
store: popup.store
|
||||
isLoading: popup.isLoading
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
isBridgeTx: popup.isBridgeTx
|
||||
amountToReceive: d.totalAmountToReceive
|
||||
cryptoFiatFlipped: amountToSendInput.cryptoFiatFlipped
|
||||
}
|
||||
}
|
||||
|
||||
TokenListView {
|
||||
id: tokenListRect
|
||||
anchors.left: parent.left
|
||||
|
@ -336,7 +295,7 @@ StatusDialog {
|
|||
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
topPadding: 0
|
||||
topPadding: 12
|
||||
Layout.fillHeight: true
|
||||
Layout.preferredWidth: parent.width
|
||||
contentHeight: layout.height + Style.current.padding
|
||||
|
@ -441,7 +400,7 @@ StatusDialog {
|
|||
store: popup.store
|
||||
interactive: popup.interactive
|
||||
selectedAccount: popup.selectedAccount
|
||||
amountToSend: isNaN(parseFloat(amountToSendInput.text)) ? 0 : parseFloat(amountToSendInput.text)
|
||||
amountToSend: isNaN(parseFloat(amountToSendInput.cryptoValueToSend)) ? 0 : parseFloat(amountToSendInput.cryptoValueToSend)
|
||||
requiredGasInEth:d.totalFeesInEth
|
||||
selectedAsset: assetSelector.selectedAsset
|
||||
onReCalculateSuggestedRoute: popup.recalculateRoutesAndFees()
|
||||
|
@ -476,7 +435,7 @@ StatusDialog {
|
|||
maxFiatFees: popup.isLoading ? "..." : "%1 %2".arg(LocaleUtils.numberToLocaleString(d.totalFeesInFiat)).arg(popup.store.currentCurrency.toUpperCase())
|
||||
totalTimeEstimate: popup.isLoading? "..." : d.totalTimeEstimate
|
||||
pending: d.isPendingTx || popup.isLoading
|
||||
visible: d.isReady && !isNaN(amountToSendInput.text) && fees.isValid && !d.errorMode
|
||||
visible: d.isReady && !isNaN(amountToSendInput.cryptoValueToSend) && fees.isValid && !d.errorMode
|
||||
onNextButtonClicked: popup.sendTransaction()
|
||||
}
|
||||
|
||||
|
@ -499,6 +458,8 @@ StatusDialog {
|
|||
d.totalFeesInEth = gasTimeEstimate.totalFeesInEth
|
||||
d.totalFeesInFiat = parseFloat(popup.store.getFiatValue( gasTimeEstimate.totalFeesInEth, "ETH", popup.store.currentCurrency)) +
|
||||
parseFloat(popup.store.getFiatValue(gasTimeEstimate.totalTokenFees, fees.selectedTokenSymbol, popup.store.currentCurrency))
|
||||
d.totalAmountToReceive = popup.store.getWei2Eth(response.suggestedRoutes.amountToReceive, assetSelector.selectedAsset.decimals)
|
||||
networkSelector.toNetworksList = response.suggestedRoutes.toNetworks
|
||||
popup.isLoading = false
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,6 +69,10 @@ QtObject {
|
|||
return profileSectionStore.ensUsernamesStore.getFiatValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function getCryptoValue(balance, cryptoSymbol, fiatSymbol) {
|
||||
return profileSectionStore.ensUsernamesStore.getCryptoValue(balance, cryptoSymbol, fiatSymbol)
|
||||
}
|
||||
|
||||
function getGasEthValue(gweiValue, gasLimit) {
|
||||
return profileSectionStore.ensUsernamesStore.getGasEthValue(gweiValue, gasLimit)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
import utils 1.0
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property var store
|
||||
property var selectedAsset
|
||||
property bool isLoading: false
|
||||
property string amountToReceive
|
||||
property bool isBridgeTx: false
|
||||
property bool cryptoFiatFlipped: false
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
function formatValue(value) {
|
||||
const precision = (value === 0 ? 2 : 0)
|
||||
return LocaleUtils.numberToLocaleString(value, precision)
|
||||
}
|
||||
readonly property string fiatValue: {
|
||||
if(!root.selectedAsset || !amountToReceive)
|
||||
return formatValue(0)
|
||||
let cryptoValue = root.store.getFiatValue(amountToReceive, root.selectedAsset.symbol, root.store.currentCurrency)
|
||||
return formatValue(parseFloat(cryptoValue))
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignTop
|
||||
text: root.isBridgeTx ? qsTr("Amount Bridged") : qsTr("Recipient will get")
|
||||
font.pixelSize: 13
|
||||
lineHeight: 18
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight
|
||||
Layout.preferredHeight: 42
|
||||
StatusBaseText {
|
||||
id: amountToReceiveText
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: isLoading ? "..." : cryptoFiatFlipped ? d.fiatValue: amountToReceive
|
||||
font.pixelSize: Utils.getFontSizeBasedOnLetterCount(text)
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: isLoading ? "..." : root.store.currentCurrency.toUpperCase()
|
||||
font.pixelSize: amountToReceiveText.font.pixelSize
|
||||
color: Theme.palette.directColor1
|
||||
visible: cryptoFiatFlipped
|
||||
}
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignRight | Qt.AlignBottom
|
||||
StatusBaseText {
|
||||
id: txtFiatBalance
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
text: isLoading ? "..." : cryptoFiatFlipped ? amountToReceive : d.fiatValue
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
Layout.leftMargin: 4
|
||||
text: isLoading ? "..." : !cryptoFiatFlipped ? root.store.currentCurrency.toUpperCase() : !!root.selectedAsset ? root.selectedAsset.symbol.toUpperCase() : ""
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
import QtQuick 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls.Validators 0.1
|
||||
|
||||
import "../controls"
|
||||
|
||||
import utils 1.0
|
||||
|
||||
ColumnLayout {
|
||||
id: root
|
||||
|
||||
property alias input: amountToSendInput
|
||||
property alias floatValidator: floatValidator
|
||||
|
||||
property var store
|
||||
property var selectedAsset
|
||||
property bool errorMode
|
||||
property bool isBridgeTx: false
|
||||
property bool interactive: false
|
||||
property double maxFiatBalance
|
||||
property bool cryptoFiatFlipped: false
|
||||
property string cryptoValueToSend: !cryptoFiatFlipped ? amountToSendInput.text : txtFiatBalance.text
|
||||
|
||||
signal reCalculateSuggestedRoute()
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
readonly property string zeroString: formatValue(0, 2)
|
||||
property Timer waitTimer: Timer {
|
||||
interval: 1000
|
||||
onTriggered: reCalculateSuggestedRoute()
|
||||
}
|
||||
function formatValue(value, precision) {
|
||||
const precisionVal = !!precision ? precision : (value === 0 ? 2 : 0)
|
||||
return LocaleUtils.numberToLocaleString(value, precisionVal)
|
||||
}
|
||||
function getFiatValue(value) {
|
||||
if(!root.selectedAsset || !value)
|
||||
return zeroString
|
||||
let cryptoValue = root.store.getFiatValue(value, root.selectedAsset.symbol, root.store.currentCurrency)
|
||||
return formatValue(parseFloat(cryptoValue))
|
||||
}
|
||||
function getCryptoValue(value) {
|
||||
if(!root.selectedAsset || !value)
|
||||
return zeroString
|
||||
let cryptoValue = root.store.getCryptoValue(value, root.selectedAsset.symbol, root.store.currentCurrency)
|
||||
return formatValue(parseFloat(cryptoValue))
|
||||
}
|
||||
}
|
||||
|
||||
onSelectedAssetChanged: {
|
||||
if(!!root.selectedAsset) {
|
||||
txtFiatBalance.text = !cryptoFiatFlipped ? d.getFiatValue(amountToSendInput.text): d.getCryptoValue(amountToSendInput.text)
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignTop
|
||||
text: root.isBridgeTx ? qsTr("Amount to bridge") : qsTr("Amount to send")
|
||||
font.pixelSize: 13
|
||||
lineHeight: 18
|
||||
lineHeightMode: Text.FixedHeight
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
RowLayout {
|
||||
Layout.alignment: Qt.AlignLeft
|
||||
AmountInputWithCursor {
|
||||
id: amountToSendInput
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
Layout.maximumWidth: 163
|
||||
Layout.preferredWidth: (!!text) ? input.edit.paintedWidth : textMetrics.advanceWidth
|
||||
placeholderText: d.zeroString
|
||||
input.edit.color: root.errorMode ? Theme.palette.dangerColor1 : Theme.palette.directColor1
|
||||
input.edit.readOnly: !root.interactive
|
||||
validators: [
|
||||
StatusFloatValidator {
|
||||
id: floatValidator
|
||||
bottom: 0
|
||||
top: root.maxFiatBalance
|
||||
errorMessage: ""
|
||||
}
|
||||
]
|
||||
TextMetrics {
|
||||
id: textMetrics
|
||||
text: amountToSendInput.placeholderText
|
||||
font: amountToSendInput.input.placeholder.font
|
||||
}
|
||||
Keys.onReleased: {
|
||||
const amount = amountToSendInput.text.trim()
|
||||
if (!Utils.containsOnlyDigits(amount) || isNaN(amount)) {
|
||||
return
|
||||
}
|
||||
txtFiatBalance.text = !cryptoFiatFlipped ? d.getFiatValue(amount): d.getCryptoValue(amount)
|
||||
d.waitTimer.restart()
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
text: root.store.currentCurrency.toUpperCase()
|
||||
font.pixelSize: amountToSendInput.input.edit.font.pixelSize
|
||||
color: Theme.palette.baseColor1
|
||||
visible: cryptoFiatFlipped
|
||||
}
|
||||
}
|
||||
Item {
|
||||
id: fiatBalanceLayout
|
||||
Layout.alignment: Qt.AlignLeft | Qt.AlignBottom
|
||||
Layout.preferredWidth: txtFiatBalance.width + currencyText.width
|
||||
Layout.preferredHeight: txtFiatBalance.height
|
||||
StatusBaseText {
|
||||
id: txtFiatBalance
|
||||
anchors.top: parent.top
|
||||
anchors.left: parent.left
|
||||
text: d.getFiatValue(amountToSendInput.text)
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
StatusBaseText {
|
||||
id: currencyText
|
||||
anchors.top: parent.top
|
||||
anchors.left: txtFiatBalance.right
|
||||
anchors.leftMargin: 4
|
||||
text: !cryptoFiatFlipped ? root.store.currentCurrency.toUpperCase() : !!root.selectedAsset ? root.selectedAsset.symbol.toUpperCase() : ""
|
||||
font.pixelSize: 13
|
||||
color: Theme.palette.directColor5
|
||||
}
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
onClicked: {
|
||||
cryptoFiatFlipped = !cryptoFiatFlipped
|
||||
amountToSendInput.validate()
|
||||
if(!!amountToSendInput.text) {
|
||||
const tempVal = Number.fromLocaleString(txtFiatBalance.text)
|
||||
txtFiatBalance.text = !!amountToSendInput.text ? amountToSendInput.text : d.zeroString
|
||||
amountToSendInput.text = tempVal
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -36,6 +36,7 @@ Rectangle {
|
|||
Layout.alignment: Qt.AlignTop
|
||||
radius: 8
|
||||
asset.name: "fees"
|
||||
asset.color: Theme.palette.directColor1
|
||||
}
|
||||
Column {
|
||||
Layout.alignment: Qt.AlignTop | Qt.AlignHCenter
|
||||
|
|
|
@ -28,6 +28,7 @@ Item {
|
|||
property bool interactive: true
|
||||
property bool isBridgeTx: false
|
||||
property bool showUnpreferredNetworks: advancedNetworkRoutingPage.showUnpreferredNetworks
|
||||
property var toNetworksList: []
|
||||
|
||||
signal reCalculateSuggestedRoute()
|
||||
|
||||
|
@ -79,6 +80,7 @@ Item {
|
|||
selectedAsset: root.selectedAsset
|
||||
selectedAccount: root.selectedAccount
|
||||
errorMode: root.errorMode
|
||||
toNetworksList: root.toNetworksList
|
||||
weiToEth: function(wei) {
|
||||
return "%1 %2".arg(LocaleUtils.numberToLocaleString(parseFloat(store.getWei2Eth(wei, selectedAsset.decimals)))).arg(selectedAsset.symbol)
|
||||
}
|
||||
|
|
|
@ -37,6 +37,7 @@ ColumnLayout {
|
|||
Layout.alignment: Qt.AlignTop
|
||||
radius: 8
|
||||
asset.name: "flash"
|
||||
asset.color: Theme.palette.directColor1
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
|
|
@ -22,6 +22,7 @@ RowLayout {
|
|||
property bool isBridgeTx: false
|
||||
property var selectedAsset
|
||||
property var selectedAccount
|
||||
property var toNetworksList: []
|
||||
property var weiToEth: function(wei) {}
|
||||
property var reCalculateSuggestedRoute: function() {}
|
||||
property bool errorMode: false
|
||||
|
@ -31,6 +32,7 @@ RowLayout {
|
|||
Layout.alignment: Qt.AlignTop
|
||||
radius: 8
|
||||
asset.name: "flash"
|
||||
asset.color: Theme.palette.directColor1
|
||||
}
|
||||
ColumnLayout {
|
||||
Layout.alignment: Qt.AlignTop
|
||||
|
@ -61,13 +63,13 @@ RowLayout {
|
|||
ScrollBar.horizontal.policy: ScrollBar.AsNeeded
|
||||
clip: true
|
||||
visible: !root.isLoading ? root.isBridgeTx ? true : root.bestRoutes !== undefined ? root.bestRoutes.length > 0 : true : false
|
||||
Row {
|
||||
Column {
|
||||
id: row
|
||||
spacing: Style.current.padding
|
||||
Repeater {
|
||||
id: repeater
|
||||
objectName: "networksList"
|
||||
model: isBridgeTx ? store.allNetworks : root.bestRoutes
|
||||
model: isBridgeTx ? store.allNetworks : root.toNetworksList
|
||||
delegate: isBridgeTx ? networkItem : routeItem
|
||||
}
|
||||
}
|
||||
|
@ -89,15 +91,15 @@ RowLayout {
|
|||
Component {
|
||||
id: routeItem
|
||||
StatusListItem {
|
||||
objectName: modelData.toNetwork.chainName
|
||||
objectName: modelData.chainName
|
||||
leftPadding: 5
|
||||
rightPadding: 5
|
||||
implicitWidth: 126
|
||||
title: modelData.toNetwork.chainName
|
||||
implicitWidth: 410
|
||||
title: modelData.chainName
|
||||
subTitle: {
|
||||
let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === modelData.toNetwork.chainId)
|
||||
let index = store.lockedInAmounts.findIndex(lockedItem => lockedItem !== undefined && lockedItem.chainID === modelData.chainId)
|
||||
if(!root.errorMode || index === -1)
|
||||
return root.weiToEth(modelData.amountIn)
|
||||
return root.weiToEth(modelData.amountOut)
|
||||
else {
|
||||
return root.weiToEth(parseInt(store.lockedInAmounts[index].value, 16))
|
||||
}
|
||||
|
@ -105,7 +107,7 @@ RowLayout {
|
|||
statusListItemSubTitle.color: root.errorMode ? Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
asset.name: Style.svg("tiny/" + modelData.toNetwork.iconUrl)
|
||||
asset.name: Style.svg("tiny/" + modelData.iconUrl)
|
||||
asset.isImage: true
|
||||
color: "transparent"
|
||||
}
|
||||
|
|
|
@ -800,6 +800,17 @@ QtObject {
|
|||
}
|
||||
}
|
||||
|
||||
function getFontSizeBasedOnLetterCount(text) {
|
||||
if(text.length >= 12)
|
||||
return 18
|
||||
if(text.length >= 10)
|
||||
return 24
|
||||
if(text.length > 6)
|
||||
return 28
|
||||
else
|
||||
return 34
|
||||
}
|
||||
|
||||
// Leave this function at the bottom of the file as QT Creator messes up the code color after this
|
||||
function isPunct(c) {
|
||||
return /(!|\@|#|\$|%|\^|&|\*|\(|\)|\+|\||-|=|\\|{|}|[|]|"|;|'|<|>|\?|,|\.|\/)/.test(c)
|
||||
|
|
Loading…
Reference in New Issue