feat(@desktop/wallet): Handle contract deployment (#11570)

closes #9047
This commit is contained in:
Cuteivist 2023-07-24 13:18:42 +02:00 committed by GitHub
parent 38672ffda6
commit 9b8340b695
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 109 additions and 17 deletions

View File

@ -26,7 +26,7 @@ type
# see status-go/services/wallet/activity/filter.go Type
ActivityType* {.pure.} = enum
Send, Receive, Buy, Swap, Bridge
Send, Receive, Buy, Swap, Bridge, ContractDeployment
# see status-go/services/wallet/activity/filter.go Status
ActivityStatus* {.pure.} = enum

View File

@ -294,6 +294,7 @@
<file>assets/img/icons/strikethrough.svg</file>
<file>assets/img/icons/subscription.svg</file>
<file>assets/img/icons/swap.svg</file>
<file>assets/img/icons/contract_deploy.svg</file>
<file>assets/img/icons/symbols.svg</file>
<file>assets/img/icons/tabs.svg</file>
<file>assets/img/icons/telegram.svg</file>

View File

@ -0,0 +1,6 @@
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M9.00704 4.07812V8.35185C9.00704 9.0781 8.4183 9.66684 7.69205 9.66684H3.74707" stroke="black" stroke-width="1.5"/>
<path d="M16.9913 16.6009L13.7617 14.6045L16.9913 9.01479L20.2209 14.6045L16.9913 16.6009Z" stroke="black" stroke-width="1.5"/>
<path d="M16.9913 20.4378L13.6191 14.8513L16.9913 9.01479L20.3635 14.8513L16.9913 20.4378Z" stroke="black" stroke-width="1.5"/>
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.3807 3C9.43406 2.99987 8.52242 3.35776 7.82869 4.00184L4.19851 7.37223C3.43426 8.08178 3 9.07754 3 10.1204V17.8458C3 19.9168 4.67893 21.5958 6.75 21.5958H13.8999C13.969 21.5958 14.0377 21.5939 14.1059 21.5902C14.4436 21.5719 14.6026 21.1966 14.4278 20.9071L13.9575 20.128C13.9454 20.1078 13.9234 20.0958 13.8999 20.0958H6.75C5.50736 20.0958 4.5 19.0884 4.5 17.8458V10.1204C4.5 9.49468 4.76056 8.89722 5.21911 8.47149L8.84929 5.1011C9.26552 4.71466 9.81251 4.49992 10.3805 4.5L13.9002 4.50047C15.1428 4.50064 16.1499 5.50795 16.1499 6.75047C16.1499 6.93775 16.3373 7.06878 16.5216 7.03566C16.7762 6.98991 17.0376 6.98799 17.2928 7.02989C17.4713 7.0592 17.6499 6.93138 17.6499 6.75047C17.6499 4.6796 15.9713 3.00075 13.9004 3.00047L10.3807 3Z" fill="black"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

View File

@ -265,6 +265,35 @@ Item {
}
}
}
TransactionDataTile {
id: contractDeploymentTile
readonly property bool hasValue: root.isTransactionValid && !!root.transaction.contract
&& transactionHeader.transactionStatus !== Constants.TransactionStatus.Pending
&& transactionHeader.transactionStatus !== Constants.TransactionStatus.Failed
width: parent.width
title: qsTr("To")
visible: d.transactionType === Constants.TransactionType.ContractDeployment
subTitle: {
if (transactionHeader.transactionStatus === Constants.TransactionStatus.Failed) {
return qsTr("Contract address not created")
} else if (!hasValue) {
return qsTr("Awaiting contract address...")
}
return qsTr("Contract created") + "\n" + transaction.contract
}
buttonIconName: hasValue ? "more" : ""
statusListItemSubTitle.customColor: hasValue ? Theme.palette.directColor1 : Theme.palette.directColor5
onButtonClicked: addressMenu.openContractMenu(this, transaction.contract, transactionHeader.networkName, d.symbol)
components: [
Loader {
anchors.verticalCenter: parent.verticalCenter
anchors.verticalCenterOffset: Style.current.halfPadding
active: transactionHeader.transactionStatus === Constants.TransactionStatus.Pending
width: active ? implicitWidth : 0
sourceComponent: StatusLoadingIndicator { }
}
]
}
TransactionAddressTile {
width: parent.width
title: qsTr("To")
@ -272,7 +301,7 @@ Item {
contactsStore: root.contactsStore
rootStore: WalletStores.RootStore
onButtonClicked: addressMenu.openReceiverMenu(this, addresses[0], d.networkShortName)
visible: d.transactionType !== Constants.TransactionType.Swap && d.transactionType !== Constants.TransactionType.Bridge && d.transactionType !== Constants.TransactionType.Destroy
visible: d.transactionType !== Constants.TransactionType.ContractDeployment && d.transactionType !== Constants.TransactionType.Swap && d.transactionType !== Constants.TransactionType.Bridge && d.transactionType !== Constants.TransactionType.Destroy
}
TransactionDataTile {
width: parent.width
@ -319,6 +348,7 @@ Item {
}
networkName: transactionHeader.networkName
shortNetworkName: d.networkShortName
visible: !!subTitle && d.transactionType !== Constants.TransactionType.ContractDeployment
}
TransactionContractTile {
// Used for Bridge to display 'To' network Protocol contract address
@ -548,7 +578,7 @@ Item {
}
TransactionDataTile {
width: parent.width
title: transactionHeader.transactionStatus === Constants.TransactionType.Pending ? qsTr("Amount to receive") : qsTr("Amount received")
title: transactionHeader.transactionStatus === Constants.TransactionStatus.Pending ? qsTr("Amount to receive") : qsTr("Amount received")
subTitle: {
if (!root.isTransactionValid || transactionHeader.isNFT)
return ""
@ -609,27 +639,43 @@ Item {
}
TransactionDataTile {
width: parent.width
// Using fees in this tile because of same higlight and color settings as Total
title: d.transactionType === Constants.TransactionType.Destroy || transactionHeader.isNFT ? qsTr("Fees") : qsTr("Total")
readonly property bool fieldIsHidden: (transactionHeader.isNFT && d.isIncoming) || !d.symbol
readonly property bool showMaxFee: d.transactionType === Constants.TransactionType.ContractDeployment && transactionHeader.transactionStatus === Constants.TransactionStatus.Pending
readonly property bool showFee: d.transactionType === Constants.TransactionType.Destroy || transactionHeader.isNFT || d.transactionType === Constants.TransactionType.ContractDeployment
readonly property bool showValue: d.transactionType === Constants.TransactionType.Receive || (d.transactionType === Constants.TransactionType.Buy && progressBlock.isLayer1)
// NOTE Using fees in this tile because of same higlight and color settings as Total
title: {
if (showMaxFee) {
return qsTr("Estimated max fee")
} else if (showFee) {
return qsTr("Fees")
}
return qsTr("Total")
}
subTitle: {
if ((transactionHeader.isNFT && d.isIncoming) || !d.symbol)
if (fieldIsHidden)
return ""
const type = d.transactionType
if (type === Constants.TransactionType.Destroy || transactionHeader.isNFT) {
if (showMaxFee) {
const maxFeeEth = RootStore.getGasEthValue(transaction.maxTotalFees.amount, 1)
return RootStore.formatCurrencyAmount(maxFeeEth, Constants.ethToken)
} else if (showFee) {
return RootStore.formatCurrencyAmount(d.feeEthValue, Constants.ethToken)
} else if (type === Constants.TransactionType.Receive || (type === Constants.TransactionType.Buy && progressBlock.isLayer1)) {
} else if (showValue) {
return d.cryptoValueFormatted
}
const cryptoValue = transactionHeader.isMultiTransaction ? d.outCryptoValueFormatted : d.cryptoValueFormatted
return "%1 + %2".arg(cryptoValue).arg(RootStore.formatCurrencyAmount(d.feeEthValue, Constants.ethToken))
}
tertiaryTitle: {
if ((transactionHeader.isNFT && d.isIncoming) || !d.symbol)
if (fieldIsHidden)
return ""
const type = d.transactionType
if (type === Constants.TransactionType.Destroy || transactionHeader.isNFT) {
if (showMaxFee) {
const maxFeeEth = RootStore.getGasEthValue(transaction.maxTotalFees.amount, 1)
const maxFeeFiat = RootStore.getFiatValue(d.feeEthValue, "ETH", RootStore.currentCurrency)
return RootStore.formatCurrencyAmount(maxFeeFiat, RootStore.currentCurrency)
} else if (showFee) {
return RootStore.formatCurrencyAmount(d.feeFiatValue, RootStore.currentCurrency)
} else if (type === Constants.TransactionType.Receive || (type === Constants.TransactionType.Buy && progressBlock.isLayer1)) {
} else if (showValue) {
return d.fiatValueFormatted
}
const fiatValue = transactionHeader.isMultiTransaction ? transactionHeader.outFiatValue : transactionHeader.fiatValue

View File

@ -79,7 +79,7 @@ StatusListItem {
readonly property string outTransactionValue: isModelDataValid && isMultiTransaction ? rootStore.formatCurrencyAmount(outCryptoValue, modelData.outSymbol) : qsTr("N/A")
readonly property string tokenImage: {
if (!isModelDataValid)
if (!isModelDataValid || modelData.txType === Constants.TransactionType.ContractDeployment)
return ""
if (root.isNFT) {
return modelData.nftImageUrl ? modelData.nftImageUrl : ""
@ -177,6 +177,9 @@ StatusListItem {
case Constants.TransactionType.Bridge:
details += qsTr("Bridge transaction details") + endl2
break
case Constants.TransactionType.ContractDeployment:
details += qsTr("Contract deployment details") + endl2
break
default:
break
}
@ -188,6 +191,7 @@ StatusListItem {
case Constants.TransactionType.Destroy:
case Constants.TransactionType.Swap:
case Constants.TransactionType.Bridge:
case Constants.TransactionType.ContractDeployment:
details += subTitle + endl2
break
default:
@ -254,6 +258,18 @@ StatusListItem {
details += qsTr("To") + endl + toNetworkName + endl2
details += qsTr("In") + endl + modelData.from + endl2
break
case Constants.TransactionType.ContractDeployment:
details += qsTr("From") + endl + modelData.sender + endl2
const failed = root.transactionStatus === Constants.TransactionStatus.Failed
const isPending = root.transactionStatus === Constants.TransactionStatus.Pending || !modelData.contract
if (failed) {
details += qsTr("To\nContract address not created")
} else if (isPending) {
details += qsTr("To\nAwaiting contract address...")
} else {
details += qsTr("To\nContract created") + endl + modelData.contract + endl2
}
break
default:
details += qsTr("From") + endl + modelData.sender + endl2
details += qsTr("To") + endl + modelData.recipient + endl2
@ -275,7 +291,7 @@ StatusListItem {
details += qsTr("%1 %2 contract address").arg(root.networkName).arg(protocolName) + endl
details += protocolFromContractAddress + endl2
}
if (!!modelData.contract) {
if (!!modelData.contract && type !== Constants.TransactionType.ContractDeployment) {
let symbol = !!modelData.symbol || !modelData.contract ? modelData.symbol : "(%1)".arg(Utils.compactAddress(modelData.contract, 4))
details += qsTr("%1 %2 contract address").arg(root.networkName).arg(symbol) + endl
details += modelData.contract + endl2
@ -367,6 +383,18 @@ StatusListItem {
valuesString += qsTr("Fees %1 (%2)").arg(feeCrypto).arg(feeFiat) + endl2
} else if (type === Constants.TransactionType.Receive || (type === Constants.TransactionType.Buy && isLayer1)) {
valuesString += qsTr("Total %1 (%2)").arg(root.transactionValue).arg(fiatTransactionValue) + endl2
} else if (type === Constants.TransactionType.ContractDeployment) {
const isPending = root.transactionStatus === Constants.TransactionStatus.Pending
if (isPending) {
const maxFeeEthValue = rootStore.getGasEthValue(modelData.maxTotalFees.amount, 1)
const maxFeeCrypto = rootStore.formatCurrencyAmount(maxFeeEthValue, "ETH")
const maxFeeFiat = rootStore.formatCurrencyAmount(maxFeeCrypto, root.currentCurrency)
valuesString += qsTr("Estimated max fee %1 (%2)").arg(maxFeeCrypto).arg(maxFeeFiat) + endl2
} else {
const feeCrypto = rootStore.formatCurrencyAmount(feeEthValue, "ETH")
const feeFiat = rootStore.formatCurrencyAmount(feeFiatValue, root.currentCurrency)
valuesString += qsTr("Fees %1 (%2)").arg(feeCrypto).arg(feeFiat) + endl2
}
} else {
const feeEth = rootStore.formatCurrencyAmount(feeEthValue, "ETH")
const txValue = isMultiTransaction ? root.inTransactionValue : root.transactionValue
@ -416,6 +444,8 @@ StatusListItem {
return "swap"
case Constants.TransactionType.Bridge:
return "bridge"
case Constants.TransactionType.ContractDeployment:
return "contract_deploy"
default:
return ""
}
@ -463,6 +493,8 @@ StatusListItem {
return failed ? qsTr("Swap failed") : (isPending ? qsTr("Swapping") : qsTr("Swapped"))
case Constants.TransactionType.Bridge:
return failed ? qsTr("Bridge failed") : (isPending ? qsTr("Bridging") : qsTr("Bridged"))
case Constants.TransactionType.ContractDeployment:
return failed ? qsTr("Contract deployment failed") : (isPending ? qsTr("Deploying contract") : qsTr("Contract deployed"))
default:
return ""
}
@ -475,7 +507,8 @@ StatusListItem {
statusListItemTitleIcons.sourceComponent: Row {
spacing: 8
Row {
visible: !root.loading
id: tokenImagesRow
visible: !root.loading && !!root.tokenIconAsset.name
spacing: secondTokenImage.visible ? -tokenImage.width * 0.2 : 0
StatusRoundIcon {
id: tokenImage
@ -508,6 +541,7 @@ StatusListItem {
visible: !!text
loading: root.loading
customColor: Theme.palette.baseColor1
leftPadding: tokenImagesRow.visible ? 0 : parent.spacing
}
}
@ -533,6 +567,10 @@ StatusListItem {
case Constants.TransactionType.Bridge:
let toNetworkName = "" // TODO fill when Bridge data is implemented
return qsTr("%1 from %2 to %3").arg(inTransactionValue).arg(networkName).arg(toNetworkName)
case Constants.TransactionType.ContractDeployment:
const name = addressNameTo || addressNameFrom
return !!modelData.contract ? qsTr("Contract %1 via %2 on %3").arg(Utils.compactAddress(modelData.contract, 4)).arg(name).arg(networkName)
: qsTr("Via %1 on %2").arg(name).arg(networkName)
default:
return qsTr("%1 to %2 via %3").arg(transactionValue).arg(toAddress).arg(networkName)
}

View File

@ -1007,7 +1007,8 @@ QtObject {
Buy,
Swap,
Bridge,
Sell, // TODO update value when added to backend
ContractDeployment,
Sell,
Destroy // TODO update value when added to backend
}