mirror of
https://github.com/status-im/status-desktop.git
synced 2025-02-21 11:08:55 +00:00
872 lines
40 KiB
QML
872 lines
40 KiB
QML
import QtQuick 2.15
|
|
import QtQuick.Controls 2.15
|
|
|
|
import SortFilterProxyModel 0.2
|
|
|
|
import StatusQ 0.1
|
|
import StatusQ.Core 0.1
|
|
import StatusQ.Core.Theme 0.1
|
|
import StatusQ.Core.Utils 0.1 as SQUtils
|
|
|
|
import AppLayouts.Wallet.stores 1.0 as WalletStores
|
|
import AppLayouts.Wallet.popups.simpleSend 1.0
|
|
import AppLayouts.Wallet.adaptors 1.0
|
|
import AppLayouts.Wallet 1.0
|
|
|
|
import shared.popups.send 1.0
|
|
import shared.stores.send 1.0
|
|
|
|
import utils 1.0
|
|
|
|
QtObject {
|
|
id: root
|
|
|
|
required property var popupParent
|
|
required property int loginType
|
|
required property TransactionStore transactionStore
|
|
required property WalletStores.CollectiblesStore walletCollectiblesStore
|
|
required property WalletStores.TransactionStoreNew transactionStoreNew
|
|
|
|
/** for ens flows **/
|
|
required property string myPublicKey
|
|
required property string ensRegisteredAddress
|
|
/** TODO: This should probably be a property and not
|
|
a function. Needs changes on backend side **/
|
|
property var getStatusTokenKey: function() {}
|
|
|
|
/** for sticker flows **/
|
|
required property string stickersMarketAddress
|
|
required property string stickersNetworkId
|
|
|
|
/** Feature flag for single network send until its feature complete **/
|
|
required property bool simpleSendEnabled
|
|
|
|
/** For simple send modal flows, decoupling from transaction store **/
|
|
|
|
/** Expected model structure:
|
|
- name: name of account
|
|
- address: wallet address
|
|
- color: color of the account
|
|
- emoji: emoji selected for the account
|
|
- currencyBalance: total currency balance in CurrencyAmount
|
|
- accountBalance: balance of selected token + selected chain
|
|
**/
|
|
required property var walletAccountsModel
|
|
/** Expected model structure:
|
|
- tokensKey: unique string ID of the token (asset); e.g. "ETH" or contract address
|
|
- name: user visible token name (e.g. "Ethereum")
|
|
- symbol: user visible token symbol (e.g. "ETH")
|
|
- decimals: number of decimal places
|
|
- communityId: optional; ID of the community this token belongs to, if any
|
|
- marketDetails: object containing props like `currencyPrice` for the computed values below
|
|
- balances: submodel[ chainId:int, account:string, balance:BigIntString, iconUrl:string ]
|
|
**/
|
|
required property var groupedAccountAssetsModel
|
|
/** Expected token by symbol model structure:
|
|
- key: id for the token,
|
|
- name: name of the token,
|
|
- symbol: symbol of the token,
|
|
- decimals: decimals for the token
|
|
*/
|
|
required property var plainTokensBySymbolModel
|
|
/** Expected model structure:
|
|
- symbol [string] - unique identifier of a collectible
|
|
- collectionUid [string] - unique identifier of a collection
|
|
- contractAddress [string] - collectible's contract address
|
|
- name [string] - collectible's name e.g. "Magicat"
|
|
- collectionName [string] - collection name e.g. "Crypto Kitties"
|
|
- mediaUrl [url] - collectible's media url
|
|
- imageUrl [url] - collectible's image url
|
|
- communityId [string] - unique identifier of a community for community collectible or empty
|
|
- ownership [model] - submodel of balances per chain/account
|
|
- balance [int] - balance (always 1 for ERC-721)
|
|
- accountAddress [string] - unique identifier of an account
|
|
**/
|
|
required property var collectiblesBySymbolModel
|
|
/**
|
|
Expected model structure:
|
|
- chainId: network chain id
|
|
- chainName: name of network
|
|
- iconUrl: network icon url
|
|
networks on both mainnet & testnet
|
|
**/
|
|
required property var flatNetworksModel
|
|
/**
|
|
Expected model structure:
|
|
- chainId: network chain id
|
|
- chainName: name of network
|
|
- iconUrl: network icon url
|
|
networks on either mainnet OR testnet
|
|
**/
|
|
required property var filteredFlatNetworksModel
|
|
/** true if testnet mode is on **/
|
|
required property bool areTestNetworksEnabled
|
|
/** whether community tokens are shown in send modal
|
|
based on a global setting **/
|
|
required property bool showCommunityAssetsInSend
|
|
|
|
required property var savedAddressesModel
|
|
required property var recentRecipientsModel
|
|
|
|
/** required function to resolve an ens name
|
|
- ensName [string] - ensName to be resolved
|
|
- uuid [string] - unique identifier for the request
|
|
**/
|
|
required property var fnResolveENS
|
|
/** required signal to receive resolved ens name address **/
|
|
signal ensNameResolved(string resolvedPubKey, string resolvedAddress, string uuid)
|
|
|
|
/** curently selected fiat currency symbol **/
|
|
required property string currentCurrency
|
|
/** required function to format currency amount to locale string
|
|
- amount [real] - amount to be formatted as a number
|
|
- symbol [string] - fiat/crypto currency symbol
|
|
**/
|
|
required property var fnFormatCurrencyAmount
|
|
/** required function to format to currency amount from big int
|
|
- amount [real] - amount to be formatted as a number
|
|
- symbol [string] - fiat/crypto currency symbol
|
|
- decimals [int] - decimals of the crypto token
|
|
**/
|
|
required property var fnFormatCurrencyAmountFromBigInt
|
|
|
|
/** required property holds the detailed collectible **/
|
|
required property var detailedCollectible
|
|
/** required property holds if collectible details is loading **/
|
|
required property bool isDetailedCollectibleLoading
|
|
/** required function to fetch detailed collectible
|
|
chainId, contractAddress, tokenId
|
|
- chainId [int] - chainId of collectible
|
|
- contractAddress [string] - contract address of collectible
|
|
- tokenId [string] - token id of collectible
|
|
**/
|
|
required property var fnGetDetailedCollectible
|
|
/** required function to reset the detailed collectible **/
|
|
required property var fnResetDetailedCollectible
|
|
|
|
/** required function to get openSea explorer url
|
|
- networkShortName [string] - collectible networks short name
|
|
**/
|
|
required property var fnGetOpenSeaUrl
|
|
|
|
/** property to store the params to be updated in the send modal until it is launched **/
|
|
property var simpleSendParams
|
|
|
|
/** signal to request launch of buy crypto modal **/
|
|
signal launchBuyFlowRequested(string accountAddress, int chainId, string tokenKey)
|
|
|
|
function openSend(params = {}, forceLaunchOldSend = false) {
|
|
// TODO remove once simple send is feature complete
|
|
if(root.simpleSendEnabled && !forceLaunchOldSend) {
|
|
root.simpleSendParams = params
|
|
let sendModalInst = simpleSendModalComponent.createObject(popupParent)
|
|
sendModalInst.open()
|
|
} else {
|
|
let sendModalInst = sendModalComponent.createObject(popupParent, params)
|
|
sendModalInst.open()
|
|
}
|
|
}
|
|
|
|
function connectUsername(ensName) {
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
sendType: Constants.SendType.ENSSetPubKey,
|
|
selectedTokenKey: Constants.ethToken ,
|
|
selectedRawAmount: "0",
|
|
selectedRecipientAddress: root.ensRegisteredAddress,
|
|
interactive: false,
|
|
publicKey: root.myPublicKey,
|
|
ensName: ensName
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedSendType: Constants.SendType.ENSSetPubKey,
|
|
preSelectedHoldingID: Constants.ethToken ,
|
|
preSelectedHoldingType: Constants.TokenType.Native,
|
|
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0),
|
|
preSelectedRecipient: root.ensRegisteredAddress,
|
|
interactive: false,
|
|
publicKey: root.myPublicKey,
|
|
ensName: ensName
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
function registerUsername(ensName) {
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
sendType: Constants.SendType.ENSRegister,
|
|
selectedTokenKey: root.getStatusTokenKey(),
|
|
// TODO this should come from backend.To be fixed when ENS is reworked
|
|
selectedRawAmount: SQUtils.AmountsArithmetic.fromNumber(10, 18).toString(),
|
|
selectedRecipientAddress: root.ensRegisteredAddress,
|
|
interactive: false,
|
|
publicKey: root.myPublicKey,
|
|
ensName: ensName
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedSendType: Constants.SendType.ENSRegister,
|
|
preSelectedHoldingID: root.getStatusTokenKey(),
|
|
preSelectedHoldingType: Constants.TokenType.ERC20,
|
|
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(10),
|
|
preSelectedRecipient: root.ensRegisteredAddress,
|
|
interactive: false,
|
|
publicKey: root.myPublicKey,
|
|
ensName: ensName
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
function releaseUsername(ensName, senderAddress, chainId) {
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
sendType: Constants.SendType.ENSRelease,
|
|
selectedAccountAddress: senderAddress,
|
|
selectedTokenKey: Constants.ethToken ,
|
|
selectedRawAmount: "0",
|
|
selectedChainId: chainId,
|
|
selectedRecipientAddress: root.ensRegisteredAddress,
|
|
interactive: false,
|
|
publicKey: root.myPublicKey,
|
|
ensName: ensName
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedSendType: Constants.SendType.ENSRelease,
|
|
preSelectedAccountAddress: senderAddress,
|
|
preSelectedHoldingID: Constants.ethToken ,
|
|
preSelectedHoldingType: Constants.TokenType.Native,
|
|
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(0),
|
|
preSelectedChainId: chainId,
|
|
preSelectedRecipient: root.ensRegisteredAddress,
|
|
interactive: false,
|
|
publicKey: root.myPublicKey,
|
|
ensName: ensName
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
function buyStickerPack(packId, price) {
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
sendType: Constants.SendType.StickersBuy,
|
|
selectedTokenKey: root.getStatusTokenKey(),
|
|
selectedRawAmount: SQUtils.AmountsArithmetic.fromNumber(price, 18).toString(),
|
|
selectedChainId: root.stickersNetworkId,
|
|
selectedRecipientAddress: root.stickersMarketAddress,
|
|
interactive: false,
|
|
stickersPackId: packId
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedSendType: Constants.SendType.StickersBuy,
|
|
preSelectedHoldingID: root.getStatusTokenKey(),
|
|
preSelectedHoldingType: Constants.TokenType.ERC20,
|
|
preDefinedAmountToSend: LocaleUtils.numberToLocaleString(price),
|
|
preSelectedChainId: root.stickersNetworkId,
|
|
preSelectedRecipient: root.stickersMarketAddress,
|
|
interactive: false,
|
|
stickersPackId: packId
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
function transferOwnership(tokenId, senderAddress) {
|
|
let selectedChainId =
|
|
SQUtils.ModelUtils.getByKey(root.collectiblesBySymbolModel, "symbol", tokenId, "chainId")
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
sendType: Constants.SendType.ERC721Transfer,
|
|
selectedAccountAddress: senderAddress,
|
|
selectedTokenKey: tokenId,
|
|
selectedRawAmount: "1",
|
|
selectedChainId: selectedChainId,
|
|
transferOwnership: true
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedSendType: Constants.SendType.ERC721Transfer,
|
|
preSelectedAccountAddress: senderAddress,
|
|
preSelectedHoldingID: tokenId,
|
|
preSelectedHoldingType: Constants.TokenType.ERC721,
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
function sendToRecipient(recipientAddress) {
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
selectedRecipientAddress: recipientAddress,
|
|
openReason: "send to recipient"
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedRecipient: recipientAddress
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
function bridgeToken(tokenId, tokenType) {
|
|
let params = {
|
|
preSelectedSendType: Constants.SendType.Bridge,
|
|
preSelectedHoldingID: tokenId ,
|
|
preSelectedHoldingType: tokenType,
|
|
onlyAssets: true
|
|
}
|
|
openSend(params, true)
|
|
}
|
|
|
|
function sendToken(senderAddress, tokenId, tokenType) {
|
|
let sendType = Constants.SendType.Transfer
|
|
let selectedChainId = 0
|
|
let selectedRawAmount = ""
|
|
if (tokenType === Constants.TokenType.ERC721) {
|
|
sendType = Constants.SendType.ERC721Transfer
|
|
selectedRawAmount = "1"
|
|
selectedChainId =
|
|
SQUtils.ModelUtils.getByKey(root.collectiblesBySymbolModel, "symbol", tokenId, "chainId")
|
|
}
|
|
else if(tokenType === Constants.TokenType.ERC1155) {
|
|
sendType = Constants.SendType.ERC1155Transfer
|
|
selectedRawAmount = "1"
|
|
selectedChainId =
|
|
SQUtils.ModelUtils.getByKey(root.collectiblesBySymbolModel, "symbol", tokenId, "chainId")
|
|
}
|
|
else {
|
|
let layer1chainId = SQUtils.ModelUtils.getByKey(root.filteredFlatNetworksModel, "layer", "1", "chainId")
|
|
let networksChainIdArray = SQUtils.ModelUtils.modelToFlatArray(root.filteredFlatNetworksModel, "chainId")
|
|
let selectedAssetAddressPerChain =
|
|
SQUtils.ModelUtils.getByKey(root.plainTokensBySymbolModel, "key", tokenId, "addressPerChain")
|
|
// check if layer address is found
|
|
selectedChainId = SQUtils.ModelUtils.getByKey(selectedAssetAddressPerChain, "chainId", layer1chainId, "chainId")
|
|
// if not layer 1 chain id found, select the first one is list
|
|
if (!selectedChainId) {
|
|
selectedChainId = SQUtils.ModelUtils.getFirstModelEntryIf(
|
|
selectedAssetAddressPerChain,
|
|
(addPerChain) => {
|
|
return networksChainIdArray.includes(addPerChain.chainId)
|
|
})
|
|
}
|
|
}
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
sendType: sendType,
|
|
selectedAccountAddress: senderAddress,
|
|
selectedTokenKey: tokenId,
|
|
selectedRawAmount: selectedRawAmount,
|
|
selectedChainId: selectedChainId,
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedSendType: sendType,
|
|
preSelectedAccountAddress: senderAddress,
|
|
preSelectedHoldingID: tokenId,
|
|
preSelectedHoldingType: tokenType,
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
function openTokenPaymentRequest(recipientAddress, symbol, rawAmount, chainId) {
|
|
let params = {}
|
|
if (root.simpleSendEnabled) {
|
|
params = {
|
|
selectedTokenKey: symbol,
|
|
selectedRawAmount: rawAmount,
|
|
selectedChainId: chainId,
|
|
selectedRecipientAddress: recipientAddress,
|
|
interactive: false,
|
|
openReason: "token payment request"
|
|
}
|
|
} else {
|
|
params = {
|
|
preSelectedHoldingID: symbol,
|
|
preSelectedHoldingType: Constants.TokenType.ERC20,
|
|
preDefinedRawAmountToSend: rawAmount,
|
|
preSelectedChainId: chainId,
|
|
preSelectedRecipient: recipientAddress
|
|
}
|
|
}
|
|
openSend(params)
|
|
}
|
|
|
|
readonly property Component sendModalComponent: Component {
|
|
SendModal {
|
|
loginType: root.loginType
|
|
|
|
store: root.transactionStore
|
|
collectiblesStore: root.walletCollectiblesStore
|
|
|
|
showCustomRoutingMode: !production
|
|
|
|
onClosed: destroy()
|
|
}
|
|
}
|
|
|
|
readonly property Component simpleSendModalComponent: Component {
|
|
SimpleSendModal {
|
|
id: simpleSendModal
|
|
|
|
accountsModel: handler.accountsSelectorAdaptor.processedWalletAccounts
|
|
assetsModel: handler.assetsSelectorViewAdaptor.outputAssetsModel
|
|
flatCollectiblesModel: handler.collectiblesSelectionAdaptor.filteredFlatModel
|
|
collectiblesModel: handler.collectiblesSelectionAdaptor.model
|
|
networksModel: root.filteredFlatNetworksModel
|
|
recipientsModel: handler.recipientViewAdaptor.recipientsModel
|
|
recipientsFilterModel: handler.recipientViewAdaptor.recipientsFilterModel
|
|
|
|
currentCurrency: root.currentCurrency
|
|
fnFormatCurrencyAmount: root.fnFormatCurrencyAmount
|
|
fnResolveENS: root.fnResolveENS
|
|
|
|
onOpened: {
|
|
if(isValidParameter(root.simpleSendParams.interactive)) {
|
|
interactive = root.simpleSendParams.interactive
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.displayOnlyAssets)) {
|
|
displayOnlyAssets = root.simpleSendParams.displayOnlyAssets
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.sendType)) {
|
|
sendType = root.simpleSendParams.sendType
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.selectedAccountAddress) &&
|
|
!!root.simpleSendParams.selectedAccountAddress) {
|
|
selectedAccountAddress = root.simpleSendParams.selectedAccountAddress
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.selectedTokenKey)) {
|
|
selectedTokenKey = root.simpleSendParams.selectedTokenKey
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.selectedChainId)) {
|
|
selectedChainId = root.simpleSendParams.selectedChainId
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.selectedRawAmount)) {
|
|
selectedRawAmount = root.simpleSendParams.selectedRawAmount
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.selectedRecipientAddress)) {
|
|
selectedRecipientAddress = root.simpleSendParams.selectedRecipientAddress
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.publicKey)) {
|
|
publicKey = root.simpleSendParams.publicKey
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.ensName)) {
|
|
ensName = root.simpleSendParams.ensName
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.stickersPackId)) {
|
|
stickersPackId = root.simpleSendParams.stickersPackId
|
|
}
|
|
if(isValidParameter(root.simpleSendParams.transferOwnership)) {
|
|
transferOwnership = root.simpleSendParams.transferOwnership
|
|
}
|
|
let metricsData = ""
|
|
if(isValidParameter(root.simpleSendParams.openReason)) {
|
|
metricsData = root.simpleSendParams.openReason
|
|
} else {
|
|
metricsData = handler.getSendTypeString()
|
|
}
|
|
|
|
handler.sendMetricsEvent("popup opened", metricsData)
|
|
}
|
|
|
|
function isValidParameter(param) {
|
|
return param !== undefined && param !== null
|
|
}
|
|
|
|
onClosed: {
|
|
handler.sendMetricsEvent("popup closed", "")
|
|
destroy()
|
|
root.transactionStoreNew.stopUpdatesForSuggestedRoute()
|
|
}
|
|
|
|
onFormChanged: {
|
|
handler.resetRouterValues()
|
|
if(allValuesFilledCorrectly) {
|
|
handler.uuid = Utils.uuid()
|
|
simpleSendModal.routesLoading = true
|
|
let tokenKey = selectedTokenKey
|
|
/** TODO: This special handling for collectibles should ideally not
|
|
be needed, howver is needed because of current implementation and
|
|
collectible token id is contractAddress:tokenId **/
|
|
if(sendType === Constants.SendType.ERC1155Transfer ||
|
|
sendType === Constants.SendType.ERC721Transfer) {
|
|
const selectedCollectible =
|
|
SQUtils.ModelUtils.getByKey(root.collectiblesBySymbolModel, "symbol", selectedTokenKey)
|
|
if(!!selectedCollectible &&
|
|
!!selectedCollectible.contractAddress &&
|
|
!!selectedCollectible.tokenId) {
|
|
tokenKey = "%1:%2".arg(
|
|
selectedCollectible.contractAddress).arg(
|
|
selectedCollectible.tokenId)
|
|
}
|
|
}
|
|
root.transactionStoreNew.fetchSuggestedRoutes(handler.uuid,
|
|
sendType,
|
|
selectedChainId,
|
|
selectedAccountAddress,
|
|
selectedRecipientAddress,
|
|
selectedRawAmount,
|
|
tokenKey,
|
|
/*amountOut = */ "0",
|
|
/*toToken =*/ "",
|
|
handler.extraParamsJson)
|
|
}
|
|
}
|
|
|
|
onReviewSendClicked: {
|
|
handler.sendMetricsEvent("review send clicked", handler.getSendTypeString())
|
|
if(sendType === Constants.SendType.ERC1155Transfer ||
|
|
sendType === Constants.SendType.ERC721Transfer) {
|
|
const selectedCollectible =
|
|
SQUtils.ModelUtils.getByKey(root.collectiblesBySymbolModel, "symbol", selectedTokenKey)
|
|
if(!!selectedCollectible &&
|
|
!!selectedCollectible.contractAddress &&
|
|
!!selectedCollectible.tokenId) {
|
|
root.fnGetDetailedCollectible(simpleSendModal.selectedChainId ,
|
|
selectedCollectible.contractAddress,
|
|
selectedCollectible.tokenId)
|
|
}
|
|
}
|
|
|
|
handler.reviewNext()
|
|
|
|
Global.openPopup(sendSignModalCmp)
|
|
}
|
|
|
|
onLaunchBuyFlow: {
|
|
root.launchBuyFlowRequested(selectedAccountAddress, selectedChainId, selectedTokenKey)
|
|
}
|
|
|
|
ModelEntry {
|
|
id: txPathUnderReviewEntry
|
|
sourceModel: handler.fetchedPathModel
|
|
key: "index"
|
|
value: handler.indexOfTxPathUnderReview
|
|
}
|
|
|
|
QtObject {
|
|
id: handler
|
|
property string uuid
|
|
property var fetchedPathModel
|
|
|
|
readonly property string extraParamsJson: {
|
|
if (!!simpleSendModal.stickersPackId) {
|
|
return JSON.stringify({[Constants.suggestedRoutesExtraParamsProperties.packId]: simpleSendModal.stickersPackId})
|
|
}
|
|
if (!!simpleSendModal.ensName && !!simpleSendModal.publicKey) {
|
|
return JSON.stringify({[Constants.suggestedRoutesExtraParamsProperties.username]: simpleSendModal.ensName,
|
|
[Constants.suggestedRoutesExtraParamsProperties.publicKey]: simpleSendModal.publicKey})
|
|
}
|
|
return ""
|
|
}
|
|
|
|
property int indexOfTxPathUnderReview: -1
|
|
readonly property bool reviewingLastTxPath: !!handler.fetchedPathModel && handler.indexOfTxPathUnderReview === handler.fetchedPathModel.ModelCount.count - 1
|
|
|
|
property bool approvalForTxPathUnderReviewReviewed: false
|
|
readonly property bool reviewApprovalForTxPathUnderReview: !!txPathUnderReviewEntry.item
|
|
&& txPathUnderReviewEntry.item.approvalRequired
|
|
&& !handler.approvalForTxPathUnderReviewReviewed
|
|
|
|
function reviewNext() {
|
|
if (!handler.reviewApprovalForTxPathUnderReview) {
|
|
handler.indexOfTxPathUnderReview++
|
|
handler.approvalForTxPathUnderReviewReviewed = false
|
|
} else {
|
|
handler.approvalForTxPathUnderReviewReviewed = true
|
|
}
|
|
}
|
|
|
|
function routesFetched(returnedUuid, pathModel, errCode, errDescription) {
|
|
simpleSendModal.routesLoading = false
|
|
if(returnedUuid !== handler.uuid) {
|
|
// Suggested routes for a different fetch, ignore
|
|
return
|
|
}
|
|
simpleSendModal.routerErrorCode = errCode
|
|
simpleSendModal.routerError = WalletUtils.getRouterErrorBasedOnCode(errCode)
|
|
simpleSendModal.routerErrorDetails = "%1 - %2".arg(errCode).arg(
|
|
WalletUtils.getRouterErrorDetailsOnCode(errCode, errDescription))
|
|
fetchedPathModel = pathModel
|
|
}
|
|
|
|
function transactionSent(returnedUuid, chainId, approvalTx, txHash, error) {
|
|
if(returnedUuid !== handler.uuid) {
|
|
// Suggested routes for a different fetch, ignore
|
|
return
|
|
}
|
|
if (!!error) {
|
|
if (error.includes(Constants.walletSection.authenticationCanceled)) {
|
|
return
|
|
}
|
|
simpleSendModal.routerError = error
|
|
sendMetricsEvent("transaction error")
|
|
return
|
|
}
|
|
sendMetricsEvent("transaction successful")
|
|
simpleSendModal.close()
|
|
}
|
|
|
|
function sendMetricsEvent(eventName, data = "") {
|
|
Global.addCentralizedMetricIfEnabled("send", {subEvent: eventName, data: data})
|
|
}
|
|
|
|
function getSendTypeString() {
|
|
switch(simpleSendModal.sendType) {
|
|
case Constants.SendType.Transfer:
|
|
return "Transfer"
|
|
case Constants.SendType.ENSRegister:
|
|
return "ENS Register"
|
|
case Constants.SendType.ENSRelease:
|
|
return "ENS Release"
|
|
case Constants.SendType.ENSSetPubKey:
|
|
return "ENS Set Public Key"
|
|
case Constants.SendType.StickersBuy:
|
|
return "Stickers Buy"
|
|
case Constants.SendType.ERC721Transfer:
|
|
return "ERC721 Transfer"
|
|
case Constants.SendType.ERC1155Transfer:
|
|
return "ERC1155 Transfer"
|
|
case Constants.SendType.CommunityBurn:
|
|
return "Community Burn"
|
|
case Constants.SendType.CommunityDeployAssets:
|
|
return "Community Deploy Assets"
|
|
case Constants.SendType.CommunityDeployCollectibles:
|
|
return "Community Deploy Collectibles"
|
|
case Constants.SendType.CommunityDeployOwnerToken:
|
|
return "Community Deploy Owner Token"
|
|
case Constants.SendType.CommunityMintTokens:
|
|
return "Community Mint Tokens"
|
|
case Constants.SendType.CommunityRemoteBurn:
|
|
return "Community Remote Burn"
|
|
case Constants.SendType.CommunitySetSignerPubKey:
|
|
return "Community Set Signer Public Key"
|
|
case Constants.SendType.Approve:
|
|
return "Approve"
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
readonly property var recipientViewAdaptor: RecipientViewAdaptor {
|
|
savedAddressesModel: root.savedAddressesModel
|
|
accountsModel: root.walletAccountsModel
|
|
recentRecipientsModel: root.recentRecipientsModel
|
|
|
|
selectedSenderAddress: simpleSendModal.selectedAccountAddress
|
|
selectedRecipientType: simpleSendModal.selectedRecipientType
|
|
searchPattern: simpleSendModal.recipientSearchPattern
|
|
}
|
|
|
|
readonly property var accountsSelectorAdaptor: WalletAccountsSelectorAdaptor {
|
|
accounts: root.walletAccountsModel
|
|
assetsModel: root.groupedAccountAssetsModel
|
|
tokensBySymbolModel: root.plainTokensBySymbolModel
|
|
filteredFlatNetworksModel: root.filteredFlatNetworksModel
|
|
|
|
selectedTokenKey: simpleSendModal.selectedTokenKey
|
|
selectedNetworkChainId: simpleSendModal.selectedChainId
|
|
|
|
fnFormatCurrencyAmountFromBigInt: root.fnFormatCurrencyAmountFromBigInt
|
|
}
|
|
|
|
readonly property var assetsSelectorViewAdaptor: TokenSelectorViewAdaptor {
|
|
assetsModel: root.groupedAccountAssetsModel
|
|
flatNetworksModel: root.flatNetworksModel
|
|
|
|
currentCurrency: root.currentCurrency
|
|
showCommunityAssets: root.showCommunityAssetsInSend
|
|
showZeroBalanceForDefaultTokens: true
|
|
|
|
accountAddress: simpleSendModal.selectedAccountAddress
|
|
enabledChainIds: [simpleSendModal.selectedChainId]
|
|
}
|
|
|
|
readonly property var collectiblesSelectionAdaptor: CollectiblesSelectionAdaptor {
|
|
accountKey: simpleSendModal.selectedAccountAddress
|
|
enabledChainIds: [simpleSendModal.selectedChainId]
|
|
|
|
networksModel: root.filteredFlatNetworksModel
|
|
collectiblesModel: SortFilterProxyModel {
|
|
sourceModel: root.collectiblesBySymbolModel
|
|
filters: ValueFilter {
|
|
roleName: "soulbound"
|
|
value: false
|
|
}
|
|
}
|
|
filterCommunityOwnerAndMasterTokens: !simpleSendModal.transferOwnership
|
|
}
|
|
|
|
readonly property var totalFeesAggregator: FunctionAggregator {
|
|
model: !!handler.fetchedPathModel ?
|
|
handler.fetchedPathModel: null
|
|
initialValue: "0"
|
|
roleName: "txTotalFee"
|
|
|
|
aggregateFunction: (aggr, value) => SQUtils.AmountsArithmetic.sum(
|
|
SQUtils.AmountsArithmetic.fromString(aggr),
|
|
SQUtils.AmountsArithmetic.fromString(value)).toString()
|
|
|
|
onValueChanged: {
|
|
const ethToken = SQUtils.ModelUtils.getByKey(root.plainTokensBySymbolModel, "key", Constants.ethToken)
|
|
let decimals = !!ethToken ? ethToken.decimals: 18
|
|
let ethFiatValue = !!ethToken ? ethToken.marketDetails.currencyPrice.amount: 1
|
|
let totalFees = SQUtils.AmountsArithmetic.div(SQUtils.AmountsArithmetic.fromString(value), SQUtils.AmountsArithmetic.fromNumber(1, decimals))
|
|
let totalFeesInFiat = root.fnFormatCurrencyAmount(ethFiatValue*totalFees, root.currentCurrency).toString()
|
|
simpleSendModal.estimatedCryptoFees = root.fnFormatCurrencyAmount(totalFees.toString(), Constants.ethToken)
|
|
simpleSendModal.estimatedFiatFees = totalFeesInFiat
|
|
}
|
|
}
|
|
|
|
readonly property var estimatedTimeAggregator: FunctionAggregator {
|
|
model: !!handler.fetchedPathModel ?
|
|
handler.fetchedPathModel: null
|
|
initialValue: Constants.TransactionEstimatedTime.Unknown
|
|
roleName: "estimatedTime"
|
|
|
|
aggregateFunction: (aggr, value) => aggr < value? value : aggr
|
|
|
|
onValueChanged: {
|
|
simpleSendModal.estimatedTime = WalletUtils.getLabelForEstimatedTxTime(value)
|
|
}
|
|
}
|
|
|
|
Component.onCompleted: {
|
|
root.ensNameResolved.connect(ensNameResolved)
|
|
root.transactionStoreNew.suggestedRoutesReady.connect(routesFetched)
|
|
root.transactionStoreNew.transactionSent.connect(transactionSent)
|
|
}
|
|
|
|
function resetRouterValues() {
|
|
handler.uuid = ""
|
|
handler.fetchedPathModel = null
|
|
handler.indexOfTxPathUnderReview = -1
|
|
simpleSendModal.estimatedCryptoFees = ""
|
|
simpleSendModal.estimatedFiatFees = ""
|
|
simpleSendModal.estimatedTime = ""
|
|
simpleSendModal.routerErrorCode = ""
|
|
simpleSendModal.routerError = ""
|
|
simpleSendModal.routerErrorDetails = ""
|
|
}
|
|
}
|
|
|
|
SignSendAdaptor {
|
|
id: signSendAdaptor
|
|
accountKey: simpleSendModal.selectedAccountAddress
|
|
accountsModel: root.walletAccountsModel
|
|
recipientModel: handler.recipientViewAdaptor.recipientsModel
|
|
chainId: simpleSendModal.selectedChainId
|
|
networksModel: root.flatNetworksModel
|
|
tokenKey: simpleSendModal.selectedTokenKey
|
|
tokenBySymbolModel: root.plainTokensBySymbolModel
|
|
selectedAmountInBaseUnit: simpleSendModal.selectedRawAmount
|
|
selectedRecipientAddress: simpleSendModal.selectedRecipientAddress
|
|
}
|
|
|
|
Component {
|
|
id: sendSignModalCmp
|
|
SendSignModal {
|
|
closePolicy: Popup.CloseOnEscape
|
|
destroyOnClose: true
|
|
onClosed: root.fnResetDetailedCollectible()
|
|
// Unused
|
|
formatBigNumber: function(number, symbol, noSymbolOption) {}
|
|
|
|
tokenSymbol: !!signSendAdaptor.selectedAsset &&
|
|
!!signSendAdaptor.selectedAsset.symbol ?
|
|
signSendAdaptor.selectedAsset.symbol: ""
|
|
tokenAmount: signSendAdaptor.selectedAmount
|
|
tokenContractAddress: signSendAdaptor.selectedAssetContractAddress
|
|
|
|
accountName: signSendAdaptor.selectedAccount.name
|
|
accountAddress: signSendAdaptor.selectedAccount.address
|
|
accountEmoji: signSendAdaptor.selectedAccount.emoji
|
|
accountColor: Utils.getColorForId(signSendAdaptor.selectedAccount.colorId)
|
|
|
|
recipientAddress: signSendAdaptor.recipientAddress
|
|
recipientName: signSendAdaptor.recipientName
|
|
recipientEns: signSendAdaptor.recipientEns
|
|
recipientEmoji: signSendAdaptor.recipientEmoji
|
|
recipientWalletColor: signSendAdaptor.recipientWalletColor
|
|
|
|
networkShortName: signSendAdaptor.selectedNetwork.shortName
|
|
networkName: signSendAdaptor.selectedNetwork.chainName
|
|
networkIconPath: Theme.svg(signSendAdaptor.selectedNetwork.iconUrl)
|
|
networkBlockExplorerUrl: signSendAdaptor.selectedNetwork.blockExplorerURL
|
|
|
|
readonly property var totalFeesEth: {
|
|
let tatlFeeInWei = "0"
|
|
if (!!txPathUnderReviewEntry.item) {
|
|
if (handler.reviewApprovalForTxPathUnderReview) {
|
|
tatlFeeInWei = SQUtils.AmountsArithmetic.sum(SQUtils.AmountsArithmetic.fromString(txPathUnderReviewEntry.item.approvalFee),
|
|
SQUtils.AmountsArithmetic.fromString(txPathUnderReviewEntry.item.approvalL1Fee))
|
|
} else {
|
|
tatlFeeInWei = SQUtils.AmountsArithmetic.sum(SQUtils.AmountsArithmetic.fromString(txPathUnderReviewEntry.item.txFee),
|
|
SQUtils.AmountsArithmetic.fromString(txPathUnderReviewEntry.item.txL1Fee))
|
|
}
|
|
}
|
|
return SQUtils.AmountsArithmetic.div(SQUtils.AmountsArithmetic.fromString(tatlFeeInWei), SQUtils.AmountsArithmetic.fromNumber(1, Constants.ethTokenDecimals))
|
|
}
|
|
|
|
fiatFees: {
|
|
const ethToken = SQUtils.ModelUtils.getByKey(root.plainTokensBySymbolModel, "key", Constants.ethToken)
|
|
const ethFiatValue = !!ethToken ? ethToken.marketDetails.currencyPrice.amount: 1
|
|
return root.fnFormatCurrencyAmount(ethFiatValue*totalFeesEth, root.currentCurrency).toString()
|
|
}
|
|
|
|
cryptoFees: root.fnFormatCurrencyAmount(totalFeesEth.toString(), Constants.ethToken)
|
|
|
|
estimatedTime: {
|
|
if (!!txPathUnderReviewEntry.item) {
|
|
if (handler.reviewApprovalForTxPathUnderReview) {
|
|
return WalletUtils.getLabelForEstimatedTxTime(txPathUnderReviewEntry.item.approvalEstimatedTime)
|
|
}
|
|
return WalletUtils.getLabelForEstimatedTxTime(txPathUnderReviewEntry.item.txEstimatedTime)
|
|
}
|
|
return Constants.TransactionEstimatedTime.Unknown
|
|
}
|
|
|
|
loginType: root.loginType
|
|
|
|
isCollectible: simpleSendModal.sendType === Constants.SendType.ERC1155Transfer ||
|
|
simpleSendModal.sendType === Constants.SendType.ERC721Transfer
|
|
isCollectibleLoading: root.isDetailedCollectibleLoading
|
|
collectibleContractAddress: root.detailedCollectible.contractAddress
|
|
collectibleTokenId: root.detailedCollectible.tokenId
|
|
collectibleName: root.detailedCollectible.name
|
|
collectibleBackgroundColor: root.detailedCollectible.backgroundColor
|
|
collectibleIsMetadataValid: root.detailedCollectible.isMetadataValid
|
|
collectibleMediaUrl: root.detailedCollectible.mediaUrl
|
|
collectibleMediaType: root.detailedCollectible.mediaType
|
|
collectibleFallbackImageUrl: root.detailedCollectible.imageUrl
|
|
|
|
fnGetOpenSeaExplorerUrl: root.fnGetOpenSeaUrl
|
|
|
|
onOpened: handler.sendMetricsEvent("sign modal opened")
|
|
onRejected: handler.sendMetricsEvent("sign modal rejected")
|
|
onAccepted: {
|
|
handler.sendMetricsEvent("sign modal accepted")
|
|
if (handler.reviewingLastTxPath) {
|
|
root.transactionStoreNew.authenticateAndTransfer(handler.uuid, simpleSendModal.selectedAccountAddress)
|
|
return
|
|
}
|
|
handler.reviewNext()
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|