Skip to content
Tolinku
Tolinku
Sign In Start Free
Deep Linking · · 4 min read

Deep Linking and Web3: Connecting Decentralized Apps

By Tolinku Staff
|
Tolinku industry trends dashboard screenshot for deep linking blog posts

Web3 applications (decentralized apps, wallets, DeFi protocols, NFT marketplaces) have unique deep linking challenges. Users navigate between wallet apps, dApps, and web interfaces constantly. A swap on a DeFi protocol requires opening a wallet app to sign a transaction, then returning to the dApp. An NFT purchase links from a marketplace to a wallet for payment, then back to the marketplace for confirmation.

This guide covers how deep linking works in the Web3 ecosystem. For deep linking in super apps, see deep linking for super apps. For crypto-specific deep linking patterns, see deep links for cryptocurrency apps.

The Web3 Deep Linking Landscape

Flow From To Context Needed
Wallet connect dApp (web/app) Wallet app Session, chain, dApp metadata
Transaction signing dApp Wallet Transaction data, callback URL
Token viewing Marketplace Wallet Token ID, contract address
dApp browsing Wallet browser dApp Wallet address, chain
Payment request Merchant app Wallet Amount, recipient, memo

WalletConnect Protocol

WalletConnect is the most widely used standard for connecting dApps to wallet apps. It uses deep links as the transport:

wc:abc123@2?relay-protocol=irn&symKey=xyz

This URI launches the wallet app, which establishes an encrypted session with the dApp. The deep link carries the session parameters.

// dApp: initiate WalletConnect session
import { Core } from '@walletconnect/core';
import { Web3Wallet } from '@walletconnect/web3wallet';

const core = new Core({ projectId: 'YOUR_PROJECT_ID' });

// Generate connection URI (this is the deep link)
const { uri, approval } = await signClient.connect({
  requiredNamespaces: {
    eip155: {
      methods: ['eth_sendTransaction', 'personal_sign'],
      chains: ['eip155:1'],
      events: ['accountsChanged']
    }
  }
});

// Open wallet app with the URI
const walletDeepLink = `https://metamask.app.link/wc?uri=${encodeURIComponent(uri)}`;
window.location.href = walletDeepLink;

MetaMask

MetaMask supports deep links for common actions:

// Open MetaMask and connect
metamask://wc?uri=wc:abc123@2...

// Open a specific dApp in MetaMask's browser
https://metamask.app.link/dapp/uniswap.org

// Send transaction
metamask://send/0xRecipientAddress?value=1e18

Most wallets use Universal Links for cross-platform compatibility:

https://metamask.app.link/...     (MetaMask)
https://link.trustwallet.com/...  (Trust Wallet)
https://phantom.app/ul/...        (Phantom, Solana)
https://rainbow.me/...            (Rainbow)

Link directly to specific tokens, collections, or profiles:

/assets/{chain}/{contract}/{tokenId}     → specific NFT
/collection/{slug}                       → collection page
/profile/{address}                       → user profile
/activity/{address}                      → transaction history

Link to specific pools, swaps, or positions:

/swap?inputCurrency=ETH&outputCurrency=0xUSDC&chain=1
/pool/{poolAddress}
/positions/{positionId}
/farm/{farmId}

Web3 deep link pages should work without a wallet connected:

<!-- NFT detail page - works for everyone -->
<div class="nft-detail">
  <img src="/images/nft-preview.jpg" alt="NFT #1234">
  <h1>CryptoArt #1234</h1>
  <p>Current price: 0.5 ETH</p>

  <!-- For users with wallet -->
  <button id="buyBtn" onclick="connectAndBuy()">Buy Now</button>

  <!-- For users without wallet -->
  <div id="noWallet" style="display:none;">
    <p>You need a wallet to purchase this NFT.</p>
    <a href="https://metamask.io/download/">Get MetaMask</a>
  </div>
</div>

<script>
  if (typeof window.ethereum === 'undefined') {
    document.getElementById('buyBtn').style.display = 'none';
    document.getElementById('noWallet').style.display = 'block';
  }
</script>

EIP-681: Payment Request URLs

EIP-681 defines a standard URL format for Ethereum payment requests:

ethereum:0xRecipientAddress@1/transfer?
  address=0xTokenContract&
  uint256=1000000&
  value=0

Components:

  • ethereum: scheme
  • 0xRecipientAddress target address
  • @1 chain ID (Ethereum mainnet)
  • /transfer function name
  • Query parameters for function arguments

Different blockchains use different URL schemes:

Chain Deep Link Format
Ethereum ethereum:0xAddress?value=1e18
Bitcoin bitcoin:address?amount=0.001
Solana solana:address?amount=1&spl-token=USDC
Polygon ethereum:0xAddress@137?value=1e18
// iOS wallet app: handle EIP-681 payment request
func handlePaymentURL(_ url: URL) {
    guard url.scheme == "ethereum" else { return }

    let components = url.pathComponents
    let address = url.host // recipient address
    let chainId = url.port // chain ID (e.g., 1 for mainnet)

    let params = url.queryParameters
    let value = params["value"] // ETH amount in wei
    let gasLimit = params["gasLimit"]

    // Show transaction confirmation screen
    showTransactionConfirmation(
        to: address,
        value: value,
        chain: chainId ?? 1,
        gasLimit: gasLimit
    )
}

The Flow

Deep links can gate content based on token ownership:

User taps deep link → https://yourapp.com/exclusive/holders-only
  → Web page checks wallet connection
    → Wallet connected and owns required token → show content
    → Wallet not connected → prompt to connect
    → Connected but does not own token → show "token required" message

Implementation

async function checkTokenGate(url) {
  const path = new URL(url).pathname;
  const gateConfig = await getGateConfig(path); // which token is required

  if (!gateConfig) {
    // No gate on this content
    showContent(path);
    return;
  }

  const wallet = await connectWallet();
  if (!wallet) {
    showConnectPrompt(url);
    return;
  }

  const ownsToken = await checkTokenOwnership(
    wallet.address,
    gateConfig.contractAddress,
    gateConfig.chainId,
    gateConfig.minBalance
  );

  if (ownsToken) {
    showContent(path);
  } else {
    showTokenRequired(gateConfig);
  }
}

Tolinku handles URL routing for Web3 applications. Configure routes for your dApp pages in the Tolinku dashboard, and Tolinku routes users to your mobile app (for native dApp experiences) or web fallback. The web fallback can include wallet connection prompts and transaction initiation.

For more on industry trends, see the future of mobile deep linking.

Get deep linking tips in your inbox

One email per week. No spam.

Ready to add deep linking to your app?

Set up Universal Links, App Links, deferred deep linking, and analytics in minutes. Free to start.