feat(@desktop/wallet): Implementation of Notifications

fixes #14834
This commit is contained in:
Khushboo Mehta 2024-07-10 20:33:51 +02:00 committed by dlipicar
parent b93edff484
commit c89203f371
7 changed files with 224 additions and 29 deletions

View File

@ -462,13 +462,20 @@ proc connectForNotificationsOnly[T](self: Module[T]) =
self.events.on(SIGNAL_TRANSACTION_SENT) do(e:Args):
let args = TransactionSentArgs(e)
self.view.showToastTransactionSent(args.chainId, args.txHash, args.uuid, args.error)
self.view.showToastTransactionSent(args.chainId, args.txHash, args.uuid, args.error,
ord(args.txType), args.fromAddress, args.toAddress, args.fromTokenKey, args.fromAmount,
args.fromTokenKey, args.toAmount)
self.events.on(MARK_WALLET_ADDRESSES_AS_SHOWN) do(e:Args):
let args = WalletAddressesArgs(e)
for address in args.addresses:
self.addressWasShown(address)
self.events.on(SIGNAL_TRANSACTION_SENDING_COMPLETE) do(e:Args):
let args = TransactionMinedArgs(e)
self.view.showToastTransactionSendingComplete(args.chainId, args.transactionHash, args.data, args.success,
ord(args.txType), args.fromAddress, args.toAddress, args.fromTokenKey, args.fromAmount, args.toTokenKey, args.toAmount)
method load*[T](
self: Module[T],
events: EventEmitter,

View File

@ -341,7 +341,10 @@ QtObject:
proc showNetworkEndpointUpdated*(self: View, name: string, isTest: bool, revertedToDefault: bool) {.signal.}
proc showToastKeypairRemoved*(self: View, keypairName: string) {.signal.}
proc showToastKeypairsImported*(self: View, keypairName: string, keypairsCount: int, error: string) {.signal.}
proc showToastTransactionSent*(self: View, chainId: int, txHash: string, uuid: string, error: string) {.signal.}
proc showToastTransactionSent*(self: View, chainId: int, txHash: string, uuid: string, error: string,
txType: int, fromAddr: string, toAddr: string, fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string) {.signal.}
proc showToastTransactionSendingComplete*(self: View, chainId: int, txHash: string, data: string, success: bool,
txType: int, fromAddr: string, toAddr: string, fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string) {.signal.}
## Used in test env only, for testing keycard flows
proc registerMockedKeycard*(self: View, cardIndex: int, readerState: int, keycardState: int,

View File

@ -132,9 +132,10 @@ proc transfer*(self: Controller, from_addr: string, to_addr: string, assetKey: s
self.transactionService.transfer(from_addr, to_addr, assetKey, toAssetKey, uuid, selectedRoutes, password, sendType,
usePassword, doHashing, tokenName, isOwnerToken, slippagePercentage)
proc proceedWithTransactionsSignatures*(self: Controller, fromAddr: string, toAddr: string, uuid: string,
signatures: TransactionsSignatures, selectedRoutes: seq[TransactionPathDto]) =
self.transactionService.proceedWithTransactionsSignatures(fromAddr, toAddr, uuid, signatures, selectedRoutes)
proc proceedWithTransactionsSignatures*(self: Controller, fromAddr: string, toAddr: string,
fromTokenKey: string, toTokenKey: string, uuid: string, signatures: TransactionsSignatures,
selectedRoutes: seq[TransactionPathDto], sendType: SendType) =
self.transactionService.proceedWithTransactionsSignatures(fromAddr, toAddr, fromTokenKey, toTokenKey, uuid, signatures, selectedRoutes, sendType)
proc areTestNetworksEnabled*(self: Controller): bool =
return self.walletAccountService.areTestNetworksEnabled()

View File

@ -252,7 +252,8 @@ proc signOnKeycard(self: Module) =
break
if self.tmpTxHashBeingProcessed.len == 0:
self.controller.proceedWithTransactionsSignatures(self.tmpSendTransactionDetails.fromAddr, self.tmpSendTransactionDetails.toAddr,
self.tmpSendTransactionDetails.uuid, self.tmpSendTransactionDetails.resolvedSignatures, self.tmpSendTransactionDetails.paths)
self.tmpSendTransactionDetails.assetKey, self.tmpSendTransactionDetails.toAssetKey, self.tmpSendTransactionDetails.uuid,
self.tmpSendTransactionDetails.resolvedSignatures, self.tmpSendTransactionDetails.paths, self.tmpSendTransactionDetails.sendType)
method prepareSignaturesForTransactions*(self: Module, txHashes: seq[string]) =
if txHashes.len == 0:

View File

@ -26,6 +26,12 @@ type
chainId: int
address: string
trxType: string
txType: int
toAddress: string
fromTokenKey: string
fromAmount: string
toTokenKey: string
toAmount: string
proc watchTransactionTask*(argEncoded: string) {.gcsafe, nimcall.} =
let arg = decode[WatchTransactionTaskArg](argEncoded)
@ -36,6 +42,12 @@ proc watchTransactionTask*(argEncoded: string) {.gcsafe, nimcall.} =
"address": arg.address,
"chainId": arg.chainId,
"trxType": arg.trxType,
"txType": arg.txType,
"toAddress": arg.toAddress,
"fromTokenKey": arg.fromTokenKey,
"fromAmount": arg.fromAmount,
"toTokenKey": arg.toTokenKey,
"toAmount": arg.toAmount,
"isSuccessfull": transactions.watchTransaction(arg.chainId, arg.hash).error.isNil,
}
arg.finish(output)
@ -46,6 +58,12 @@ proc watchTransactionTask*(argEncoded: string) {.gcsafe, nimcall.} =
"address": arg.address,
"chainId": arg.chainId,
"trxType": arg.trxType,
"txType": arg.txType,
"toAddress": arg.toAddress,
"fromTokenKey": arg.fromTokenKey,
"fromAmount": arg.fromAmount,
"toTokenKey": arg.toTokenKey,
"toAmount": arg.toAmount,
"isSuccessfull": false
}

View File

@ -82,6 +82,13 @@ type
transactionHash*: string
chainId*: int
success*: bool
txType*: SendType
fromAddress*: string
toAddress*: string
fromTokenKey*: string
fromAmount*: string
toTokenKey*: string
toAmount*: string
proc `$`*(self: TransactionMinedArgs): string =
try:
@ -90,6 +97,13 @@ proc `$`*(self: TransactionMinedArgs): string =
chainId: {$self.chainId},
success: {$self.success},
data: {self.data},
txType: {$self.txType},
fromAddress: {$self.fromAddress},
toAddress: {$self.toAddress},
fromTokenKey: {$self.fromTokenKey},
fromAmount: {$self.fromAmount},
toTokenKey: {$self.toTokenKey},
toAmount: {$self.toAmount},
)"""
except ValueError:
raiseAssert "static fmt"
@ -100,6 +114,13 @@ type
txHash*: string
uuid*: string
error*: string
txType*: SendType
fromAddress*: string
toAddress*: string
fromTokenKey*: string
fromAmount*: string
toTokenKey*: string
toAmount*: string
type
OwnerTokenSentArgs* = ref object of Args
@ -207,18 +228,31 @@ QtObject:
transactionHash: hash,
chainId: chainId,
success: transactionReceipt{"status"}.getStr == "0x1",
txType: SendType(watchTxResult["txType"].getInt),
fromAddress: address,
toAddress: watchTxResult["toAddress"].getStr,
fromTokenKey: watchTxResult["fromTokenKey"].getStr,
fromAmount: watchTxResult["fromAmount"].getStr,
toTokenKey: watchTxResult["toTokenKey"].getStr,
toAmount: watchTxResult["toAmount"].getStr,
)
self.events.emit(parseEnum[PendingTransactionTypeDto](watchTxResult["trxType"].getStr).event, ev)
transactions.checkRecentHistory(@[chainId], @[address])
proc watchTransaction*(
self: Service, hash: string, fromAddress: string, toAddress: string, trxType: string, data: string, chainId: int, track: bool = true
self: Service, hash: string, fromAddress: string, toAddress: string, trxType: string, data: string, chainId: int,
fromTokenKey: string = "", fromAmount: string = "", toTokenKey: string = "", toAmount: string = "", txType: SendType = SendType.Transfer
) =
let arg = WatchTransactionTaskArg(
chainId: chainId,
hash: hash,
address: fromAddress,
trxType: trxType,
txType: ord(txType),
fromTokenKey: fromTokenKey,
fromAmount: fromAmount,
toTokenKey: toTokenKey,
toAmount: toAmount,
data: data,
tptr: watchTransactionTask,
vptr: cast[ByteAddress](self.vptr),
@ -317,7 +351,8 @@ QtObject:
path.cbridgeTx = cbridgeTx
return path
proc sendTransactionSentSignal(self: Service, fromAddr: string, toAddr: string, uuid: string,
proc sendTransactionSentSignal(self: Service, txType: SendType, fromAddr: string, toAddr: string,
fromTokenKey: string, fromAmount: string, toTokenKey: string, toAmount: string, uuid: string,
routes: seq[TransactionPathDto], response: RpcResponse[JsonNode], err: string = "", tokenName = "", isOwnerToken=false) =
# While preparing the tx in the Send modal user cannot see the address, it's revealed once the tx is sent
# (there are few places where we display the toast from and link to the etherscan where the address can be seen)
@ -325,17 +360,22 @@ QtObject:
self.events.emit(MARK_WALLET_ADDRESSES_AS_SHOWN, WalletAddressesArgs(addresses: @[fromAddr, toAddr]))
if err.len > 0:
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(uuid: uuid, error: err))
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(uuid: uuid, error: err, txType: txType,
fromAddress: fromAddr, toAddress: toAddr, fromTokenKey: fromTokenKey, fromAmount: fromAmount,
toTokenKey: toTokenKey, toAmount: toAmount))
elif response.result{"hashes"} != nil:
for route in routes:
for hash in response.result["hashes"][$route.fromNetwork.chainID]:
if isOwnerToken:
self.events.emit(SIGNAL_OWNER_TOKEN_SENT, OwnerTokenSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr, uuid: uuid, tokenName: tokenName, status: ContractTransactionStatus.InProgress))
self.events.emit(SIGNAL_OWNER_TOKEN_SENT, OwnerTokenSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr,
uuid: uuid, tokenName: tokenName, status: ContractTransactionStatus.InProgress))
else:
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr, uuid: uuid , error: ""))
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: route.fromNetwork.chainID, txHash: hash.getStr, uuid: uuid ,
error: "", txType: txType, fromAddress: fromAddr, toAddress: toAddr, fromTokenKey: fromTokenKey, fromAmount: fromAmount, toTokenKey: toTokenKey, toAmount: toAmount))
let metadata = TokenTransferMetadata(tokenName: tokenName, isOwnerToken: isOwnerToken)
self.watchTransaction(hash.getStr, fromAddr, toAddr, $PendingTransactionTypeDto.WalletTransfer, $(%metadata), route.fromNetwork.chainID, track = false)
self.watchTransaction(hash.getStr, fromAddr, toAddr, $PendingTransactionTypeDto.WalletTransfer, $(%metadata), route.fromNetwork.chainID,
fromTokenKey, fromAmount, toTokenKey, toAmount, txType)
proc isCollectiblesTransfer(self: Service, sendType: SendType): bool =
return sendType == ERC721Transfer or sendType == ERC1155Transfer
@ -364,6 +404,7 @@ QtObject:
try:
var paths: seq[TransactionBridgeDto] = @[]
var totalAmountToSend: UInt256
var totalAmountToReceive: UInt256
let toAddress = parseAddress(to_addr)
for route in routes:
@ -377,6 +418,7 @@ QtObject:
paths.add(self.createApprovalPath(route, from_addr, toAddress, gasFees))
totalAmountToSend += route.amountIn
totalAmountToReceive += route.amountOut
txData = ens_utils.buildTransaction(parseAddress(from_addr), route.amountIn,
$route.gasAmount, gasFees, route.gasFees.eip1559Enabled, $route.gasFees.maxPriorityFeePerGas, $route.gasFees.maxFeePerGasM)
txData.to = parseAddress(to_addr).some
@ -400,9 +442,11 @@ QtObject:
)
if password != "":
self.sendTransactionSentSignal(from_addr, to_addr, uuid, routes, response)
self.sendTransactionSentSignal(sendType, from_addr, to_addr, tokenSymbol, totalAmountToSend.toString(10),
toTokenSymbol, totalAmountToReceive.toString(10), uuid, routes, response)
except Exception as e:
self.sendTransactionSentSignal(from_addr, to_addr, uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}")
self.sendTransactionSentSignal(sendType, from_addr, to_addr, tokenSymbol, "",
toTokenSymbol, "", uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}")
proc mustIgnoreApprovalRequests(sendType: SendType): bool =
# Swap requires approvals to be done in advance in a separate Tx
@ -430,6 +474,7 @@ QtObject:
toContractAddress: Address
paths: seq[TransactionBridgeDto] = @[]
totalAmountToSend: UInt256
totalAmountToReceive: UInt256
mtCommand = MultiTransactionCommandDto(
fromAddress: from_addr,
toAddress: to_addr,
@ -474,6 +519,7 @@ QtObject:
paths.add(approvalPath)
totalAmountToSend += route.amountIn
totalAmountToReceive += route.amountOut
if sendType == SendType.Approve:
# We only do the approvals
@ -505,10 +551,14 @@ QtObject:
let response = transactions.createMultiTransaction(mtCommand, paths, password)
if password != "":
self.sendTransactionSentSignal(mtCommand.fromAddress, mtCommand.toAddress, uuid, routes, response, err="", tokenName, isOwnerToken)
self.sendTransactionSentSignal(sendType, mtCommand.fromAddress, mtCommand.toAddress,
assetKey, totalAmountToSend.toString(10), toAssetKey, totalAmountToReceive.toString(10),
uuid, routes, response, err="", tokenName, isOwnerToken)
except Exception as e:
self.sendTransactionSentSignal(mtCommand.fromAddress, mtCommand.toAddress, uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}")
self.sendTransactionSentSignal(sendType, mtCommand.fromAddress, mtCommand.toAddress,
assetKey, "", toAssetKey, "",
uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}")
proc transfer*(
self: Service,
@ -563,15 +613,24 @@ QtObject:
sendType, tokenName, isOwnerToken, slippagePercentage)
except Exception as e:
self.events.emit(SIGNAL_TRANSACTION_SENT, TransactionSentArgs(chainId: 0, txHash: "", uuid: uuid, error: fmt"Error sending token transfer transaction: {e.msg}"))
self.sendTransactionSentSignal(sendType, fromAddr, toAddr, assetKey, "", toAssetKey, "", uuid, @[], RpcResponse[JsonNode](), fmt"Error sending token transfer transaction: {e.msg}")
proc proceedWithTransactionsSignatures*(self: Service, fromAddr: string, toAddr: string, uuid: string,
signatures: TransactionsSignatures, selectedRoutes: seq[TransactionPathDto]) =
proc proceedWithTransactionsSignatures*(self: Service, fromAddr: string, toAddr: string,
fromTokenKey: string, toTokenKey: string, uuid: string, signatures: TransactionsSignatures,
selectedRoutes: seq[TransactionPathDto], sendType: SendType) =
try:
let response = transactions.proceedWithTransactionsSignatures(signatures)
self.sendTransactionSentSignal(fromAddr, toAddr, uuid, selectedRoutes, response)
var totalAmountToSend: UInt256
var totalAmountToReceive: UInt256
for route in selectedRoutes:
totalAmountToSend += route.amountIn
totalAmountToReceive += route.amountOut
self.sendTransactionSentSignal(sendType, fromAddr, toAddr, fromTokenKey, totalAmountToSend.toString(10), toTokenKey, totalAmountToReceive.toString(10), uuid, selectedRoutes, response)
except Exception as e:
self.sendTransactionSentSignal(fromAddr, toAddr, uuid, @[], RpcResponse[JsonNode](), fmt"Error proceeding with transactions signatures: {e.msg}")
self.sendTransactionSentSignal(sendType, fromAddr, toAddr, fromTokenKey, "", toTokenKey, "",
uuid, @[], RpcResponse[JsonNode](), fmt"Error proceeding with transactions signatures: {e.msg}")
proc suggestedFees*(self: Service, chainId: int): SuggestedFeesDto =
try:

View File

@ -218,14 +218,120 @@ Item {
)
}
function onShowToastTransactionSent(chainId: int, txHash: string, uuid: string, error: string) {
if (!error) {
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on etherscan"),
"",
true,
Constants.ephemeralNotificationType.normal,
"%1/%2".arg(appMain.rootStore.getEtherscanLink(chainId)).arg(txHash))
function onShowToastTransactionSent(chainId: int, txHash: string, uuid: string, error: string, txType: int,
fromAddr: string, toAddr: string, fromTokenKey: string, fromAmount: string,
toTokenKey: string, toAmount: string) {
switch(txType) {
case Constants.SendType.Approve: {
const fromToken = SQUtils.ModelUtils.getByKey(appMain.tokensStore.plainTokensBySymbolModel, "key", fromTokenKey)
const fromAccountName = SQUtils.ModelUtils.getByKey(appMain.transactionStore.accounts, "address", fromAddr, "name")
const networkName = SQUtils.ModelUtils.getByKey(WalletStore.RootStore.filteredFlatModel, "chainId", chainId, "chainName")
if(!!fromToken && !!fromAccountName && !!networkName) {
const approvalAmount = currencyStore.formatCurrencyAmountFromBigInt(fromAmount, fromToken.symbol, fromToken.decimals)
let toastTitle = qsTr("Setting spending cap: %1 in %2 for %3 on %4").arg(approvalAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
let toastSubtitle = qsTr("View on %1").arg(networkName)
let urlLink = "%1/%2".arg(appMain.rootStore.getEtherscanLink(chainId)).arg(txHash)
let toastType = Constants.ephemeralNotificationType.normal
let icon = ""
if(error) {
toastTitle = qsTr("Failed to set spending cap: %1 in %2 for %3 on %4").arg(approvalAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
toastSubtitle = ""
urlLink = ""
toastType = Constants.ephemeralNotificationType.danger
icon = "warning"
}
Global.displayToastMessage(toastTitle, toastSubtitle, icon, !error, toastType, urlLink)
}
break
}
case Constants.SendType.Swap: {
const fromToken = SQUtils.ModelUtils.getByKey(appMain.tokensStore.plainTokensBySymbolModel, "key", fromTokenKey)
const toToken = SQUtils.ModelUtils.getByKey(appMain.tokensStore.plainTokensBySymbolModel, "key", toTokenKey)
const fromAccountName = SQUtils.ModelUtils.getByKey(appMain.transactionStore.accounts, "address", fromAddr, "name")
const networkName = SQUtils.ModelUtils.getByKey(WalletStore.RootStore.filteredFlatModel, "chainId", chainId, "chainName")
if(!!fromToken && !!toToken && !!fromAccountName && !!networkName) {
const fromSwapAmount = currencyStore.formatCurrencyAmountFromBigInt(fromAmount, fromToken.symbol, fromToken.decimals)
const toSwapAmount = currencyStore.formatCurrencyAmountFromBigInt(toAmount, toToken.symbol, toToken.decimals)
let toastTitle = qsTr("Swapping %1 to %2 in %3 using %4 on %5").arg(fromSwapAmount).arg(toSwapAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
let toastSubtitle = qsTr("View on %1").arg(networkName)
let urlLink = "%1/%2".arg(appMain.rootStore.getEtherscanLink(chainId)).arg(txHash)
let toastType = Constants.ephemeralNotificationType.normal
let icon = ""
if(error) {
toastTitle = qsTr("Failed to swap %1 to %2 in %3 using %4 on %5").arg(fromSwapAmount).arg(toSwapAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
toastSubtitle = ""
urlLink = ""
toastType = Constants.ephemeralNotificationType.danger
icon = "warning"
}
Global.displayToastMessage(toastTitle, toastSubtitle, icon, !error, toastType, urlLink)
}
break
}
default: {
if (!error) {
let networkName = SQUtils.ModelUtils.getByKey(WalletStore.RootStore.filteredFlatModel, "chainId", chainId, "chainName")
if(!!networkName) {
Global.displayToastMessage(qsTr("Transaction pending..."),
qsTr("View on %1").arg(networkName),
"",
true,
Constants.ephemeralNotificationType.normal,
"%1/%2".arg(appMain.rootStore.getEtherscanLink(chainId)).arg(txHash))
}
}
break
}
}
}
function onShowToastTransactionSendingComplete(chainId: int, txHash: string, data: string, success: bool,
txType: int, fromAddr: string, toAddr: string, fromTokenKey: string,
fromAmount: string, toTokenKey: string, toAmount: string) {
switch(txType) {
case Constants.SendType.Approve: {
const fromToken = SQUtils.ModelUtils.getByKey(appMain.tokensStore.plainTokensBySymbolModel, "key", fromTokenKey)
const fromAccountName = SQUtils.ModelUtils.getByKey(appMain.transactionStore.accounts, "address", fromAddr, "name")
const networkName = SQUtils.ModelUtils.getByKey(WalletStore.RootStore.filteredFlatModel, "chainId", chainId, "chainName")
if(!!fromToken && !!fromAccountName && !!networkName) {
const approvalAmount = currencyStore.formatCurrencyAmountFromBigInt(fromAmount, fromToken.symbol, fromToken.decimals)
let toastTitle = qsTr("Spending cap set: %1 in %2 for %3 on %4").arg(approvalAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
const toastSubtitle = qsTr("View on %1").arg(networkName)
const urlLink = "%1/%2".arg(appMain.rootStore.getEtherscanLink(chainId)).arg(txHash)
let toastType = Constants.ephemeralNotificationType.success
let icon = "checkmark-circle"
if(!success) {
toastTitle = qsTr("Failed to set spending cap: %1 in %2 for %3 on %4").arg(approvalAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
toastType = Constants.ephemeralNotificationType.danger
icon = "warning"
}
Global.displayToastMessage(toastTitle, toastSubtitle, icon, false, toastType, urlLink)
}
break
}
case Constants.SendType.Swap: {
const fromToken = SQUtils.ModelUtils.getByKey(appMain.tokensStore.plainTokensBySymbolModel, "key", fromTokenKey)
const toToken = SQUtils.ModelUtils.getByKey(appMain.tokensStore.plainTokensBySymbolModel, "key", toTokenKey)
const fromAccountName = SQUtils.ModelUtils.getByKey(appMain.transactionStore.accounts, "address", fromAddr, "name")
const networkName = SQUtils.ModelUtils.getByKey(WalletStore.RootStore.filteredFlatModel, "chainId", chainId, "chainName")
if(!!fromToken && !!toToken && !!fromAccountName && !!networkName) {
const fromSwapAmount = currencyStore.formatCurrencyAmountFromBigInt(fromAmount, fromToken.symbol, fromToken.decimals)
const toSwapAmount = currencyStore.formatCurrencyAmountFromBigInt(toAmount, toToken.symbol, toToken.decimals)
let toastTitle = qsTr("Swapped %1 to %2 in %3 using %4 on %5").arg(fromSwapAmount).arg(toSwapAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
const toastSubtitle = qsTr("View on %1").arg(networkName)
const urlLink = "%1/%2".arg(appMain.rootStore.getEtherscanLink(chainId)).arg(txHash)
let toastType = Constants.ephemeralNotificationType.success
let icon = "checkmark-circle"
if(!success) {
toastTitle = qsTr("Failed to swap %1 to %2 in %3 using %4 on %5").arg(fromSwapAmount).arg(toSwapAmount).arg(fromAccountName).arg(Constants.swap.paraswapUrl).arg(networkName)
toastType = Constants.ephemeralNotificationType.danger
icon = "warning"
}
Global.displayToastMessage(toastTitle, toastSubtitle, icon, false, toastType, urlLink)
}
break
}
default: break
}
}