CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-ant-design--web3

Efficient React components for building Web3 dApps with comprehensive wallet integration and blockchain UI components.

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

hooks.mddocs/

React Hooks

React hooks for accessing Web3 state and functionality from any component within a Web3ConfigProvider context.

Capabilities

useAccount

Hook to access the current connected account information including address, name, avatar, and connection status.

/**
 * Hook to access the current connected account information
 * @returns Object containing account information
 */
function useAccount(): Pick<ConfigConsumerProps, 'account'>;

interface ConfigConsumerProps {
  account?: Account;
}

interface Account {
  address: string;
  name?: string;
  avatar?: string;
  addresses?: [`0x${string}`, ...`0x${string}`[]] | readonly `0x${string}`[];
  status?: ConnectStatus;
}

const enum ConnectStatus {
  Connected = 'connected',
  Disconnected = 'disconnected',
  Signed = 'signed',
}

Usage Examples:

import { useAccount } from "@ant-design/web3";

function AccountDisplay() {
  const { account } = useAccount();
  
  if (!account) {
    return <div>No account connected</div>;
  }
  
  return (
    <div>
      <h3>Connected Account</h3>
      <p>Address: {account.address}</p>
      {account.name && <p>Name: {account.name}</p>}
      <p>Status: {account.status}</p>
      {account.avatar && (
        <img src={account.avatar} alt="Avatar" width={32} height={32} />
      )}
      {account.addresses && (
        <div>
          <h4>Multiple Addresses:</h4>
          <ul>
            {account.addresses.map((addr, index) => (
              <li key={index}>{addr}</li>
            ))}
          </ul>
        </div>
      )}
    </div>
  );
}

// Conditional rendering based on connection status
function ConditionalContent() {
  const { account } = useAccount();
  
  switch (account?.status) {
    case 'connected':
      return <div>Wallet connected: {account.address}</div>;
    case 'signed':
      return <div>Wallet signed in: {account.address}</div>;
    case 'disconnected':
    default:
      return <div>Please connect your wallet</div>;
  }
}

// Using account in effects
function AccountWatcher() {
  const { account } = useAccount();
  
  useEffect(() => {
    if (account?.address) {
      console.log('Account changed:', account.address);
      // Fetch user data, update UI, etc.
      fetchUserData(account.address);
    }
  }, [account?.address]);
  
  return <div>Watching account changes...</div>;
}

useConnection

Hook to access wallet connection and disconnection functions for programmatic wallet management.

/**
 * Hook to access wallet connection and disconnection functions
 * @returns Object containing connect and disconnect functions
 */
function useConnection(): Pick<ConfigConsumerProps, 'connect' | 'disconnect'>;

interface ConfigConsumerProps {
  connect?: (wallet?: Wallet, options?: ConnectOptions) => Promise<void | Account>;
  disconnect?: () => Promise<void>;
}

interface ConnectOptions {
  connectType?: 'extension' | 'qrCode' | 'openMobile';
}

interface Wallet extends WalletMetadata {
  _standardWallet?: any;
  _isMobileWallet?: boolean;
  hasWalletReady?: () => Promise<boolean>;
  hasExtensionInstalled?: () => Promise<boolean>;
  getQrCode?: () => Promise<{ uri: string }>;
  customQrCodePanel?: boolean;
}

Usage Examples:

import { useConnection } from "@ant-design/web3";

function CustomConnectButton() {
  const { connect, disconnect } = useConnection();
  const { account } = useAccount();
  
  const handleConnect = async () => {
    try {
      const result = await connect();
      console.log('Connected:', result);
    } catch (error) {
      console.error('Connection failed:', error);
    }
  };
  
  const handleDisconnect = async () => {
    try {
      await disconnect();
      console.log('Disconnected successfully');
    } catch (error) {
      console.error('Disconnection failed:', error);
    }
  };
  
  if (account) {
    return (
      <button onClick={handleDisconnect}>
        Disconnect {account.address}
      </button>
    );
  }
  
  return (
    <button onClick={handleConnect}>
      Connect Wallet
    </button>
  );
}

// Connect to specific wallet
function WalletSpecificConnect() {
  const { connect } = useConnection();
  
  const connectToMetaMask = async () => {
    const metaMaskWallet = {
      name: "MetaMask",
      remark: "Connect with MetaMask",
      icon: "metamask-icon",
      extensions: [{
        key: 'Chrome',
        browserIcon: 'chrome',
        browserName: 'Chrome',
        link: 'https://metamask.io',
        description: 'MetaMask extension'
      }]
    };
    
    try {
      await connect(metaMaskWallet, { connectType: 'extension' });
    } catch (error) {
      console.error('MetaMask connection failed:', error);
    }
  };
  
  return <button onClick={connectToMetaMask}>Connect MetaMask</button>;
}

// Connection with loading state
function ConnectWithLoading() {
  const { connect, disconnect } = useConnection();
  const { account } = useAccount();
  const [loading, setLoading] = useState(false);
  
  const handleConnect = async () => {
    setLoading(true);
    try {
      await connect();
    } catch (error) {
      console.error('Connection error:', error);
    } finally {
      setLoading(false);
    }
  };
  
  return (
    <button onClick={handleConnect} disabled={loading}>
      {loading ? 'Connecting...' : account ? 'Connected' : 'Connect'}
    </button>
  );
}

useProvider

Hook to access the complete Web3 provider context with optional prop overrides for customization and testing.

/**
 * Hook to access the Web3 provider context with optional prop overrides
 * @param props - Optional props to override context values
 * @returns Complete provider interface with merged context and props
 */
function useProvider(
  props?: UniversalWeb3ProviderInterface
): UniversalWeb3ProviderInterface;

interface UniversalWeb3ProviderInterface {
  account?: Account;
  chain?: Chain;
  balance?: Balance;
  availableWallets?: Wallet[];
  availableChains?: Chain[];
  extendsContextFromParent?: boolean;
  addressPrefix?: string | false;
  connect?: (wallet?: Wallet, options?: ConnectOptions) => Promise<void | Account>;
  disconnect?: () => Promise<void>;
  switchChain?: (chain: Chain) => Promise<void>;
  getNFTMetadata?: (params: { address: string; tokenId?: bigint }) => Promise<NFTMetadata>;
  sign?: SignConfig;
}

interface Balance {
  value?: bigint;
  coverAddress?: boolean;
  name?: string;
  symbol?: string;
  icon?: React.ReactNode;
  decimal?: number;
}

interface Chain {
  id: ChainIds | number;
  name: string;
  type?: ChainType;
  icon?: React.ReactNode;
  browser?: {
    icon?: React.ReactNode;
    getBrowserLink?: (address: string, type: BrowserLinkType) => string;
  };
  nativeCurrency?: BalanceMetadata & { name: string };
}

Usage Examples:

import { useProvider } from "@ant-design/web3";

// Access full provider context
function ProviderInfo() {
  const provider = useProvider();
  
  return (
    <div>
      <h3>Provider Information</h3>
      <p>Current Chain: {provider.chain?.name}</p>
      <p>Account: {provider.account?.address}</p>
      <p>Balance: {provider.balance?.value?.toString()}</p>
      <p>Available Wallets: {provider.availableWallets?.length}</p>
      <p>Available Chains: {provider.availableChains?.length}</p>
    </div>
  );
}

// Override provider values
function CustomProvider() {
  const customChain = {
    id: 1337,
    name: "Local Testnet",
    type: ChainType.EVM
  };
  
  const provider = useProvider({
    chain: customChain,
    addressPrefix: "local:"
  });
  
  return (
    <div>
      <p>Using custom chain: {provider.chain?.name}</p>
      <p>Address prefix: {provider.addressPrefix}</p>
    </div>
  );
}

// Chain switching functionality
function ChainSwitcher() {
  const provider = useProvider();
  
  const switchToPolygon = async () => {
    const polygonChain = {
      id: 137,
      name: "Polygon",
      type: ChainType.EVM
    };
    
    try {
      await provider.switchChain?.(polygonChain);
      console.log('Switched to Polygon');
    } catch (error) {
      console.error('Chain switch failed:', error);
    }
  };
  
  return (
    <div>
      <p>Current: {provider.chain?.name}</p>
      <button onClick={switchToPolygon}>Switch to Polygon</button>
    </div>
  );
}

// NFT metadata fetching
function NFTLoader() {
  const provider = useProvider();
  const [metadata, setMetadata] = useState(null);
  
  const loadNFT = async () => {
    if (provider.getNFTMetadata) {
      try {
        const nftData = await provider.getNFTMetadata({
          address: "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
          tokenId: BigInt(1)
        });
        setMetadata(nftData);
      } catch (error) {
        console.error('NFT load failed:', error);
      }
    }
  };
  
  return (
    <div>
      <button onClick={loadNFT}>Load NFT</button>
      {metadata && <p>NFT Name: {metadata.name}</p>}
    </div>
  );
}

useNFT

Hook for loading NFT metadata with automatic caching, loading states, and error handling.

/**
 * Hook for loading NFT metadata
 * @param address - NFT contract address
 * @param tokenId - NFT token ID
 * @param getNFTMetadata - Custom metadata fetcher function
 * @returns Object containing loading state, metadata, and error
 */
function useNFT(
  address?: string,
  tokenId?: bigint | number,
  getNFTMetadata?: Web3ConfigProviderProps['getNFTMetadata']
): { loading: boolean; metadata: NFTMetadata; error?: Error };

interface NFTMetadata {
  name?: string;
  description?: string;
  image?: string;
  dna?: string;
  edition?: string | number;
  date?: number;
  attributes?: Array<{
    trait_type?: string;
    value?: string;
  }>;
  compiler?: string;
}

Usage Examples:

import { useNFT } from "@ant-design/web3";

// Basic NFT loading
function NFTDisplay() {
  const { loading, metadata, error } = useNFT(
    "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
    BigInt(1)
  );
  
  if (loading) return <div>Loading NFT...</div>;
  if (error) return <div>Error: {error.message}</div>;
  
  return (
    <div>
      <h3>{metadata.name}</h3>
      <p>{metadata.description}</p>
      {metadata.image && (
        <img src={metadata.image} alt={metadata.name} width={300} />
      )}
      {metadata.attributes && (
        <div>
          <h4>Attributes:</h4>
          {metadata.attributes.map((attr, index) => (
            <div key={index}>
              {attr.trait_type}: {attr.value}
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

// Dynamic NFT loading with state
function DynamicNFTViewer() {
  const [contractAddress, setContractAddress] = useState("");
  const [tokenId, setTokenId] = useState("");
  
  const { loading, metadata, error } = useNFT(
    contractAddress || undefined,
    tokenId ? BigInt(tokenId) : undefined
  );
  
  return (
    <div>
      <input 
        placeholder="Contract Address"
        value={contractAddress}
        onChange={(e) => setContractAddress(e.target.value)}
      />
      <input 
        placeholder="Token ID"
        value={tokenId}
        onChange={(e) => setTokenId(e.target.value)}
      />
      
      {loading && <div>Loading...</div>}
      {error && <div>Error: {error.message}</div>}
      {metadata.name && (
        <div>
          <h3>{metadata.name}</h3>
          {metadata.image && <img src={metadata.image} width={200} />}
        </div>
      )}
    </div>
  );
}

// Custom metadata fetcher
function CustomNFTLoader() {
  const customFetcher = async ({ address, tokenId }) => {
    const response = await fetch(`/api/nft/${address}/${tokenId}`);
    if (!response.ok) throw new Error('Failed to fetch NFT');
    return response.json();
  };
  
  const { loading, metadata, error } = useNFT(
    "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
    BigInt(1234),
    customFetcher
  );
  
  return (
    <div>
      {loading ? "Loading..." : metadata.name || "No NFT data"}
    </div>
  );
}

// NFT with fallback handling
function RobustNFTDisplay() {
  const { loading, metadata, error } = useNFT(
    "0xbc4ca0eda7647a8ab7c2061c2e118a18a936f13d",
    BigInt(9999)
  );
  
  if (loading) {
    return (
      <div className="nft-loading">
        <div className="spinner" />
        <span>Loading NFT metadata...</span>
      </div>
    );
  }
  
  if (error) {
    return (
      <div className="nft-error">
        <h4>Failed to load NFT</h4>
        <p>{error.message}</p>
        <button onClick={() => window.location.reload()}>
          Retry
        </button>
      </div>
    );
  }
  
  return (
    <div className="nft-card">
      <img 
        src={metadata.image || '/placeholder-nft.png'} 
        alt={metadata.name || 'NFT'}
        onError={(e) => {
          e.target.src = '/placeholder-nft.png';
        }}
      />
      <h3>{metadata.name || 'Unnamed NFT'}</h3>
      <p>{metadata.description || 'No description available'}</p>
    </div>
  );
}

Hook Integration Patterns

Combined Hook Usage

import { useAccount, useConnection, useProvider } from "@ant-design/web3";

function WalletManager() {
  const { account } = useAccount();
  const { connect, disconnect } = useConnection();
  const provider = useProvider();
  
  const handleChainSwitch = async (chainId: number) => {
    const targetChain = provider.availableChains?.find(
      chain => chain.id === chainId
    );
    
    if (targetChain && provider.switchChain) {
      await provider.switchChain(targetChain);
    }
  };
  
  return (
    <div>
      {account ? (
        <div>
          <p>Connected: {account.address}</p>
          <p>Chain: {provider.chain?.name}</p>
          <button onClick={() => disconnect()}>Disconnect</button>
          <select onChange={(e) => handleChainSwitch(Number(e.target.value))}>
            {provider.availableChains?.map(chain => (
              <option key={chain.id} value={chain.id}>{chain.name}</option>
            ))}
          </select>
        </div>
      ) : (
        <button onClick={() => connect()}>Connect Wallet</button>
      )}
    </div>
  );
}

Testing with Hooks

import { renderHook } from '@testing-library/react';
import { useProvider } from "@ant-design/web3";

// Test hook with mock data
const wrapper = ({ children }) => (
  <Web3ConfigProvider
    account={{ address: "0x123", status: "connected" }}
    chain={{ id: 1, name: "Ethereum" }}
  >
    {children}
  </Web3ConfigProvider>
);

const { result } = renderHook(() => useProvider(), { wrapper });
expect(result.current.account?.address).toBe("0x123");

docs

address-display.md

common-types.md

configuration.md

crypto-components.md

hooks.md

index.md

nft-components.md

payment.md

wallet-connection.md

tile.json