Optimizing Decentralized Apps UX with Milestones: A Significantly Accelerated Finality Solution

The recent launch of Milestones on the Mainnet has introduced a game-changing feature for dApp developers. This new capability significantly improves the user experience by providing faster and more definite transaction finality, reducing the likelihood of chain reorganization. In this post, we’ll explore how dApp developers can leverage this new feature, leaving behind the sometimes lengthy wait times associated with transaction finalities prior to the launch of Milestones.

Before we delve into the details of how to utilize Milestones to achieve a vastly improved UX in your web3 project, you are welcome to explore the specifics of Milestones mechanism via the following links:

Traditional Method

The traditional method of ensuring transaction finality involves sending a transaction to the network, fetching its block number, and then waiting for 256 block confirmations by calculating the difference between the latest block number and your transaction block number, and comparing it with 256 block confirmations. Here’s a code snippet that illustrates this process:

const isConfirmed = async (provider, txHash) => {
try {
// Get the transaction hash
const tx = await provider.getTransaction(txHash)
// Check if the transaction and transaction block number exist
if (!tx || !tx.blockNumber) return false
// Get the latest block number from the network
const lastestBlockNumber = await provider.getBlockNumber()
// Calculate the difference between the latest block number
// and your transaction block number, and compare it with 256 block confirmations
if (lastestBlockNumber - tx.blockNumber >= 256)
{
console.log("Your transaction block has been confirmed after 256 blocks");
return true
}
return false
} catch (error) {
console.log(`Error in isConfirmed: ${error}`)
return false
}
}

Drawbacks:

The main drawback of the traditional method was its reliance on waiting for 256 blocks, which typically took around 10+ minutes on Polygon PoS. The waiting time was subject to network congestion and traffic, sometimes exceeding the expected duration, resulting in a subpar developer and user experience.

Milestones Method

To tackle the block reorganization issue and elevate user experience significantly, developers can leverage Milestones by employing the eth-JSON RPC method eth_getBlockByNumber. By specifying the first parameter (i.e. block number) as ‘finalized’, one can retrieve the latest finalized block number. Compare this number with a transaction’s block number to determine whether the transaction has achieved finality, ensuring a seamless user experience.

Here’s a code snippet you can reference:

// Code snippet for eth-JSON RPC method
import axios from "axios";
import { MATIC_RPC_URL } from "../utils/constants";
import { msToMinAndSec } from "../utils/msToMinAndSec";
// Fetch finality data using eth-JSON RPC method
export async function ethJsonRpcMethod(yourBlock: number): Promise<void> {
	try {
		console.log("Waiting for your block to get finalized...\n");
		// Flag for block finality
		let finalised: boolean = false;
		// Store the last known finalized block value
		let lastFinalizedBlock: number | null = null;
		while (!finalised) {
			const response = (
				await axios.post(MATIC_RPC_URL, {
				jsonrpc: "2.0",
				id: 1,
				method: "eth_getBlockByNumber",
				params: ["finalized", true],
			})).data;
		// Convert hex to number
		lastFinalizedBlock = parseInt(response.result.number.toString(), 16);
		// Check if your block has achieved finality
		if (lastFinalizedBlock >= yourBlock) {
			finalised = true;
		}
	} catch (error) {
		console.log(`Error at ethJsonRpcMethod: ${error}`);
		process.exit(1);
	}
}

By utilizing the above approach, dApp developers can greatly enhance user experience by minimizing the wait time for transaction finality, often achieving it within 1-2 minutes.

Additional Code and Disclaimers:

For further code references, you can visit the GitHub repository where these code snippets were sourced. It is essential to be aware that the code available in the mentioned repository has not undergone an official audit and is not recommended for production usage. Please exercise caution and use it at your own discretion.