npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@fliidotdev/blinks-react

v0.1.3

Published

React components for Blinks SDK

Readme

@fliidotdev/blinks-react

React components and hooks for building Solana Blinks interfaces. Create beautiful, interactive blockchain experiences with pre-built components and custom hooks.

Installation

npm install @fliidotdev/blinks-react @fliidotdev/blinks-core
# or
yarn add @fliidotdev/blinks-react @fliidotdev/blinks-core
# or
pnpm add @fliidotdev/blinks-react @fliidotdev/blinks-core

Features

  • Pre-built Components: Ready-to-use Blink components
  • Custom Hooks: React hooks for blockchain interactions
  • Wallet Integration: Seamless wallet connection UI
  • Responsive Design: Mobile-first, accessible components
  • Theme Support: Customizable themes and styles
  • TypeScript: Full type safety and IntelliSense
  • SSR Compatible: Works with Next.js and other SSR frameworks

Quick Start

import { BlinkProvider, BlinkButton, useWallet } from '@fliidotdev/blinks-react';
import { WalletAdapterNetwork } from '@solana/wallet-adapter-base';

function App() {
  return (
    <BlinkProvider network={WalletAdapterNetwork.Mainnet}>
      <PaymentButton />
    </BlinkProvider>
  );
}

function PaymentButton() {
  const { connected, publicKey } = useWallet();
  
  return (
    <BlinkButton
      action={{
        type: 'transfer',
        recipient: 'ABC...XYZ',
        amount: 0.1
      }}
      onSuccess={(signature) => console.log('Success!', signature)}
      onError={(error) => console.error('Failed:', error)}
    >
      Pay 0.1 SOL
    </BlinkButton>
  );
}

Components

<BlinkProvider>

Root provider component that manages wallet connection and blockchain state.

import { BlinkProvider } from '@fliidotdev/blinks-react';

<BlinkProvider
  network={WalletAdapterNetwork.Mainnet}
  endpoint="https://api.mainnet-beta.solana.com"
  wallets={[phantom, solflare]}
>
  {children}
</BlinkProvider>

Props:

  • network - Solana network to connect to
  • endpoint - RPC endpoint URL
  • wallets - Array of wallet adapters
  • autoConnect - Auto-connect to wallet (default: false)
  • theme - UI theme configuration

<BlinkButton>

Interactive button component for executing Blink actions.

<BlinkButton
  action={{
    type: 'transfer',
    recipient: walletAddress,
    amount: 1.5
  }}
  variant="primary"
  size="large"
  loading={isProcessing}
  disabled={!connected}
  onSuccess={handleSuccess}
  onError={handleError}
>
  Send 1.5 SOL
</BlinkButton>

Props:

  • action - Blink action configuration
  • variant - Button style variant
  • size - Button size
  • loading - Loading state
  • disabled - Disabled state
  • onSuccess - Success callback
  • onError - Error callback

<WalletConnect>

Wallet connection interface with multi-wallet support.

<WalletConnect
  showBalance={true}
  showDisconnect={true}
  buttonProps={{
    variant: 'outline',
    size: 'medium'
  }}
/>

<TransactionStatus>

Display transaction status with automatic updates.

<TransactionStatus
  signature={txSignature}
  showExplorer={true}
  autoHide={5000}
/>

<BlinkCard>

Card component for displaying Blink information.

<BlinkCard
  title="Premium Subscription"
  description="Subscribe for exclusive features"
  price={5}
  currency="SOL"
  action={subscribeAction}
  image="/subscription.png"
  badge="Popular"
/>

<ActionList>

List of executable actions with icons and descriptions.

<ActionList
  actions={[
    {
      type: 'transfer',
      label: 'Send Payment',
      icon: '💸',
      amount: 10
    },
    {
      type: 'swap',
      label: 'Swap Tokens',
      icon: '🔄',
      fromToken: 'SOL',
      toToken: 'USDC'
    }
  ]}
  onSelect={handleActionSelect}
/>

Hooks

useWallet

Access wallet connection state and methods.

const {
  connected,
  connecting,
  publicKey,
  wallet,
  connect,
  disconnect,
  signTransaction,
  signMessage
} = useWallet();

useBlink

Execute Blink actions programmatically.

const { execute, executing, error } = useBlink();

const handleTransfer = async () => {
  const signature = await execute({
    type: 'transfer',
    recipient: recipientAddress,
    amount: 1.0
  });
};

useBalance

Get wallet balance and token balances.

const { balance, tokens, loading, refresh } = useBalance();

// SOL balance
console.log(`Balance: ${balance} SOL`);

// Token balances
tokens.forEach(token => {
  console.log(`${token.symbol}: ${token.balance}`);
});

useTransaction

Monitor transaction status.

const { status, confirmations, error } = useTransaction(signature);

if (status === 'confirmed') {
  console.log('Transaction confirmed!');
}

useAction

Create and manage Blink actions.

const action = useAction({
  type: 'custom',
  handler: async (params) => {
    // Custom logic
    return { success: true };
  }
});

<button onClick={() => action.execute()}>
  Execute Custom Action
</button>

Styling

Theme Configuration

import { BlinkProvider, createTheme } from '@fliidotdev/blinks-react';

const customTheme = createTheme({
  colors: {
    primary: '#7B3FF2',
    secondary: '#2FC5CC',
    success: '#00D395',
    error: '#FF6B6B',
    background: '#1A1B23',
    surface: '#2D2E3F',
    text: '#FFFFFF'
  },
  fonts: {
    body: 'Inter, sans-serif',
    heading: 'Poppins, sans-serif'
  },
  radii: {
    small: '4px',
    medium: '8px',
    large: '16px'
  },
  shadows: {
    small: '0 2px 4px rgba(0,0,0,0.1)',
    medium: '0 4px 8px rgba(0,0,0,0.15)',
    large: '0 8px 16px rgba(0,0,0,0.2)'
  }
});

<BlinkProvider theme={customTheme}>
  {/* Your app */}
</BlinkProvider>

CSS Classes

All components support className props for custom styling:

<BlinkButton
  className="custom-button"
  action={action}
>
  Custom Styled Button
</BlinkButton>
.custom-button {
  background: linear-gradient(45deg, #7B3FF2, #2FC5CC);
  border-radius: 12px;
  font-weight: bold;
}

Advanced Usage

Custom Action Handler

function CustomActionButton() {
  const { execute } = useBlink();
  
  const handleCustomAction = async () => {
    const result = await execute({
      type: 'custom',
      handler: async () => {
        // Your custom logic
        const tx = await buildCustomTransaction();
        return await sendTransaction(tx);
      }
    });
  };
  
  return <button onClick={handleCustomAction}>Execute</button>;
}

Batch Transactions

function BatchActions() {
  const { executeBatch } = useBlink();
  
  const handleBatch = async () => {
    const results = await executeBatch([
      { type: 'transfer', recipient: addr1, amount: 1 },
      { type: 'transfer', recipient: addr2, amount: 2 },
      { type: 'transfer', recipient: addr3, amount: 3 }
    ]);
    
    console.log('All transactions:', results);
  };
  
  return <button onClick={handleBatch}>Send to Multiple</button>;
}

SSR with Next.js

// pages/_app.tsx
import { BlinkProvider } from '@fliidotdev/blinks-react';
import dynamic from 'next/dynamic';

const WalletProvider = dynamic(
  () => import('../components/WalletProvider'),
  { ssr: false }
);

function MyApp({ Component, pageProps }) {
  return (
    <WalletProvider>
      <BlinkProvider>
        <Component {...pageProps} />
      </BlinkProvider>
    </WalletProvider>
  );
}

Error Handling

function SafeBlinkButton() {
  const [error, setError] = useState(null);
  
  return (
    <>
      <BlinkButton
        action={action}
        onError={(err) => {
          setError(err.message);
          // Log to error tracking service
          trackError(err);
        }}
      >
        Execute Action
      </BlinkButton>
      
      {error && (
        <ErrorAlert message={error} onDismiss={() => setError(null)} />
      )}
    </>
  );
}

Testing

import { render, screen, fireEvent } from '@testing-library/react';
import { MockBlinkProvider } from '@fliidotdev/blinks-react/testing';

test('BlinkButton executes action', async () => {
  render(
    <MockBlinkProvider mockWallet={mockWallet}>
      <BlinkButton action={mockAction}>
        Click Me
      </BlinkButton>
    </MockBlinkProvider>
  );
  
  fireEvent.click(screen.getByText('Click Me'));
  
  await waitFor(() => {
    expect(mockAction).toHaveBeenCalled();
  });
});

Performance Optimization

Lazy Loading

import { lazy, Suspense } from 'react';

const BlinkCard = lazy(() => import('@fliidotdev/blinks-react/BlinkCard'));

function App() {
  return (
    <Suspense fallback={<Loading />}>
      <BlinkCard {...props} />
    </Suspense>
  );
}

Memoization

import { memo, useMemo } from 'react';

const ExpensiveBlinkList = memo(({ actions }) => {
  const sortedActions = useMemo(
    () => actions.sort((a, b) => b.priority - a.priority),
    [actions]
  );
  
  return <ActionList actions={sortedActions} />;
});

Accessibility

All components follow WCAG 2.1 guidelines:

  • Keyboard navigation support
  • Screen reader announcements
  • Focus management
  • ARIA attributes
  • Color contrast compliance

License

MIT © fliidotdev

Contributing

We welcome contributions! Please see our Contributing Guide.

Support