fix(networks): enable network before mint or airdrop (#15601)

Fixes #15507

Makes sure to enable the network where the owner token was minted before minting or airdroping a token.
This makes sure that the account selector shows the right balance and there is no ETH error before doing the transation
This commit is contained in:
Jonathan Rainville 2024-07-22 09:52:44 -04:00 committed by GitHub
parent 83db905e28
commit 8db0ac94f0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
12 changed files with 170 additions and 15 deletions

View File

@ -91,6 +91,9 @@ QtObject:
let (chainIds, enable) = self.flatNetworks.networksToChangeStateOnUserActionFor(chainId, self.areTestNetworksEnabled)
self.delegate.setNetworksState(chainIds, enable)
proc enableNetwork*(self: View, chainId: int) {.slot.} =
self.delegate.setNetworksState(@[chainId], enable = true)
proc getNetworkShortNames*(self: View, preferredNetworks: string): string {.slot.} =
return self.flatNetworks.getNetworkShortNames(preferredNetworks, self.areTestNetworksEnabled)

View File

@ -235,6 +235,8 @@ StackLayout {
id: communitySettingsView
rootStore: root.rootStore
walletAccountsModel: WalletStore.RootStore.nonWatchAccounts
enabledChainIds: WalletStore.RootStore.networkFilters
onEnableNetwork: WalletStore.RootStore.enableNetwork(chainId)
tokensStore: root.tokensStore
sendModalPopup: root.sendModalPopup
transactionStore: root.transactionStore

View File

@ -33,12 +33,15 @@ StackView {
required property var membersModel
required property var accountsModel
required property string enabledChainIds
property int viewWidth: 560 // by design
property string previousPageName: depth > 1 ? qsTr("Airdrops") : ""
signal airdropClicked(var airdropTokens, var addresses, string feeAccountAddress)
signal navigateToMintTokenSettings(bool isAssetType)
signal registerAirdropFeeSubscriber(var feeSubscriber)
signal enableNetwork(int chainId)
function navigateBack() {
pop(StackView.Immediate)
@ -120,6 +123,8 @@ StackView {
feeErrorText: feesSubscriber.feesError
feesPerSelectedContract: feesSubscriber.feesPerContract
feesAvailable: !!feesSubscriber.airdropFeesResponse
enabledChainIds: root.enabledChainIds
onEnableNetwork: root.enableNetwork(chainId)
onAirdropClicked: {
root.airdropClicked(airdropTokens, addresses, feeAccountAddress)

View File

@ -49,15 +49,19 @@ StackView {
// It will monitorize if Owner and/or TMaster token items are included in the `tokensModel` despite the deployment state
property bool ownerOrTMasterTokenItemsExist: false
// Network related properties:
property var flatNetworks
readonly property int ownerTokenChainId: SQUtils.ModelUtils.get(root.tokensModel, "privilegesLevel", Constants.TokenPrivilegesLevel.Owner).chainId ?? 0
readonly property int chainIndex: NetworkModelHelpers.getChainIndexByChainId(root.flatNetworks, root.ownerTokenChainId)
readonly property string chainName: NetworkModelHelpers.getChainName(root.flatNetworks, chainIndex)
property string enabledChainIds
// Models:
property var tokensModel
property var membersModel
property var accounts // Expected roles: address, name, color, emoji, walletType
required property var referenceAssetsBySymbolModel
// Network related properties:
property var flatNetworks
signal mintCollectible(var collectibleItem)
signal mintAsset(var assetItem)
signal mintOwnerToken(var ownerToken, var tMasterToken)
@ -83,6 +87,8 @@ StackView {
signal startTokenHoldersManagement(int chainId, string address)
signal stopTokenHoldersManagement()
signal enableNetwork(int chainId)
function navigateBack() {
pop(StackView.Immediate)
}
@ -122,6 +128,8 @@ StackView {
QtObject {
id: d
property string networkThatIsNotActive
// Owner or TMaster token retry navigation
function retryPrivilegedToken(key, chainId, accountName, accountAddress) {
var properties = {
@ -136,6 +144,18 @@ StackView {
}
}
onVisibleChanged: {
if (!visible) {
return
}
// If the tokens' network is not activated, show a warning to the user
if (!root.enabledChainIds.includes(root.ownerTokenChainId)) {
d.networkThatIsNotActive = root.chainName
} else {
d.networkThatIsNotActive = ""
}
}
initialItem: SettingsPage {
implicitWidth: 0
title: qsTr("Tokens")
@ -276,18 +296,15 @@ StackView {
SettingsPage {
id: newTokenPage
readonly property int ownerTokenChainId: SQUtils.ModelUtils.get(root.tokensModel, "privilegesLevel", Constants.TokenPrivilegesLevel.Owner).chainId ?? 0
readonly property int chainIndex: NetworkModelHelpers.getChainIndexByChainId(root.flatNetworks, ownerTokenChainId)
readonly property string chainName: NetworkModelHelpers.getChainName(root.flatNetworks, chainIndex)
readonly property string chainIcon: NetworkModelHelpers.getChainIconUrl(root.flatNetworks, chainIndex)
readonly property string chainIcon: NetworkModelHelpers.getChainIconUrl(root.flatNetworks, root.chainIndex)
property TokenObject asset: TokenObject{
type: Constants.TokenType.ERC20
multiplierIndex: 18
// Minted tokens will use ALWAYS the same chain where the owner token was deployed.
chainId: newTokenPage.ownerTokenChainId
chainName: newTokenPage.chainName
chainId: root.ownerTokenChainId
chainName: root.chainName
chainIcon: newTokenPage.chainIcon
}
@ -295,13 +312,11 @@ StackView {
type: Constants.TokenType.ERC721
// Minted tokens will use ALWAYS the same chain where the owner token was deployed.
chainId: newTokenPage.ownerTokenChainId
chainName: newTokenPage.chainName
chainId: root.ownerTokenChainId
chainName: root.chainName
chainIcon: newTokenPage.chainIcon
}
property bool isAssetView: false
property int validationMode: StatusInput.ValidationMode.OnlyWhenDirty
property string referenceName: ""
@ -373,6 +388,12 @@ StackView {
feeErrorText: deployFeeSubscriber.feeErrorText
isFeeLoading: !deployFeeSubscriber.feesResponse
networkThatIsNotActive: d.networkThatIsNotActive
onEnableNetwork: {
root.enableNetwork(root.ownerTokenChainId)
d.networkThatIsNotActive = ""
}
onPreviewClicked: {
const properties = {
token: token
@ -780,7 +801,13 @@ StackView {
feeText: remotelyDestructFeeSubscriber.feeText
feeErrorText: remotelyDestructFeeSubscriber.feeErrorText
isFeeLoading: !remotelyDestructFeeSubscriber.feesResponse
isFeeLoading: !remotelyDestructFeeSubscriber.feesResponse
networkThatIsNotActive: d.networkThatIsNotActive
onEnableNetwork: {
root.enableNetwork(root.ownerTokenChainId)
d.networkThatIsNotActive = ""
}
onRemotelyDestructClicked: {
remotelyDestructPopup.close()
@ -812,6 +839,12 @@ StackView {
tokenSource: footer.token.artworkSource
chainName: footer.token.chainName
networkThatIsNotActive: d.networkThatIsNotActive
onEnableNetwork: {
root.enableNetwork(root.ownerTokenChainId)
d.networkThatIsNotActive = ""
}
onAmountToBurnChanged: burnTokensFeeSubscriber.updateAmount()
feeText: burnTokensFeeSubscriber.feeText

View File

@ -0,0 +1,26 @@
import QtQuick 2.15
import QtQuick.Layouts 1.15
import StatusQ.Core 0.1
import StatusQ.Controls 0.1
RowLayout {
id: root
property string networkThatIsNotActive
signal enableNetwork
spacing: 6
WarningPanel {
id: wantedNetworkNotActive
Layout.fillWidth: true
text: qsTr("The owner token is minted on a network that isn't selected. Click here to enable it:")
}
StatusButton {
text: qsTr("Enable %1").arg(root.networkThatIsNotActive)
Layout.alignment: Qt.AlignVCenter
onClicked: root.enableNetwork()
}
}

View File

@ -19,6 +19,7 @@ MembersSettingsPanel 1.0 MembersSettingsPanel.qml
MembersTabPanel 1.0 MembersTabPanel.qml
MintTokensFooterPanel 1.0 MintTokensFooterPanel.qml
MintTokensSettingsPanel 1.0 MintTokensSettingsPanel.qml
NetworkWarningPanel 1.0 NetworkWarningPanel.qml
OverviewSettingsChart 1.0 OverviewSettingsChart.qml
OverviewSettingsFooter 1.0 OverviewSettingsFooter.qml
OverviewSettingsPanel 1.0 OverviewSettingsPanel.qml

View File

@ -26,6 +26,7 @@ StatusDialog {
property int multiplierIndex
property url tokenSource
property string chainName
property string networkThatIsNotActive
readonly property alias amountToBurn: d.amountToBurn
readonly property alias selectedAccountAddress: d.accountAddress
@ -41,6 +42,7 @@ StatusDialog {
signal burnClicked(string burnAmount, string accountAddress)
signal cancelClicked
signal enableNetwork
QtObject {
id: d
@ -186,6 +188,14 @@ StatusDialog {
readonly property bool error: d.isFeeError
}
}
NetworkWarningPanel {
visible: !!root.networkThatIsNotActive
Layout.fillWidth: true
networkThatIsNotActive: root.networkThatIsNotActive
onEnableNetwork: root.enableNetwork()
}
}
header: StatusDialogHeader {

View File

@ -19,6 +19,7 @@ StatusDialog {
property alias model: tokenHoldersPanel.model
property string collectibleName
property string chainName
property string networkThatIsNotActive
// Fees related properties:
property bool isFeeLoading
@ -38,6 +39,7 @@ StatusDialog {
property var accounts
signal remotelyDestructClicked(var walletsAndAmounts, string accountAddress)
signal enableNetwork
QtObject {
id: d
@ -103,7 +105,7 @@ StatusDialog {
id: feesBox
Layout.fillWidth: true
Layout.bottomMargin: 16
Layout.bottomMargin: networkWarningPanel.visible ? 0 : 16
Layout.leftMargin: 16
Layout.rightMargin: 16
@ -129,6 +131,19 @@ StatusDialog {
readonly property bool error: d.isFeeError
}
}
NetworkWarningPanel {
id: networkWarningPanel
visible: !!root.networkThatIsNotActive
Layout.fillWidth: true
Layout.bottomMargin: 16
Layout.leftMargin: 18
Layout.rightMargin: 18
networkThatIsNotActive: root.chainName
onEnableNetwork: root.enableNetwork()
}
}
footer: StatusDialogFooter {

View File

@ -40,6 +40,8 @@ StatusSectionLayout {
property bool communitySettingsDisabled
property var sendModalPopup
required property string enabledChainIds
required property var walletAccountsModel // name, address, emoji, color
readonly property bool isOwner: community.memberRole === Constants.memberRole.owner
@ -51,6 +53,8 @@ StatusSectionLayout {
required property bool isPendingOwnershipRequest
signal finaliseOwnershipClicked
signal enableNetwork(int chainId)
readonly property string filteredSelectedTags: {
let tagsArray = []
if (community && community.tags) {
@ -334,6 +338,7 @@ StatusSectionLayout {
readonly property string sectionName: qsTr("Tokens")
readonly property string sectionIcon: "token"
readonly property bool sectionEnabled: true
enabledChainIds: root.enabledChainIds
readonly property CommunityTokensStore communityTokensStore:
rootStore.communityTokensStore
@ -373,6 +378,8 @@ StatusSectionLayout {
onStopTokenHoldersManagement: communityTokensStore.stopTokenHoldersManagement()
onEnableNetwork: root.enableNetwork(chainId)
onMintCollectible:
communityTokensStore.deployCollectible(
root.community.id, collectibleItem)
@ -526,6 +533,8 @@ StatusSectionLayout {
assetsModel: assetsModelLoader.item
collectiblesModel: collectiblesModelLoader.item
membersModel: community.members
enabledChainIds: root.enabledChainIds
onEnableNetwork: root.enableNetwork(chainId)
accountsModel: root.walletAccountsModel
onAirdropClicked: communityTokensStore.airdrop(

View File

@ -45,6 +45,8 @@ StatusScrollView {
// Bool property indicating whether the fees are available
required property bool feesAvailable
property string enabledChainIds
property int viewWidth: 560 // by design
readonly property var selectedHoldingsModel: ListModel {}
@ -101,6 +103,8 @@ StatusScrollView {
signal navigateToMintTokenSettings(bool isAssetType)
signal enableNetwork(int chainId)
function selectToken(key, amount, type) {
if(selectedHoldingsModel)
selectedHoldingsModel.clear()
@ -125,6 +129,9 @@ StatusScrollView {
&& airdropRecipientsSelector.valid
&& airdropRecipientsSelector.count > 0
property string networkThatIsNotActive
property int networkIdThatIsNotActive
readonly property var selectedContractKeysAndAmounts: {
//Depedencies:
root.selectedHoldingsModel
@ -161,6 +168,7 @@ StatusScrollView {
key, amount, type,
tokenText: amountLocalized + " " + modelItem.name,
tokenImage: modelItem.iconSource,
networkId: modelItem.chainId,
networkText: modelItem.chainName,
networkImage: Style.svg(modelItem.chainIcon),
remainingSupply: modelItem.remainingSupply,
@ -292,12 +300,25 @@ StatusScrollView {
root.selectedHoldingsModel, ["key", "amount"])
}
function isChainEnabled(entry) {
// If the tokens' network is not activated, show a warning to the user
if (!!entry && !root.enabledChainIds.includes(entry.networkId)) {
d.networkThatIsNotActive = entry.networkText
d.networkIdThatIsNotActive = entry.networkId
} else {
d.networkThatIsNotActive = ""
d.networkIdThatIsNotActive = 0
}
}
onAddAsset: {
const entry = d.prepareEntry(key, amount, Constants.TokenType.ERC20)
entry.valid = true
selectedHoldingsModel.append(entry)
dropdown.close()
isChainEnabled(entry)
}
onAddCollectible: {
@ -306,6 +327,8 @@ StatusScrollView {
selectedHoldingsModel.append(entry)
dropdown.close()
isChainEnabled(entry)
}
onUpdateAsset: {
@ -554,6 +577,18 @@ StatusScrollView {
recipientsCountInstantiator.maximumRecipientsCount < airdropRecipientsSelector.count
}
NetworkWarningPanel {
visible: !!d.networkThatIsNotActive
Layout.fillWidth: true
Layout.topMargin: Style.current.padding
networkThatIsNotActive: d.networkThatIsNotActive
onEnableNetwork: {
root.enableNetwork(d.networkIdThatIsNotActive)
d.networkThatIsNotActive = ""
d.networkIdThatIsNotActive = 0
}
}
StatusButton {
Layout.preferredHeight: 44
Layout.alignment: Qt.AlignHCenter

View File

@ -44,6 +44,9 @@ StatusScrollView {
property string feeErrorText
property bool isFeeLoading
property string networkThatIsNotActive
signal enableNetwork
readonly property string feeLabel:
isAssetView ? qsTr("Mint asset on %1").arg(root.token.chainName)
: qsTr("Mint collectible on %1").arg(root.token.chainName)
@ -253,6 +256,15 @@ StatusScrollView {
}
}
NetworkWarningPanel {
visible: !!root.networkThatIsNotActive
Layout.fillWidth: true
Layout.topMargin: Style.current.padding
networkThatIsNotActive: root.networkThatIsNotActive
onEnableNetwork: root.enableNetwork()
}
CustomSwitchRowComponent {
id: unlimitedSupplyChecker

View File

@ -375,6 +375,10 @@ QtObject {
networksModule.toggleNetwork(chainId)
}
function enableNetwork(chainId) {
networksModule.enableNetwork(chainId)
}
function copyToClipboard(text) {
globalUtils.copyToClipboard(text)
}