Skip to content

Quickstart - For Wallets & WaaS

Integrate apps into a wallet

1. Install the SDK

npm install universal-portability

2. Set Up Provider

Wrap your application with the UniversalPortabilityProvider:

import { UniversalPortabilityProvider } from 'universal-portability';
 
function App() {
  return (
    <WagmiProvider config={wagmiConfig}>
      <UniversalPortabilityProvider>
        {/* Your app */}
      </UniversalPortabilityProvider>
    </WagmiProvider>
  );
}

3. Implement Message Handlers

Your wallet needs to listen for events from Interspace—such as requests to connect, sign a message, or approve a transaction.

Create these two hooks to handle communication between your wallet and embedded dApps:

src/hooks/useMessageHandler.ts

import { useEffect } from 'react';
import { useUniversalPortability } from 'universal-portability';
import { sendTransaction, signMessage } from '@wagmi/core';
import { config } from '../wagmi';
import { hexToString } from 'viem';
 
export interface MessageHandlerConfig {
  walletAddress: string;
  chainId: number;
}
 
export function useMessageHandler({ walletAddress, chainId }: MessageHandlerConfig) {
  const { sendMessageToIFrame } = useUniversalPortability();
 
  useEffect(() => {
    const handleMessage = async (event: MessageEvent) => {
      const { type, payload, requestId } = event.data;
 
      try {
        switch (type) {
          case 'INTERSPACE_CONNECT_REQUEST':
            sendMessageToIFrame(
              {
                type: 'INTERSPACE_CONNECT_RESPONSE',
                payload: {
                  address: walletAddress,
                  chainId,
                  isConnected: true
                }
              }
            );
            break;
 
          case 'SIGN_MESSAGE_REQUEST':
            // Handle message signing
            break;
 
          case 'TRANSACTION_REQUEST':
            // Handle transaction requests
            break;
        }
      } catch (error: any) {
        // Error handling
      }
    };
 
    window.addEventListener('message', handleMessage);
    return () => window.removeEventListener('message', handleMessage);
  }, [walletAddress, chainId, sendMessageToIFrame]);
}

src/hooks/usePortHandler.ts

import { useAccount, useChainId } from 'wagmi';
import { useMessageHandler } from './useMessageHandler';
 
export function usePortHandler() {
  const { address } = useAccount();
  const chainId = useChainId();
 
  useMessageHandler({
    walletAddress: address!,
    chainId: chainId!
  });
 
  return {
    isReady: Boolean(address && chainId)
  };
}

4. Create dApp Store Container

Interspace can serve as your "dApp store" aggregator. You can display all available apps, letting users pick which to launch. For instance:

import { Port, usePortableApps } from 'universal-portability';
 
function DAppStoreContainer() {
  const { apps } = usePortableApps(); // array of dApp metadata
 
  return (
    <div className="dapp-grid">
      {apps.map(app => (
        <div key={app.id} className="dapp-card">
          <img src={app.logo} alt={app.name} />
          <h3>{app.name}</h3>
          <button onClick={() => navigateToApp(app)}>
            Launch {app.name}
          </button>
        </div>
      ))}
    </div>
  );
}

5. Render dApp Interface

When the user selects a dApp, you embed it:

import { Port } from 'universal-portability';
import { useAccount, useChainId } from 'wagmi';
 
import { usePortHandler } from '../hooks/usePortHandler';
 
function AppContainer({ app }) {
  const rpcURL = process.env.RPC_URL;
  const { address } = useAccount();
 
  // enable postMessage communication
  usePortHandler();
 
  return (
    <Port
      src={`https://interspace.fi/apps/${app.slug}`}
      address={address}
      rpcUrl={rpcURL}
      height="400px"
      width="800px"
    />
  );
}

Message Protocol

The SDK uses a secure postMessage protocol with these main events:

  • INTERSPACE_CONNECT_REQUEST: Initial wallet connection request
  • SIGN_MESSAGE_REQUEST: Request to sign a message
  • TRANSACTION_REQUEST: Request to send a transaction
  • SWITCH_CHAIN_REQUEST: Request to switch chain
  • *_RESPONSE: Corresponding response events

All sensitive operations (signing, approvals) are handled by your wallet's existing security infrastructure, ensuring a safe and consistent user experience.

Contact Us