import QtQuick 2.14
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.14
import utils 1.0
import shared.popups 1.0
import shared.status 1.0
import shared.popups.send 1.0
import shared.stores.send 1.0
import StatusQ 0.1
import StatusQ.Core 0.1
import StatusQ.Core.Theme 0.1
import StatusQ.Core.Utils 0.1
import StatusQ.Controls 0.1
import StatusQ.Components 0.1
import AppLayouts.Wallet.stores 1.0
Item {
id: root
property var ensUsernamesStore
property var contactsStore
required property TransactionStore transactionStore
property WalletAssetsStore walletAssetsStore
property string username: ""
signal backBtnClicked();
signal usernameRegistered(userName: string);
QtObject {
id: d
readonly property var sntToken: ModelUtils.getByKey(root.walletAssetsStore.groupedAccountAssetsModel, "tokensKey", root.ensUsernamesStore.getStatusTokenKey())
readonly property SumAggregator aggregator: SumAggregator {
model: !!d.sntToken && !!d.sntToken.balances ? d.sntToken.balances: nil
roleName: "balance"
}
property real sntBalance: !!sntToken && !!sntToken.decimals ? aggregator.value/(10 ** sntToken.decimals): 0
}
StatusBaseText {
id: sectionTitle
text: qsTr("ENS usernames")
anchors.left: parent.left
anchors.leftMargin: 24
anchors.top: parent.top
anchors.topMargin: 24
font.weight: Font.Bold
font.pixelSize: 20
color: Theme.palette.directColor1
StatusBetaTag {
anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.right
anchors.leftMargin: 7
}
}
Loader {
id: transactionDialog
function open() {
this.active = true
this.item.open()
}
function closed() {
this.active = false // kill an opened instance
}
sourceComponent: SendModal {
id: buyEnsModal
interactive: false
store: root.transactionStore
preSelectedSendType: Constants.SendType.ENSRegister
preSelectedRecipient: root.ensUsernamesStore.getEnsRegisteredAddress()
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(10)
preSelectedHoldingID: !!d.sntToken && !!d.sntToken.symbol ? d.sntToken.symbol: ""
preSelectedHoldingType: Constants.TokenType.ERC20
sendTransaction: function() {
if(bestRoutes.count === 1) {
let path = bestRoutes.firstItem()
let eip1559Enabled = path.gasFees.eip1559Enabled
let maxFeePerGas = path.gasFees.maxFeePerGasM
root.ensUsernamesStore.authenticateAndRegisterEns(
root.ensUsernamesStore.chainId,
username,
store.selectedSenderAccountAddress,
path.gasAmount,
eip1559Enabled ? "" : path.gasFees.gasPrice,
eip1559Enabled ? path.gasFees.maxPriorityFeePerGas : "",
eip1559Enabled ? maxFeePerGas: path.gasFees.gasPrice,
eip1559Enabled,
)
}
}
Connections {
target: root.ensUsernamesStore.ensUsernamesModule
function onTransactionWasSent(chainId: int, txHash: string, error: string) {
if (!!error) {
if (error.includes(Constants.walletSection.cancelledMessage)) {
return
}
buyEnsModal.sendingError.text = error
return buyEnsModal.sendingError.open()
}
usernameRegistered(username)
let url = "%1/%2".arg(buyEnsModal.store.getEtherscanLink(chainId)).arg(txHash)
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
url)
}
}
}
}
// TODO: Replace with StatusModal
ModalPopup {
id: popup
title: qsTr("Terms of name registration")
StatusScrollView {
id: scroll
anchors.fill: parent
contentWidth: availableWidth
Column {
spacing: Style.current.halfPadding
width: scroll.availableWidth
StatusBaseText {
text: qsTr("Funds are deposited for 1 year. Your SNT will be locked, but not spent.")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("After 1 year, you can release the name and get your deposit back, or take no action to keep the name.")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("If terms of the contract change — e.g. Status makes contract upgrades — user has the right to release the username regardless of time held.")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("The contract controller cannot access your deposited funds. They can only be moved back to the address that sent them.")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("Your address(es) will be publicly associated with your ENS name.")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("Usernames are created as subdomain nodes of stateofus.eth and are subject to the ENS smart contract terms.")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("You authorize the contract to transfer SNT on your behalf. This can only occur when you approve a transaction to authorize the transfer.")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("These terms are guaranteed by the smart contract logic at addresses:")
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
font.weight: Font.Bold
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("%1 (Status UsernameRegistrar).").arg(root.ensUsernamesStore.getEnsRegisteredAddress())
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
font.family: Style.current.monoFont.name
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("Look up on Etherscan")
.arg(root.ensUsernamesStore.getEtherscanLink())
.arg(root.ensUsernamesStore.getEnsRegisteredAddress())
anchors.left: parent.left
anchors.right: parent.right
onLinkActivated: Global.openLink(link)
color: Theme.palette.directColor1
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton // we don't want to eat clicks on the Text
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
StatusBaseText {
text: qsTr("%1 (ENS Registry).").arg(root.ensUsernamesStore.getEnsRegistry())
wrapMode: Text.WordWrap
anchors.left: parent.left
anchors.right: parent.right
font.family: Style.current.monoFont.name
color: Theme.palette.directColor1
}
StatusBaseText {
text: qsTr("Look up on Etherscan")
.arg(root.ensUsernamesStore.getEtherscanLink())
.arg(root.ensUsernamesStore.getEnsRegistry())
anchors.left: parent.left
anchors.right: parent.right
onLinkActivated: Global.openLink(link)
color: Theme.palette.directColor1
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton // we don't want to eat clicks on the Text
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}
}
}
StatusScrollView {
id: sview
anchors.top: sectionTitle.bottom
anchors.topMargin: Style.current.padding
anchors.bottom: startBtn.top
anchors.bottomMargin: Style.current.padding
anchors.left: parent.left
anchors.right: parent.right
contentWidth: availableWidth
Item {
id: contentItem
width: sview.availableWidth
Rectangle {
id: circleAt
anchors.top: parent.top
anchors.topMargin: 24
anchors.horizontalCenter: parent.horizontalCenter
width: 60
height: 60
radius: 120
color: Style.current.blue
StatusBaseText {
text: "@"
opacity: 0.7
font.weight: Font.Bold
font.pixelSize: 18
color: Style.current.white
anchors.horizontalCenter: parent.horizontalCenter
anchors.verticalCenter: parent.verticalCenter
}
}
StatusBaseText {
id: ensUsername
text: username + ".stateofus.eth"
font.weight: Font.Bold
font.pixelSize: 18
anchors.top: circleAt.bottom
anchors.topMargin: 24
anchors.left: parent.left
anchors.right: parent.right
horizontalAlignment: Text.AlignHCenter
color: Theme.palette.directColor1
}
StatusDescriptionListItem {
id: walletAddressLbl
title: qsTr("Wallet address")
subTitle: root.ensUsernamesStore.getWalletDefaultAddress()
tooltip.text: qsTr("Copied to clipboard!")
asset.name: "copy"
iconButton.onClicked: {
root.ensUsernamesStore.copyToClipboard(subTitle)
tooltip.visible = !tooltip.visible
}
anchors.top: ensUsername.bottom
anchors.topMargin: 24
}
StatusDescriptionListItem {
id: keyLbl
title: qsTr("Key")
subTitle: {
let pubKey = root.ensUsernamesStore.pubkey;
return pubKey.substring(0, 20) + "..." + pubKey.substring(pubKey.length - 20);
}
tooltip.text: qsTr("Copied to clipboard!")
asset.name: "copy"
iconButton.onClicked: {
root.ensUsernamesStore.copyToClipboard(root.ensUsernamesStore.pubkey)
tooltip.visible = !tooltip.visible
}
anchors.top: walletAddressLbl.bottom
anchors.topMargin: 24
}
StatusCheckBox {
id: termsAndConditionsCheckbox
objectName: "ensAgreeTerms"
anchors.top: keyLbl.bottom
anchors.topMargin: Style.current.padding
anchors.left: parent.left
anchors.leftMargin: 24
}
StatusBaseText {
text: qsTr("Agree to Terms of name registration. I understand that my wallet address will be publicly connected to my username.")
anchors.left: termsAndConditionsCheckbox.right
anchors.leftMargin: Style.current.halfPadding
anchors.right: parent.right
wrapMode: Text.WordWrap
anchors.verticalCenter: termsAndConditionsCheckbox.verticalCenter
onLinkActivated: popup.open()
color: Theme.palette.directColor1
TapHandler {
enabled: !parent.hoveredLink
onSingleTapped: termsAndConditionsCheckbox.toggle()
}
MouseArea {
anchors.fill: parent
acceptedButtons: Qt.NoButton // we don't want to eat clicks on the Text
cursorShape: parent.hoveredLink ? Qt.PointingHandCursor : Qt.ArrowCursor
}
}
}
}
StatusButton {
anchors.bottom: parent.bottom
anchors.bottomMargin: Style.current.padding
anchors.left: parent.left
anchors.leftMargin: Style.current.padding
text: qsTr("Back")
onClicked: backBtnClicked()
}
Item {
anchors.top: startBtn.top
anchors.right: startBtn.left
anchors.rightMargin: Style.current.padding
width: childrenRect.width
Image {
id: image1
height: 50
width: height
source: Style.png("tokens/SNT")
sourceSize: Qt.size(width, height)
cache: false
}
StatusBaseText {
id: ensPriceLbl
text: qsTr("10 SNT")
anchors.left: image1.right
anchors.leftMargin: 5
anchors.top: image1.top
color: Theme.palette.directColor1
font.pixelSize: 14
}
StatusBaseText {
text: qsTr("Deposit")
anchors.left: image1.right
anchors.leftMargin: 5
anchors.topMargin: 5
anchors.top: ensPriceLbl.bottom
color: Theme.palette.baseColor1
font.pixelSize: 14
}
}
StatusButton {
id: startBtn
objectName: "ensStartTransaction"
anchors.bottom: parent.bottom
anchors.bottomMargin: Style.current.padding
anchors.right: parent.right
anchors.rightMargin: Style.current.padding
text: d.sntBalance < 10 ?
qsTr("Not enough SNT") :
qsTr("Register")
enabled: d.sntBalance >= 10 && termsAndConditionsCheckbox.checked
onClicked: transactionDialog.open()
}
}