Before committing to a transaction, it's often useful to simulate its outcome to understand the potential changes and detect any errors preemptively.
Portal provides the function portal.api.simulateTransaction, which gives you insights into what will happen upon executing the transaction.
Here's how it works:
suspendfunsimulateTransaction(): Result<String> {val evaluateTransactionParam =EvaluateTransactionParam( to ="0x5596D66388555273eF90163f5e7314C8CE14F73c", // The recipient address.value="0x10DE4A2A", // The value to be sent in Wei.data=null, // Data for the transaction (for contract interactions). maxFeePerGas =null, // Maximum fee per gas. maxPriorityFeePerGas =null, // Maximum priority fee per gas. gas =null, // The gas limit. gasPrice =null, // Gas price in Wei. )val result = portal.api.evaluateTransaction( chainId = ETH_SEPOLIA_CHAIN_ID, operationType = EvaluateTransactionOperationType.SIMULATION, transaction = evaluateTransactionParam )if (result.isFailure) {return Result.failure(Exception("error: ${result.exceptionOrNull()?.message}")) }return Result.success("") }
suspendfunhandleSimulateTransaction() {// First, create a transaction.val transaction =SimulateTransactionParam( to ="0xRecipientAddressHere", // The recipient address.value="0x10DE4A2A", // The value to be sent in Wei.data=null, // Data for the transaction (for contract interactions). maxFeePerGas =null, // Maximum fee per gas. maxPriorityFeePerGas =null, // Maximum priority fee per gas. gas =null, // The gas limit. gasPrice =null// Gas price in Wei. )// Next, simulate the transaction.val simulatedResult = portal.api.simulateTransaction(transaction)// Finally, handle or display the simulation results.when { simulatedResult.requestError !=null-> {print("Request error: ${simulatedResult.requestError.message}") } simulatedResult.error !=null-> {print("Transaction will have error: ${simulatedResult.error.message}") }else-> {print("Simulated transaction results: ${simulatedResult.changes}") } }}
This function will return the results of the transaction simulation:
changes: An array detailing all the potential transaction outcomes. Each change has the following structure:
amount: The amount being transferred.
assetType: The type of asset being dealt with (NATIVE or ERC20 or ERC721 or ERC1155 or SPECIAL_NFT).
changeType: The type of change (APPROVE or TRANSFER).
contractAddress: Address of the contract being interacted with (null for native transactions).
decimals: Decimals used in the asset.
from: The sender address.
name: The name of the asset.
rawAmount: The unformatted amount being transferred.
symbol: The asset's symbol.
to: The receiver's address.
tokenId: An identifier for tokens (null for assets that are not tokens).
gasUsed: The gas used by the transaction.
error: An object that contains the error message if the transaction would fail upon execution.
requestError: An object that contains the error message if there was an issue with the request, such as a malformed transaction argument being provided.
By incorporating transaction simulations, you can provide your users with a preview of the transaction outcomes and preemptively detect and handle errors, ensuring a smoother user experience.
And now you are simulating transactions with Portal! 🙌 🚀 Next, we'll explore how to back up the wallet for recovery if the user loses device access.