Token Migration UI Development

We design and develop full-cycle blockchain solutions: from smart contract architecture to launching DeFi protocols, NFT marketplaces and crypto exchanges. Security audits, tokenomics, integration with existing infrastructure.
Showing 1 of 1 servicesAll 1306 services
Token Migration UI Development
Simple
~2-3 business days
FAQ
Blockchain Development Services
Blockchain Development Stages
Latest works
  • image_website-b2b-advance_0.png
    B2B ADVANCE company website development
    1214
  • image_web-applications_feedme_466_0.webp
    Development of a web application for FEEDME
    1161
  • image_websites_belfingroup_462_0.webp
    Website development for BELFINGROUP
    852
  • image_ecommerce_furnoro_435_0.webp
    Development of an online store for the company FURNORO
    1041
  • image_logo-advance_0.png
    B2B Advance company logo design
    561
  • image_crm_enviok_479_0.webp
    Development of a web application for Enviok
    823

Token Migration UI Development

Token migration is one of the few cases in Web3 where UX is critical from a security perspective. A user approves a contract they may not fully trust. The UI task: make every step transparent, show exactly what happens to the tokens, and prevent the user from clicking "Approve" without understanding the consequences.

Migration flow

Standard scheme: old token (v1) → new token (v2) through a migrator contract. The contract accepts v1, burns or locks it, mints v2 in a 1:1 ratio (or another).

The UI should cover three transactions:

  1. approve(migratorContract, amount) on the v1 token
  2. migrate(amount) on the migrator contract
  3. (optional) add v2 to MetaMask via wallet_watchAsset
async function migrateTokens(amount: bigint) {
  // Step 1: check current allowance
  const currentAllowance = await v1Token.allowance(userAddress, MIGRATOR_ADDRESS);
  
  if (currentAllowance < amount) {
    const approveTx = await v1Token.approve(MIGRATOR_ADDRESS, amount);
    await approveTx.wait();
  }
  
  // Step 2: migration
  const migrateTx = await migrator.migrate(amount);
  const receipt = await migrateTx.wait();
  
  return receipt;
}

Key UI components

Balance display before/after

Show the user explicitly what will happen: how much v1 will be deducted, how much v2 they'll receive. If the rate isn't 1:1 — especially important.

function MigrationPreview({ amount, exchangeRate }: Props) {
  const v2Amount = (BigInt(amount) * BigInt(exchangeRate * 100)) / 100n;
  
  return (
    <div className="migration-preview">
      <div className="from">
        <span>Giving: {formatEther(amount)} {V1_SYMBOL}</span>
      </div>
      <ArrowIcon />
      <div className="to">
        <span>Receiving: {formatEther(v2Amount)} {V2_SYMBOL}</span>
      </div>
    </div>
  );
}

Stepper with transaction states

Each step — approve, migrate, done — is displayed with explicit status: waiting, pending, confirmed, error.

type MigrationStep = 'idle' | 'approving' | 'approved' | 'migrating' | 'done' | 'error';

const stepConfig = {
  idle:      { label: 'Ready for migration', icon: 'clock' },
  approving: { label: 'Confirming approval...', icon: 'spinner' },
  approved:  { label: 'Approval confirmed', icon: 'check' },
  migrating: { label: 'Migrating tokens...', icon: 'spinner' },
  done:      { label: 'Migration complete', icon: 'check-circle' },
  error:     { label: 'Error', icon: 'x-circle' },
};

Link to Etherscan for each transaction as soon as the txHash is received — don't wait for confirmation.

Infinite approve warning

If the contract requests type(uint256).max approve — explicitly tell the user. Offer a choice: exact amount or unlimited. For migration, the right choice is exact amount — the user is migrating a specific quantity.

Handling edge cases

Partial migration: user migrated part of the tokens, returned later. Show current v1 and v2 balances, remainder to migrate.

Migration deadline: migrator contracts often have a deadline after which migration is impossible. If a deadline is set — show countdown, warn in advance (7 days, 24 hours).

Revert reasons: if a transaction reverts — try to decode the reason via parseRevertReason and show a human-readable message instead of "Transaction failed".

function parseRevertReason(error: any): string {
  const message = error?.info?.error?.message || error?.message || '';
  if (message.includes('Migration ended')) return 'Migration period has ended';
  if (message.includes('Insufficient balance')) return 'Insufficient tokens';
  if (message.includes('user rejected')) return 'Transaction rejected by user';
  return 'Unknown error. Try again later.';
}

Timeline estimates

Full migration UI with stepper, balances, transactions, and error handling — 2-3 days.