2023-06-22 21:24:30 +00:00
import QtQuick 2.15
import QtQuick . Controls 2.15
import QtQuick . Layouts 1.15
2023-03-09 11:12:49 +00:00
import QtQml 2.15
2023-03-07 11:32:45 +00:00
2023-05-22 13:00:40 +00:00
import StatusQ . Controls 0.1
2024-07-12 09:46:43 +00:00
import StatusQ . Core . Backpressure 0.1
import StatusQ . Core . Theme 0.1
2023-07-18 17:34:57 +00:00
import StatusQ . Core . Utils 0.1 as SQUtils
2023-02-17 11:57:17 +00:00
2023-06-28 19:30:01 +00:00
import AppLayouts . Communities . controls 1.0
2023-06-23 06:17:04 +00:00
import AppLayouts . Communities . helpers 1.0
2023-06-28 22:11:58 +00:00
import AppLayouts . Communities . layouts 1.0
2023-06-28 19:30:01 +00:00
import AppLayouts . Communities . popups 1.0
import AppLayouts . Communities . views 1.0
2023-09-12 09:26:25 +00:00
import AppLayouts . Wallet . helpers 1.0
2023-02-17 11:57:17 +00:00
2023-07-06 12:33:27 +00:00
import shared . controls 1.0
2023-02-17 11:57:17 +00:00
import utils 1.0
2023-06-27 19:56:44 +00:00
import shared . popups 1.0
2023-03-28 13:55:34 +00:00
import SortFilterProxyModel 0.2
2023-02-17 11:57:17 +00:00
2023-06-28 19:30:01 +00:00
StackView {
2023-02-17 11:57:17 +00:00
id: root
2023-06-01 10:38:56 +00:00
// General properties:
2023-07-18 17:34:57 +00:00
property int viewWidth: 560 // by design
2023-08-01 10:31:50 +00:00
property string previousPageName: depth > 1 ? qsTr ( "Back" ) : ""
2023-08-30 07:20:28 +00:00
required property string communityId
2023-07-06 12:33:27 +00:00
required property string communityName
2023-07-10 14:12:25 +00:00
required property string communityLogo
required property color communityColor
2023-09-14 10:02:51 +00:00
property var sendModalPopup
2023-07-10 14:12:25 +00:00
2023-07-18 17:34:57 +00:00
// User profile props:
required property bool isOwner
required property bool isTokenMasterOwner
required property bool isAdmin
readonly property bool isAdminOnly: root . isAdmin && ! root . isPrivilegedTokenOwnerProfile
readonly property bool isPrivilegedTokenOwnerProfile: root . isOwner || root . isTokenMasterOwner
// Owner and TMaster token related properties:
readonly property bool arePrivilegedTokensDeployed: root . isOwnerTokenDeployed && root . isTMasterTokenDeployed
property bool isOwnerTokenDeployed: false
property bool isTMasterTokenDeployed: false
2023-08-01 10:31:50 +00:00
property bool anyPrivilegedTokenFailed: false
2023-07-18 17:34:57 +00:00
// It will monitorize if Owner and/or TMaster token items are included in the `tokensModel` despite the deployment state
property bool ownerOrTMasterTokenItemsExist: false
2023-06-01 10:38:56 +00:00
2024-07-22 13:52:44 +00:00
// 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
2023-03-08 13:44:47 +00:00
// Models:
2023-02-17 11:57:17 +00:00
property var tokensModel
2024-02-28 18:02:44 +00:00
property var membersModel
2023-06-20 10:12:56 +00:00
property var accounts // Expected roles: address, name, color, emoji, walletType
2023-11-22 13:50:07 +00:00
required property var referenceAssetsBySymbolModel
2023-06-01 10:38:56 +00:00
signal mintCollectible ( var collectibleItem )
signal mintAsset ( var assetItem )
2023-07-18 12:39:38 +00:00
signal mintOwnerToken ( var ownerToken , var tMasterToken )
2023-06-28 19:30:01 +00:00
2023-08-31 22:26:24 +00:00
signal kickUserRequested ( string contactId )
signal banUserRequested ( string contactId )
2023-08-17 13:58:04 +00:00
signal remotelyDestructCollectibles ( var walletsAndAmounts , // { [walletAddress (string), amount (int)] }
2023-08-10 09:39:52 +00:00
string tokenKey ,
string accountAddress )
2023-09-21 13:02:18 +00:00
signal remotelyDestructAndBan ( string contactId , string tokenKey , string accountAddress ,
bool removeMessages )
signal remotelyDestructAndKick ( string contactId , string tokenKey , string accountAddress )
2023-08-10 12:23:59 +00:00
signal burnToken ( string tokenKey , string amount , string accountAddress )
signal airdropToken ( string tokenKey , string amount , int type , var addresses )
2023-05-30 15:18:45 +00:00
signal deleteToken ( string tokenKey )
2024-05-21 08:53:33 +00:00
signal refreshToken ( string tokenKey )
2023-09-01 09:27:44 +00:00
signal registerDeployFeesSubscriber ( var feeSubscriber )
signal registerSelfDestructFeesSubscriber ( var feeSubscriber )
signal registerBurnTokenFeesSubscriber ( var feeSubscriber )
2023-04-17 12:11:31 +00:00
2024-06-03 08:31:26 +00:00
signal startTokenHoldersManagement ( int chainId , string address )
signal stopTokenHoldersManagement ( )
2024-07-22 13:52:44 +00:00
signal enableNetwork ( int chainId )
2023-02-17 11:57:17 +00:00
function navigateBack ( ) {
2023-06-28 19:30:01 +00:00
pop ( StackView . Immediate )
2023-02-17 11:57:17 +00:00
}
2023-06-28 19:30:01 +00:00
function resetNavigation ( ) {
pop ( initialItem , StackView . Immediate )
2023-06-14 07:19:45 +00:00
}
2024-03-25 10:05:31 +00:00
// This method will be called from the outside from a different section like Airdrop or Permissions
2023-06-28 19:30:01 +00:00
function openNewTokenForm ( isAssetView ) {
resetNavigation ( )
2023-07-18 17:34:57 +00:00
if ( root . isAdminOnly ) {
2023-08-02 12:01:10 +00:00
// Admins can only see the initial tokens page. They cannot mint. Initial view.
2023-07-18 17:34:57 +00:00
return
}
2023-08-01 10:31:50 +00:00
if ( root . arePrivilegedTokensDeployed ) {
// Regular minting flow for Owner and TMaster owner, selecting the specific tab
const properties = { isAssetView }
root . push ( newTokenViewComponent , properties , StackView . Immediate )
2023-07-18 17:34:57 +00:00
return
}
if ( root . ownerOrTMasterTokenItemsExist ) {
2023-08-02 12:01:10 +00:00
// Owner and TMaster tokens deployment action has been started at least ones but still without success. Initial view.
2023-07-18 17:34:57 +00:00
return
}
if ( root . isOwner ) {
2023-08-01 10:31:50 +00:00
// Owner and TMaster tokens to be deployed. Never tried.
2023-07-10 14:12:25 +00:00
root . push ( ownerTokenViewComponent , StackView . Immediate )
2023-07-18 17:34:57 +00:00
return
2023-07-10 14:12:25 +00:00
}
2023-03-07 11:32:45 +00:00
}
2023-08-01 10:31:50 +00:00
QtObject {
id: d
2024-07-22 13:52:44 +00:00
property string networkThatIsNotActive
2023-08-01 10:31:50 +00:00
// Owner or TMaster token retry navigation
function retryPrivilegedToken ( key , chainId , accountName , accountAddress ) {
var properties = {
key: key ,
chainId: chainId ,
accountName: accountName ,
accountAddress: accountAddress ,
}
root . push ( ownerTokenEditViewComponent , properties ,
StackView . Immediate )
}
}
2023-05-30 15:18:45 +00:00
2024-07-22 13:52:44 +00:00
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 = ""
}
}
2023-08-02 12:01:10 +00:00
initialItem: SettingsPage {
implicitWidth: 0
title: qsTr ( "Tokens" )
2023-07-10 14:12:25 +00:00
2023-08-02 12:01:10 +00:00
buttons: [
2024-03-12 15:44:27 +00:00
StatusButton {
objectName: "addNewItemButton"
2023-08-02 12:01:10 +00:00
text: qsTr ( "Mint token" )
2024-03-12 15:44:27 +00:00
interactive: root . isPrivilegedTokenOwnerProfile && root . arePrivilegedTokensDeployed
2023-08-02 12:01:10 +00:00
onClicked: root . push ( newTokenViewComponent , StackView . Immediate )
2024-03-12 15:44:27 +00:00
tooltip.text: root . isAdminOnly ? qsTr ( "In order to mint, you must hodl the TokenMaster token for %1" ) . arg ( root . communityName ) : ""
2023-08-02 12:01:10 +00:00
}
]
contentItem: MintedTokensView {
model: SortFilterProxyModel {
sourceModel: root . tokensModel
proxyRoles: ExpressionRole {
name: "color"
expression: root . communityColor
2023-07-18 17:34:57 +00:00
}
}
2023-08-02 12:01:10 +00:00
isOwner: root . isOwner
isAdmin: root . isAdmin
communityName: root . communityName
2023-11-28 17:07:17 +00:00
communityId: root . communityId
2023-08-02 12:01:10 +00:00
anyPrivilegedTokenFailed: root . anyPrivilegedTokenFailed
onItemClicked: root . push ( tokenViewComponent , { tokenKey } , StackView . Immediate )
onMintOwnerTokenClicked: root . push ( ownerTokenViewComponent , StackView . Immediate )
onRetryOwnerTokenClicked: d . retryPrivilegedToken ( tokenKey , chainId , accountName , accountAddress )
2023-07-18 17:34:57 +00:00
}
2023-03-09 11:12:49 +00:00
}
2023-08-02 12:01:10 +00:00
Component {
id: tokenObjectComponent
TokenObject { }
}
// Mint tokens possible view contents:
2023-07-10 14:12:25 +00:00
Component {
id: ownerTokenViewComponent
SettingsPage {
id: ownerTokenPage
title: qsTr ( "Mint Owner token" )
contentItem: OwnerTokenWelcomeView {
2023-07-18 12:39:38 +00:00
viewWidth: root . viewWidth
2023-07-10 14:12:25 +00:00
communityLogo: root . communityLogo
communityColor: root . communityColor
communityName: root . communityName
2023-07-18 12:39:38 +00:00
onNextClicked: root . push ( ownerTokenEditViewComponent , StackView . Immediate )
}
}
}
Component {
id: ownerTokenEditViewComponent
SettingsPage {
id: ownerTokenPage
2023-07-18 17:34:57 +00:00
property int chainId
property string accountName
property string accountAddress
2023-07-18 12:39:38 +00:00
title: qsTr ( "Mint Owner token" )
contentItem: EditOwnerTokenView {
id: editOwnerTokenView
function signMintTransaction ( ) {
root . mintOwnerToken ( ownerToken , tMasterToken )
root . resetNavigation ( )
}
viewWidth: root . viewWidth
2023-07-18 17:34:57 +00:00
2023-07-18 12:39:38 +00:00
communityLogo: root . communityLogo
communityColor: root . communityColor
communityName: root . communityName
2023-07-18 17:34:57 +00:00
ownerToken.chainId: ownerTokenPage . chainId
ownerToken.accountName: ownerTokenPage . accountName
ownerToken.accountAddress: ownerTokenPage . accountAddress
tMasterToken.chainId: ownerTokenPage . chainId
tMasterToken.accountName: ownerTokenPage . accountName
tMasterToken.accountAddress: ownerTokenPage . accountAddress
2024-03-13 17:38:16 +00:00
flatNetworks: root . flatNetworks
2023-07-18 12:39:38 +00:00
accounts: root . accounts
2023-09-01 09:27:44 +00:00
feeText: feeSubscriber . feeText
feeErrorText: feeSubscriber . feeErrorText
isFeeLoading: ! feeSubscriber . feesResponse
2023-07-26 22:39:13 +00:00
2023-09-01 09:27:44 +00:00
onMintClicked: signMintPopup . open ( )
DeployFeesSubscriber {
id: feeSubscriber
2023-08-30 07:20:28 +00:00
communityId: root . communityId
2023-09-01 09:27:44 +00:00
chainId: editOwnerTokenView . ownerToken . chainId
tokenType: editOwnerTokenView . ownerToken . type
isOwnerDeployment: editOwnerTokenView . ownerToken . isPrivilegedToken
accountAddress: editOwnerTokenView . ownerToken . accountAddress
enabled: editOwnerTokenView . visible || signMintPopup . visible
Component.onCompleted: root . registerDeployFeesSubscriber ( feeSubscriber )
}
2023-07-26 22:39:13 +00:00
2023-09-21 16:49:57 +00:00
SignTransactionsPopup {
2023-07-18 12:39:38 +00:00
id: signMintPopup
2023-07-26 22:39:13 +00:00
title: qsTr ( "Sign transaction - Mint %1 tokens" ) . arg (
editOwnerTokenView . communityName )
2023-09-01 09:27:44 +00:00
totalFeeText: editOwnerTokenView . isFeeLoading ?
"" : editOwnerTokenView . feeText
errorText: editOwnerTokenView . feeErrorText
2023-07-18 12:39:38 +00:00
accountName: editOwnerTokenView . ownerToken . accountName
2023-07-26 22:39:13 +00:00
model: QtObject {
readonly property string title: editOwnerTokenView . feeLabel
readonly property string feeText: signMintPopup . totalFeeText
2023-09-01 09:27:44 +00:00
readonly property bool error: editOwnerTokenView . feeErrorText !== ""
2023-07-18 12:39:38 +00:00
}
2023-07-26 22:39:13 +00:00
2023-07-18 12:39:38 +00:00
onSignTransactionClicked: editOwnerTokenView . signMintTransaction ( )
}
2023-07-10 14:12:25 +00:00
}
}
}
2023-02-17 11:57:17 +00:00
Component {
2023-07-03 14:44:02 +00:00
id: newTokenViewComponent
2023-02-17 11:57:17 +00:00
2023-06-28 19:30:01 +00:00
SettingsPage {
id: newTokenPage
2023-06-09 11:50:22 +00:00
2024-07-22 13:52:44 +00:00
readonly property string chainIcon: NetworkModelHelpers . getChainIconUrl ( root . flatNetworks , root . chainIndex )
2023-09-12 09:26:25 +00:00
2023-06-22 21:24:30 +00:00
property TokenObject asset: TokenObject {
2023-07-03 14:44:02 +00:00
type: Constants . TokenType . ERC20
2023-08-10 12:23:59 +00:00
multiplierIndex: 18
2023-09-12 09:26:25 +00:00
// Minted tokens will use ALWAYS the same chain where the owner token was deployed.
2024-07-22 13:52:44 +00:00
chainId: root . ownerTokenChainId
chainName: root . chainName
2023-09-12 09:26:25 +00:00
chainIcon: newTokenPage . chainIcon
2023-06-22 21:24:30 +00:00
}
property TokenObject collectible: TokenObject {
2023-07-03 14:44:02 +00:00
type: Constants . TokenType . ERC721
2023-09-12 09:26:25 +00:00
// Minted tokens will use ALWAYS the same chain where the owner token was deployed.
2024-07-22 13:52:44 +00:00
chainId: root . ownerTokenChainId
chainName: root . chainName
2023-09-12 09:26:25 +00:00
chainIcon: newTokenPage . chainIcon
2023-06-22 21:24:30 +00:00
}
2023-06-09 11:50:22 +00:00
property bool isAssetView: false
2023-06-09 16:42:35 +00:00
property int validationMode: StatusInput . ValidationMode . OnlyWhenDirty
property string referenceName: ""
property string referenceSymbol: ""
2023-06-09 11:50:22 +00:00
2023-11-17 16:18:13 +00:00
title: qsTr ( "Mint token" )
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
contentItem: ColumnLayout {
width: root . viewWidth
spacing: Style . current . padding
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
StatusSwitchTabBar {
id: optionsTab
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
Layout.preferredWidth: root . viewWidth
currentIndex: newTokenPage . isAssetView ? 1 : 0
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
StatusSwitchTabButton {
id: collectiblesTab
text: qsTr ( "Collectibles" )
}
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
StatusSwitchTabButton {
id: assetsTab
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
text: qsTr ( "Assets" )
}
2023-05-22 13:00:40 +00:00
}
2023-06-28 19:30:01 +00:00
StackLayout {
Layout.preferredWidth: root . viewWidth
Layout.fillHeight: true
2023-05-22 13:00:40 +00:00
2024-03-25 10:05:31 +00:00
currentIndex: optionsTab . currentIndex
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
CustomEditCommunityTokenView {
id: newCollectibleView
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
isAssetView: false
validationMode: ! newTokenPage . isAssetView
? newTokenPage . validationMode
: StatusInput . ValidationMode . OnlyWhenDirty
2023-09-01 09:27:44 +00:00
token: newTokenPage . collectible
2023-06-28 19:30:01 +00:00
}
2023-06-09 11:50:22 +00:00
2023-06-28 19:30:01 +00:00
CustomEditCommunityTokenView {
id: newAssetView
2023-06-09 11:50:22 +00:00
2023-06-28 19:30:01 +00:00
isAssetView: true
validationMode: newTokenPage . isAssetView
? newTokenPage . validationMode
: StatusInput . ValidationMode . OnlyWhenDirty
2023-09-01 09:27:44 +00:00
token: newTokenPage . asset
2023-06-28 19:30:01 +00:00
}
2023-05-22 13:00:40 +00:00
2023-06-28 19:30:01 +00:00
component CustomEditCommunityTokenView: EditCommunityTokenView {
2023-09-01 09:27:44 +00:00
id: editView
2023-06-28 19:30:01 +00:00
viewWidth: root . viewWidth
accounts: root . accounts
tokensModel: root . tokensModel
2023-11-22 13:50:07 +00:00
referenceAssetsBySymbolModel: root . referenceAssetsBySymbolModel
2023-06-28 19:30:01 +00:00
referenceName: newTokenPage . referenceName
referenceSymbol: newTokenPage . referenceSymbol
2023-09-01 09:27:44 +00:00
feeText: deployFeeSubscriber . feeText
feeErrorText: deployFeeSubscriber . feeErrorText
isFeeLoading: ! deployFeeSubscriber . feesResponse
2023-07-27 20:29:31 +00:00
2024-07-22 13:52:44 +00:00
networkThatIsNotActive: d . networkThatIsNotActive
onEnableNetwork: {
root . enableNetwork ( root . ownerTokenChainId )
d . networkThatIsNotActive = ""
}
2023-06-28 19:30:01 +00:00
onPreviewClicked: {
const properties = {
2023-09-01 09:27:44 +00:00
token: token
2023-06-28 19:30:01 +00:00
}
2023-07-03 14:44:02 +00:00
root . push ( previewTokenViewComponent , properties ,
2023-06-28 19:30:01 +00:00
StackView . Immediate )
2023-06-22 21:24:30 +00:00
}
2023-07-27 20:29:31 +00:00
2023-09-01 09:27:44 +00:00
DeployFeesSubscriber {
id: deployFeeSubscriber
2023-08-30 07:20:28 +00:00
communityId: root . communityId
2023-09-01 09:27:44 +00:00
chainId: editView . token . chainId
tokenType: editView . token . type
isOwnerDeployment: editView . token . isPrivilegedToken
accountAddress: editView . token . accountAddress
enabled: editView . visible
Component.onCompleted: root . registerDeployFeesSubscriber ( deployFeeSubscriber )
2023-07-27 20:29:31 +00:00
}
2023-05-25 10:46:53 +00:00
}
2023-05-22 13:00:40 +00:00
}
2023-03-09 11:12:49 +00:00
}
2023-03-07 11:32:45 +00:00
}
}
Component {
2023-07-03 14:44:02 +00:00
id: previewTokenViewComponent
2023-03-07 11:32:45 +00:00
2023-06-28 19:30:01 +00:00
SettingsPage {
id: tokenPreviewPage
2023-03-07 11:32:45 +00:00
2023-06-28 19:30:01 +00:00
property alias token: preview . token
2023-03-23 13:17:07 +00:00
2023-06-30 14:36:46 +00:00
title: token . name
subtitle: token . symbol
2023-05-15 12:49:26 +00:00
2023-06-28 19:30:01 +00:00
contentItem: CommunityTokenView {
id: preview
2023-03-23 13:17:07 +00:00
2023-07-27 20:29:31 +00:00
viewWidth: root . viewWidth
preview: true
accounts: root . accounts
2023-09-01 09:27:44 +00:00
feeText: feeSubscriber . feeText
feeErrorText: feeSubscriber . feeErrorText
isFeeLoading: ! feeSubscriber . feesResponse
2023-07-27 20:29:31 +00:00
onMintClicked: signMintPopup . open ( )
2023-06-28 19:30:01 +00:00
function signMintTransaction ( ) {
if ( preview . isAssetView )
root . mintAsset ( token )
else
root . mintCollectible ( token )
2023-03-31 12:52:51 +00:00
2023-06-28 19:30:01 +00:00
root . resetNavigation ( )
2023-03-31 12:52:51 +00:00
}
2023-09-01 09:27:44 +00:00
DeployFeesSubscriber {
id: feeSubscriber
2023-08-30 07:20:28 +00:00
communityId: root . communityId
2023-09-01 09:27:44 +00:00
chainId: preview . token . chainId
tokenType: preview . token . type
isOwnerDeployment: preview . token . isPrivilegedToken
accountAddress: preview . token . accountAddress
enabled: preview . visible || signMintPopup . visible
Component.onCompleted: root . registerDeployFeesSubscriber ( feeSubscriber )
}
2023-09-21 16:49:57 +00:00
SignTransactionsPopup {
2023-06-28 19:30:01 +00:00
id: signMintPopup
2023-05-30 15:18:45 +00:00
2023-07-03 14:44:02 +00:00
title: qsTr ( "Sign transaction - Mint %1 token" ) . arg (
2023-07-27 20:29:31 +00:00
preview . token . name )
2023-09-01 09:27:44 +00:00
totalFeeText: preview . isFeeLoading ? "" : preview . feeText
2023-07-27 20:29:31 +00:00
accountName: preview . token . accountName
model: QtObject {
readonly property string title: preview . feeLabel
readonly property string feeText: signMintPopup . totalFeeText
2023-09-01 09:27:44 +00:00
readonly property bool error: preview . feeErrorText !== ""
2023-05-18 15:01:48 +00:00
}
2023-07-27 20:29:31 +00:00
2023-06-28 19:30:01 +00:00
onSignTransactionClicked: preview . signMintTransaction ( )
2023-06-05 13:49:36 +00:00
}
}
2023-03-07 11:32:45 +00:00
}
}
2023-07-03 14:44:02 +00:00
component TokenViewPage: SettingsPage {
id: tokenViewPage
2023-03-28 13:55:34 +00:00
2023-09-01 09:27:44 +00:00
property TokenObject token: TokenObject { }
2023-07-18 17:34:57 +00:00
readonly property bool deploymentFailed: view . deployState === Constants . ContractTransactionStatus . Failed
2023-03-28 13:55:34 +00:00
2024-02-28 18:02:44 +00:00
property var membersModel
2023-09-01 09:27:44 +00:00
property var tokenOwnersModel
property string airdropKey
2023-07-18 17:34:57 +00:00
// Owner and TMaster related props
2023-08-04 16:41:21 +00:00
readonly property bool isPrivilegedTokenItem: isOwnerTokenItem || isTMasterTokenItem
readonly property bool isOwnerTokenItem: token . privilegesLevel === Constants . TokenPrivilegesLevel . Owner
readonly property bool isTMasterTokenItem: token . privilegesLevel === Constants . TokenPrivilegesLevel . TMaster
2023-07-18 17:34:57 +00:00
2023-07-03 14:44:02 +00:00
title: view . name
subtitle: view . symbol
2023-06-22 21:24:30 +00:00
2023-07-03 14:44:02 +00:00
buttons: [
StatusButton {
text: qsTr ( "Delete" )
type: StatusBaseButton . Type . Danger
2023-03-28 13:55:34 +00:00
2023-07-18 17:34:57 +00:00
visible: ( ! tokenViewPage . isPrivilegedTokenItem ) && ! root . isAdminOnly && tokenViewPage . deploymentFailed
2023-05-30 15:18:45 +00:00
2023-07-03 14:44:02 +00:00
onClicked: deleteTokenAlertPopup . open ( )
} ,
StatusButton {
2023-07-18 17:34:57 +00:00
function retryAssetOrCollectible ( ) {
2023-07-03 14:44:02 +00:00
// https://bugreports.qt.io/browse/QTBUG-91917
var isAssetView = tokenViewPage . token . type === Constants . TokenType . ERC20
2023-05-18 15:01:48 +00:00
2023-07-18 17:34:57 +00:00
// Copy TokenObject
var tokenObject = tokenObjectComponent . createObject ( null , view . token )
2023-05-18 15:01:48 +00:00
2023-07-03 14:44:02 +00:00
// Then move on to the new token view, but token pre-filled:
var properties = {
isAssetView ,
referenceName: tokenObject . name ,
referenceSymbol: tokenObject . symbol ,
validationMode: StatusInput . ValidationMode . Always ,
[ isAssetView ? "asset" : "collectible" ] : tokenObject
2023-06-28 19:30:01 +00:00
}
2023-06-09 11:50:22 +00:00
2023-07-03 14:44:02 +00:00
var tokenView = root . push ( newTokenViewComponent , properties ,
2023-07-18 17:34:57 +00:00
StackView . Immediate )
2023-06-28 19:30:01 +00:00
2023-07-18 17:34:57 +00:00
// Cleanup dynamically created TokenObject
2023-07-03 14:44:02 +00:00
tokenView . Component . destruction . connect ( ( ) = > tokenObject . destroy ( ) )
2023-03-28 13:55:34 +00:00
}
2023-07-18 17:34:57 +00:00
text: qsTr ( "Retry mint" )
visible: ( tokenViewPage . isPrivilegedTokenItem && root . isOwner && tokenViewPage . deploymentFailed ) ||
( ! tokenViewPage . isPrivilegedTokenItem && ! root . isAdminOnly && tokenViewPage . deploymentFailed )
onClicked: {
2023-07-25 14:11:10 +00:00
if ( tokenViewPage . isPrivilegedTokenItem ) {
2023-08-01 10:31:50 +00:00
d . retryPrivilegedToken ( view . token . key , view . token . chainId , view . token . accountName , view . token . accountAddress )
2023-07-25 14:11:10 +00:00
} else {
2023-07-18 17:34:57 +00:00
retryAssetOrCollectible ( )
2023-07-25 14:11:10 +00:00
}
2023-07-18 17:34:57 +00:00
}
2024-05-21 08:53:33 +00:00
} ,
StatusButton {
text: qsTr ( "Refresh" )
visible: localAppSettings . refreshTokenEnabled && ( tokenViewPage . token . deployState === Constants . ContractTransactionStatus . InProgress )
onClicked: root . refreshToken ( tokenViewPage . token . key )
tooltip.text: qsTr ( "Restart token's transaction listening if the token got stuck in minting state" )
2023-03-28 13:55:34 +00:00
}
2023-07-03 14:44:02 +00:00
]
2023-04-17 12:11:31 +00:00
2023-07-03 14:44:02 +00:00
contentItem: CommunityTokenView {
id: view
2023-06-05 13:49:36 +00:00
2023-09-01 09:27:44 +00:00
property string airdropKey: tokenViewPage . airdropKey // TO REMOVE: Temporal property until airdrop backend is not ready to use token key instead of symbol
2023-06-05 13:49:36 +00:00
2023-07-03 14:44:02 +00:00
viewWidth: root . viewWidth
2023-06-28 19:30:01 +00:00
2023-09-01 09:27:44 +00:00
token: tokenViewPage . token
2024-02-28 18:02:44 +00:00
membersModel: tokenViewPage . membersModel
2023-09-01 09:27:44 +00:00
tokenOwnersModel: tokenViewPage . tokenOwnersModel
2024-02-28 18:02:44 +00:00
isOwnerTokenItem: tokenViewPage . isOwnerTokenItem
2023-06-28 19:30:01 +00:00
2024-06-03 08:31:26 +00:00
onStartTokenHoldersManagement: root . startTokenHoldersManagement ( chainId , address )
onStopTokenHoldersManagement: root . stopTokenHoldersManagement ( )
2023-07-03 14:44:02 +00:00
onGeneralAirdropRequested: {
2023-08-10 12:23:59 +00:00
root . airdropToken ( view . airdropKey ,
"1" + "0" . repeat ( view . token . multiplierIndex ) ,
view . token . type , [ ] ) // tokenKey instead when backend airdrop ready to use key instead of symbol
2023-07-03 14:44:02 +00:00
}
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
onAirdropRequested: {
2023-08-10 12:23:59 +00:00
root . airdropToken ( view . airdropKey ,
"1" + "0" . repeat ( view . token . multiplierIndex ) ,
view . token . type , [ address ] ) // tokenKey instead when backend airdrop ready to use key instead of symbol
2023-07-03 14:44:02 +00:00
}
2023-06-28 19:30:01 +00:00
2023-09-21 13:02:18 +00:00
onViewProfileRequested: {
Global . openProfilePopup ( contactId )
}
onViewMessagesRequested: {
// TODO: https://github.com/status-im/status-desktop/issues/11860
console . warn ( "View Messages is not implemented yet" )
}
2023-07-03 14:44:02 +00:00
onRemoteDestructRequested: {
2023-08-02 15:32:36 +00:00
if ( token . isPrivilegedToken ) {
tokenMasterActionPopup . openPopup (
2023-09-21 13:02:18 +00:00
TokenMasterActionPopup . ActionType . RemotelyDestruct ,
name , address , "" )
2023-08-02 15:32:36 +00:00
} else {
remotelyDestructPopup . open ( )
// TODO: set the address selected in the popup's list
}
}
onBanRequested: {
2023-08-31 22:26:24 +00:00
if ( token . isPrivilegedToken )
tokenMasterActionPopup . openPopup (
2023-09-21 13:02:18 +00:00
TokenMasterActionPopup . ActionType . Ban , name ,
address , contactId )
2023-08-31 22:26:24 +00:00
else
kickBanPopup . openPopup ( KickBanPopup . Mode . Ban , name , contactId )
2023-08-02 15:32:36 +00:00
}
onKickRequested: {
2023-08-31 22:26:24 +00:00
if ( token . isPrivilegedToken )
tokenMasterActionPopup . openPopup (
2023-09-21 13:02:18 +00:00
TokenMasterActionPopup . ActionType . Kick , name ,
address , contactId )
2023-08-31 22:26:24 +00:00
else
kickBanPopup . openPopup ( KickBanPopup . Mode . Kick , name , contactId )
2023-08-02 15:32:36 +00:00
}
TokenMasterActionPopup {
id: tokenMasterActionPopup
2023-09-01 09:27:44 +00:00
property string address: ""
2023-09-21 13:02:18 +00:00
property string contactId: ""
2023-09-01 09:27:44 +00:00
2023-08-02 15:32:36 +00:00
communityName: root . communityName
networkName: view . token . chainName
2023-08-09 12:31:58 +00:00
accountsModel: root . accounts
2023-09-01 09:27:44 +00:00
feeText: selfDestructFeesSubscriber . feeText
feeErrorText: selfDestructFeesSubscriber . feeErrorText
isFeeLoading: ! selfDestructFeesSubscriber . feesResponse
2023-08-02 15:32:36 +00:00
2023-09-21 13:02:18 +00:00
function openPopup ( type , userName , address , contactId ) {
2023-08-02 15:32:36 +00:00
tokenMasterActionPopup . actionType = type
2023-09-21 13:30:18 +00:00
tokenMasterActionPopup . userName = userName ||
SQUtils . Utils . elideAndFormatWalletAddress ( address )
2023-09-01 09:27:44 +00:00
tokenMasterActionPopup . address = address
2023-09-21 13:02:18 +00:00
tokenMasterActionPopup . contactId = contactId
2023-08-02 15:32:36 +00:00
open ( )
}
2023-09-01 09:27:44 +00:00
2023-09-21 13:02:18 +00:00
onRemotelyDestructClicked: signPopup . open ( )
onKickClicked: signPopup . open ( )
onBanClicked: signPopup . open ( )
2023-09-01 09:27:44 +00:00
SelfDestructFeesSubscriber {
id: selfDestructFeesSubscriber
2023-09-21 13:02:18 +00:00
2023-09-01 09:27:44 +00:00
walletsAndAmounts: [ {
walletAddress: tokenMasterActionPopup . address ,
2023-09-21 13:02:18 +00:00
amount: 1
2023-09-01 09:27:44 +00:00
} ]
accountAddress: tokenMasterActionPopup . selectedAccount
tokenKey: view . token . key
enabled: tokenMasterActionPopup . opened
2023-09-21 13:02:18 +00:00
Component.onCompleted: root . registerSelfDestructFeesSubscriber (
selfDestructFeesSubscriber )
}
SignTransactionsPopup {
id: signPopup
title: qsTr ( "Sign transaction - Remotely-destruct TokenMaster token" )
totalFeeText: tokenMasterActionPopup . feeText
errorText: tokenMasterActionPopup . feeErrorText
accountName: tokenMasterActionPopup . selectedAccountName
model: QtObject {
readonly property string title: tokenMasterActionPopup . feeLabel
readonly property string feeText: tokenMasterActionPopup . feeText
readonly property bool error: tokenMasterActionPopup . feeErrorText !== ""
}
onSignTransactionClicked: {
// https://bugreports.qt.io/browse/QTBUG-91917
var contactId = tokenMasterActionPopup . contactId
var tokenKey = tokenViewPage . token . key
var accountAddress = tokenMasterActionPopup . selectedAccount
switch ( tokenMasterActionPopup . actionType ) {
case TokenMasterActionPopup.ActionType.RemotelyDestruct:
var tokenToDestruct = {
walletAddress: tokenMasterActionPopup . address ,
amount: 1
}
root . remotelyDestructCollectibles (
[ tokenToDestruct ] ,
tokenKey , accountAddress )
break
case TokenMasterActionPopup.ActionType.Kick:
root . remotelyDestructAndKick ( contactId , tokenKey ,
accountAddress )
break
case TokenMasterActionPopup.ActionType.Ban:
root . remotelyDestructAndBan ( contactId , tokenKey ,
accountAddress ,
tokenMasterActionPopup . deleteMessages )
break
}
tokenMasterActionPopup . close ( )
}
2023-09-01 09:27:44 +00:00
}
2023-06-05 13:49:36 +00:00
}
2023-08-31 22:26:24 +00:00
KickBanPopup {
id: kickBanPopup
property string contactId
communityName: root . communityName
onAccepted: {
if ( mode === KickBanPopup . Mode . Kick )
root . kickUserRequested ( contactId )
else
root . banUserRequested ( contactId )
}
function openPopup ( mode , userName , contactId ) {
kickBanPopup . mode = mode
kickBanPopup . username = userName
kickBanPopup . contactId = contactId
open ( )
}
}
2023-07-03 14:44:02 +00:00
}
2023-06-05 13:49:36 +00:00
2023-07-03 14:44:02 +00:00
footer: MintTokensFooterPanel {
id: footer
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
readonly property TokenObject token: view . token
2023-07-31 13:42:38 +00:00
readonly property bool isAssetView: view . isAssetView
2023-06-28 19:30:01 +00:00
2023-07-18 17:34:57 +00:00
readonly property bool deployStateCompleted: token . deployState === Constants . ContractTransactionStatus . Completed
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
function closePopups ( ) {
remotelyDestructPopup . close ( )
alertPopup . close ( )
signTransactionPopup . close ( )
burnTokensPopup . close ( )
}
2023-06-28 19:30:01 +00:00
2023-09-14 10:02:51 +00:00
communityName: root . communityName
2023-07-18 17:34:57 +00:00
visible: {
2024-01-15 11:31:07 +00:00
if ( tokenViewPage . isOwnerTokenItem || tokenViewPage . isTMasterTokenItem )
2023-07-18 17:34:57 +00:00
// Only footer if owner profile
return root . isOwner
// Always present
return true
}
2023-07-03 14:44:02 +00:00
airdropEnabled: deployStateCompleted &&
( token . infiniteSupply ||
2023-07-31 13:42:38 +00:00
token . remainingTokens > 0 )
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
remotelyDestructEnabled: deployStateCompleted &&
! ! view . tokenOwnersModel &&
view . tokenOwnersModel . count > 0
2023-06-28 19:30:01 +00:00
2023-09-14 10:02:51 +00:00
burnEnabled: deployStateCompleted
sendOwnershipEnabled: deployStateCompleted
2023-06-28 19:30:01 +00:00
2024-01-15 11:31:07 +00:00
sendOwnershipVisible: root . isOwner && tokenViewPage . isOwnerTokenItem
2023-09-14 10:02:51 +00:00
airdropVisible: ! tokenViewPage . isOwnerTokenItem
remotelyDestructVisible: ! tokenViewPage . isOwnerTokenItem && token . remotelyDestruct
burnVisible: ! tokenViewPage . isOwnerTokenItem && ! token . infiniteSupply
2023-06-28 19:30:01 +00:00
2023-08-10 12:23:59 +00:00
onAirdropClicked: root . airdropToken (
view . airdropKey ,
"1" + "0" . repeat ( view . token . multiplierIndex ) ,
view . token . type , [ ] )
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
onRemotelyDestructClicked: remotelyDestructPopup . open ( )
onBurnClicked: burnTokensPopup . open ( )
2023-11-24 08:48:50 +00:00
onSendOwnershipClicked: Global . openTransferOwnershipPopup ( root . communityId ,
root . communityName ,
2023-09-14 10:02:51 +00:00
root . communityLogo ,
tokenViewPage . token ,
root . sendModalPopup )
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
// helper properties to pass data through popups
2023-08-17 13:58:04 +00:00
property var walletsAndAmounts
2023-08-10 12:23:59 +00:00
property string burnAmount
2023-08-07 13:31:07 +00:00
property string accountAddress
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
RemotelyDestructPopup {
id: remotelyDestructPopup
2023-06-28 19:30:01 +00:00
2023-09-01 09:27:44 +00:00
property alias feeSubscriber: remotelyDestructFeeSubscriber
2023-07-03 14:44:02 +00:00
collectibleName: view . token . name
model: view . tokenOwnersModel || null
2023-08-10 09:39:52 +00:00
accounts: root . accounts
2023-09-01 09:27:44 +00:00
chainName: view . token . chainName
2023-06-28 19:30:01 +00:00
2023-09-01 09:27:44 +00:00
feeText: remotelyDestructFeeSubscriber . feeText
feeErrorText: remotelyDestructFeeSubscriber . feeErrorText
2024-07-22 13:52:44 +00:00
isFeeLoading: ! remotelyDestructFeeSubscriber . feesResponse
networkThatIsNotActive: d . networkThatIsNotActive
onEnableNetwork: {
root . enableNetwork ( root . ownerTokenChainId )
d . networkThatIsNotActive = ""
}
2023-09-01 09:27:44 +00:00
2023-07-03 14:44:02 +00:00
onRemotelyDestructClicked: {
2023-07-21 12:10:37 +00:00
remotelyDestructPopup . close ( )
2023-08-10 09:39:52 +00:00
footer . accountAddress = accountAddress
2023-08-17 13:58:04 +00:00
footer . walletsAndAmounts = walletsAndAmounts
2023-07-03 14:44:02 +00:00
alertPopup . open ( )
2023-06-28 19:30:01 +00:00
}
2023-09-01 09:27:44 +00:00
SelfDestructFeesSubscriber {
id: remotelyDestructFeeSubscriber
2023-09-21 16:13:13 +00:00
2023-09-01 09:27:44 +00:00
walletsAndAmounts: remotelyDestructPopup . selectedWalletsAndAmounts
accountAddress: remotelyDestructPopup . selectedAccount
tokenKey: view . token . key
enabled: remotelyDestructPopup . tokenCount > 0 && accountAddress !== "" && ( remotelyDestructPopup . opened || signTransactionPopup . opened )
Component.onCompleted: root . registerSelfDestructFeesSubscriber ( remotelyDestructFeeSubscriber )
}
2023-07-03 14:44:02 +00:00
}
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
BurnTokensPopup {
id: burnTokensPopup
2023-09-21 16:13:13 +00:00
2023-09-01 09:27:44 +00:00
property alias feeSubscriber: burnTokensFeeSubscriber
2023-09-21 16:13:13 +00:00
2023-07-03 14:44:02 +00:00
communityName: root . communityName
tokenName: footer . token . name
remainingTokens: footer . token . remainingTokens
2023-08-10 12:23:59 +00:00
multiplierIndex: footer . token . multiplierIndex
2023-07-03 14:44:02 +00:00
tokenSource: footer . token . artworkSource
2023-08-07 13:31:07 +00:00
chainName: footer . token . chainName
2023-09-21 16:13:13 +00:00
2024-07-22 13:52:44 +00:00
networkThatIsNotActive: d . networkThatIsNotActive
onEnableNetwork: {
root . enableNetwork ( root . ownerTokenChainId )
d . networkThatIsNotActive = ""
}
2023-09-01 09:27:44 +00:00
onAmountToBurnChanged: burnTokensFeeSubscriber . updateAmount ( )
2023-08-07 13:31:07 +00:00
2023-09-01 09:27:44 +00:00
feeText: burnTokensFeeSubscriber . feeText
feeErrorText: burnTokensFeeSubscriber . feeErrorText
isFeeLoading: burnTokensFeeSubscriber . feeText === "" && burnTokensFeeSubscriber . feeErrorText === ""
2023-08-07 13:31:07 +00:00
accounts: root . accounts
2023-07-03 14:44:02 +00:00
onBurnClicked: {
2023-07-21 12:10:37 +00:00
burnTokensPopup . close ( )
2023-07-03 14:44:02 +00:00
footer . burnAmount = burnAmount
2023-08-07 13:31:07 +00:00
footer . accountAddress = accountAddress
2023-07-03 14:44:02 +00:00
signTransactionPopup . isRemotelyDestructTransaction = false
signTransactionPopup . open ( )
2023-04-17 12:11:31 +00:00
}
2023-09-01 09:27:44 +00:00
BurnTokenFeesSubscriber {
id: burnTokensFeeSubscriber
2023-09-21 16:13:13 +00:00
2023-09-01 09:27:44 +00:00
readonly property var updateAmount: Backpressure . debounce ( burnTokensFeeSubscriber , 500 , ( ) = > {
burnTokensFeeSubscriber . amount = burnTokensPopup . amountToBurn
} )
amount: ""
tokenKey: tokenViewPage . token . key
accountAddress: burnTokensPopup . selectedAccountAddress
enabled: burnTokensPopup . visible || signTransactionPopup . visible
Component.onCompleted: root . registerBurnTokenFeesSubscriber ( burnTokensFeeSubscriber )
}
2023-04-17 12:11:31 +00:00
}
2023-09-21 16:13:13 +00:00
AlertPopup {
id: alertPopup
title: qsTr ( "Remotely destruct %n token(s)" , "" ,
remotelyDestructPopup . tokenCount )
acceptBtnText: qsTr ( "Remotely destruct" )
alertText: qsTr ( "Continuing will destroy tokens held by members and revoke any permissions they are given. To undo you will have to issue them new tokens." )
onAcceptClicked: {
signTransactionPopup . isRemotelyDestructTransaction = true
signTransactionPopup . open ( )
}
}
2023-09-21 16:49:57 +00:00
SignTransactionsPopup {
2023-09-21 16:13:13 +00:00
id: signTransactionPopup
property bool isRemotelyDestructTransaction
readonly property string tokenName: footer . token . name
title: isRemotelyDestructTransaction
? qsTr ( "Sign transaction - Remotely destruct %1 token" ) . arg ( tokenName )
: qsTr ( "Sign transaction - Burn %1 tokens" ) . arg ( tokenName )
accountName: footer . token . accountName
totalFeeText: isRemotelyDestructTransaction
? remotelyDestructPopup . feeText
: burnTokensPopup . feeText
errorText: isRemotelyDestructTransaction
? remotelyDestructPopup . feeErrorText
: burnTokensPopup . feeErrorText
model: QtObject {
readonly property string title:
signTransactionPopup . isRemotelyDestructTransaction
? qsTr ( "Remotely destruct %Ln %1 token(s) on %2" , "" ,
remotelyDestructPopup . tokenCount )
. arg ( remotelyDestructPopup . collectibleName )
. arg ( remotelyDestructPopup . chainName )
: burnTokensPopup . feeLabel
readonly property string feeText: signTransactionPopup . totalFeeText
readonly property bool error: signTransactionPopup . errorText !== ""
}
onSignTransactionClicked: {
if ( signTransactionPopup . isRemotelyDestructTransaction )
root . remotelyDestructCollectibles ( footer . walletsAndAmounts ,
tokenKey , footer . accountAddress )
else
root . burnToken ( tokenKey , footer . burnAmount , footer . accountAddress )
footer . closePopups ( )
}
}
2023-07-03 14:44:02 +00:00
}
2023-05-30 15:18:45 +00:00
2023-07-03 14:44:02 +00:00
AlertPopup {
id: deleteTokenAlertPopup
2023-05-30 15:18:45 +00:00
2023-09-01 09:27:44 +00:00
readonly property string tokenName: view . token . name
2023-05-30 15:18:45 +00:00
2023-07-03 14:44:02 +00:00
width: 521
title: qsTr ( "Delete %1" ) . arg ( tokenName )
acceptBtnText: qsTr ( "Delete %1 token" ) . arg ( tokenName )
alertText: qsTr ( "%1 is not yet minted, are you sure you want to delete it? All data associated with this token including its icon and description will be permanently deleted." ) . arg ( tokenName )
2023-06-28 19:30:01 +00:00
2023-07-03 14:44:02 +00:00
onAcceptClicked: {
root . deleteToken ( tokenViewPage . token . key )
root . navigateBack ( )
}
}
}
Component {
id: tokenViewComponent
Item {
id: tokenViewPageWrapper
property string tokenKey
Repeater {
model: SortFilterProxyModel {
sourceModel: root . tokensModel
filters: ValueFilter {
roleName: "contractUniqueKey"
value: tokenViewPageWrapper . tokenKey
}
}
delegate: TokenViewPage {
2023-09-01 09:27:44 +00:00
required property var model
2023-07-03 14:44:02 +00:00
implicitWidth: 0
anchors.fill: parent
tokenOwnersModel: model . tokenOwnersModel
2024-02-28 18:02:44 +00:00
membersModel: root . membersModel
2023-07-03 14:44:02 +00:00
airdropKey: model . symbol // TO BE REMOVED: When airdrop backend is ready to use token key instead of symbol
2023-08-04 16:41:21 +00:00
token.privilegesLevel: model . privilegesLevel
2023-07-18 17:34:57 +00:00
token.color: root . communityColor
2023-07-03 14:44:02 +00:00
token.accountName: model . accountName
token.artworkSource: model . image
token.chainIcon: model . chainIcon
token.chainId: model . chainId
token.chainName: model . chainName
token.decimals: model . decimals
token.deployState: model . deployState
token.description: model . description
token.infiniteSupply: model . infiniteSupply
token.key: model . contractUniqueKey
token.name: model . name
token.remainingTokens: model . remainingSupply
token.remotelyDestruct: model . remoteSelfDestruct
token.supply: model . supply
token.symbol: model . symbol
token.transferable: model . transferable
token.type: model . tokenType
2023-07-04 11:05:43 +00:00
token.burnState: model . burnState
2023-07-14 13:02:22 +00:00
token.remotelyDestructState: model . remotelyDestructState
2023-07-11 13:23:00 +00:00
token.accountAddress: model . accountAddress
2023-08-10 12:23:59 +00:00
token.multiplierIndex: model . multiplierIndex
2023-11-24 08:48:50 +00:00
token.tokenAddress: model . tokenAddress
2023-07-03 14:44:02 +00:00
}
onCountChanged: {
if ( count === 0 )
root . navigateBack ( )
2023-06-28 19:30:01 +00:00
}
}
2023-05-30 15:18:45 +00:00
}
}
2023-02-17 11:57:17 +00:00
}