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

open-node-ui

v1.0.4

Published

![Open Node UI Logo](https://static.moonbnb.app/images/ui/open-ui.png)

Readme

OPEN NODE UI

Open Node UI Logo

OPEN NODE UI is a lightweight React component library and SDK built to simplify the development of decentralized applications (dApps) on Ethereum and EVM-compatible chains.
It provides ready-to-use UI components and essential utilities tailored for smart contract interactions.

🚀 Built with React • Vite • TypeScript
🛠️ Focused on developer experience and Web3 integration


💬 ChatBox Component

<ChatBox /> is a fully customizable, responsive AI/Web3 chat interface for integrating smart contract interactions, AI assistants, or support bots directly into your dApp.

It is designed to deliver seamless conversation UX for Ethereum & EVM environments.

🧩 Features

  • 📱 Responsive layout (mobile-first with desktop support)
  • 🪄 Animated message history using framer-motion
  • 🔗 System prompts + persistent conversations
  • 🧠 AI-ready input/output management
  • 📚 Options (chips) for quick-start messages
  • 🎨 Customizable styles: messages, borders, app bar, and more

⚙️ Props Overview

| Prop | Type | Description | |--------------------|----------------------------------------|-------------| | isChatOpen | boolean | Controls visibility of the chat | | setIsChatOpen | (open: boolean) => void | Toggles chat UI | | inputText | string | Current input message | | setInputText | (text: string) => void | Updates the input field | | onChat | (messages: MessageType[]) => Promise<MessageType> | Handles AI/smart contract response | | onAddMessageToDb | (msg, convoId) => Promise<Conversation> | Persists message to backend | | options | OptionItem[] | Quick-reply chips | | logo | ReactNode | Optional branding logo | | title | string | Chat window title | | systemPrompt | string | Initial system instruction | | chatWidgetStyle | React.CSSProperties (optional) | Style override for the widget | | appBarStyle | React.CSSProperties (optional) | Style override for the app bar | | aiMsgStyle | React.CSSProperties (optional) | Style for AI/assistant messages | | userMsgStyle | React.CSSProperties (optional) | Style for user messages | | bordersColor | string (optional) | Color for message box separators |


🚀 Example Usage

import { ChatBox } from "open-node-ui";

<ChatBox
  isChatOpen={isChatOpen}
  setIsChatOpen={setIsChatOpen}
  buttonSendRef={sendButtonRef}
  textInputRef={textInputRef}
  inputText={inputText}
  setInputText={setInputText}
  onChat={handleOnChat}
  onAddMessageToDb={handleSaveMessage}
  options={[
    { title: "What is staking?", icon: <SomeIcon /> },
    { title: "How do I connect a wallet?" }
  ]}
  systemPrompt="You are a helpful Web3 assistant."
  title="Web3 Assistant"
  bordersColor="#e5e5e5"
/>

🧱 AppBar Component

<AppBar /> is a flexible top navigation bar designed for dApps and modular interfaces.
It serves as the header for panels, modals, or standalone views — supporting actions, custom titles, and back/close interactions.

✨ Features

  • 🧭 Customizable layout with optional title, leading icon (e.g. back button), and action buttons
  • 📦 Fixed or relative positioning to adapt to various container types
  • 🎯 Built-in close/back logic via the onClose callback
  • 💅 Easy to theme with className and styling props

⚙️ Props Overview

| Prop | Type | Description | |-------------|-------------------|-------------| | title | React.ReactNode | Title text or custom JSX element | | leading | React.ReactNode | Optional leading element (e.g. logo or back icon) | | actions | React.ReactNode[] | Action buttons/icons (right side) | | fixed | boolean | Whether to fix the AppBar to the top (true by default) | | zIndex | number | Sets z-index for layering | | className | string | Custom class name for styling | | onClose | () => void | Callback for closing or navigating back |


🚀 Example Usage

import { AppBar } from "open-node-ui";
import { X } from "lucide-react";

<AppBar
  title="Transaction Panel"
  leading={<img src="/logo.svg" alt="logo" />}
  actions={[<X onClick={() => console.log("Close")} />]}
  onClose={() => console.log("Back pressed")}
/>

🪟 Dialog Component

<Dialog /> is a responsive modal sheet built for displaying focused content such as forms, transaction previews, wallet interactions, and confirmations.
It includes a smooth open/close animation and works well on both desktop and mobile.

✨ Features

  • 📱 Mobile-friendly modal layout with animated scale transitions
  • 🧩 Optional header and content sectioning
  • 💅 Highly customizable styles for container and overlay
  • 🔐 Controlled visibility using the open prop

⚙️ Props Overview

| Prop | Type | Description | |--------------------------|-----------------------|-------------| | open | boolean | Controls visibility of the modal | | children | React.ReactNode | Content rendered inside the modal | | header | React.ReactNode | Optional header content (e.g. title, icon) | | containerStyle | React.CSSProperties | Inline styles for the modal container | | className | string | Additional classes for the modal container | | ContentTopSpace | string | Margin above the content section (default "0px") | | barrierStyle (unused)| React.CSSProperties | (Reserved for future use — modal background barrier) | | positionedContainerStyle | React.CSSProperties | Styles for the full-screen wrapper (positioning, z-index, etc.) |


🚀 Example Usage

import { Dialog } from "open-node-ui";

<Dialog
  open={isOpen}
  header={<h2>Confirm Transaction</h2>}
  containerStyle={{ backgroundColor: "#fff", borderRadius: "16px" }}
  ContentTopSpace="20px"
>
  <p>Are you sure you want to proceed with this transaction?</p>
  <button onClick={handleConfirm}>Confirm</button>
</Dialog>

📝 ListTitle Component

<ListTitle /> is a flexible header-like component used to label sections in lists, modals, or navigation panels.
It combines a title, optional subtitle, and interactive icons (like back buttons or actions), making it ideal for top-level list headers and contextual panels.

✨ Features

  • 🧭 Optional back icon or leading content
  • 📄 Supports subtitles and section descriptions
  • 🧩 Highly customizable styles for title, subtitle, and container
  • 🔘 Clickable container for navigation or action triggers
  • 🎯 Action icons aligned to the right

⚙️ Props Overview

| Prop | Type | Description | |--------------------|-----------------------|-------------| | title | React.ReactNode | Primary title text | | subTitle | React.ReactNode | Optional subtitle below the title | | leading | React.ReactNode | Left-side content (e.g. back icon) | | actions | React.ReactNode[] | Right-side icons/buttons | | onClick | () => void | Callback when the header is clicked | | className | string | Custom class for outer container | | listTitleStyle | React.CSSProperties | Style for the outer container | | leadingStyle | React.CSSProperties | Style for the leading icon or element | | titleStyle | React.CSSProperties | Style for the title text | | subtitleStyle | React.CSSProperties | Style for the subtitle text | | actionsStyle | React.CSSProperties | Style for the right-side action container | | mainTextStyle | React.CSSProperties | Style wrapper for both title and subtitle | | leftStyle | React.CSSProperties | Style wrapper for the left side (icon + title) |


🚀 Example Usage

import { ListTitle } from "open-node-ui";
import { X } from "lucide-react";

<ListTitle
  title="Settings"
  subTitle="Manage your preferences"
  onClick={() => console.log("Go back")}
  actions={[<X onClick={() => console.log("Close")} />]}
  titleStyle={{ fontWeight: "bold" }}
/>

📥 ModalBottomSheet Component

<ModalBottomSheet /> is a sleek, animated modal that slides up from the bottom of the screen — ideal for mobile dialogs, confirmations, or dynamic content in decentralized apps.
It's designed to be minimal, flexible, and smooth in transitions.

✨ Features

  • 📱 Mobile-first design with bottom-up appearance
  • 🎞️ Animated visibility transitions using ElementOpen and ElementClose
  • 📦 Customizable content and header area
  • 🧩 Flexible container styling for height, width, padding, etc.

⚙️ Props Overview

| Prop | Type | Description | |-------------------|-----------------------|-------------| | open | boolean | Controls visibility of the modal | | children | React.ReactNode | Main content of the modal | | header | React.ReactNode | Optional top section (e.g. title, icon) | | containerStyle | React.CSSProperties | Inline styles for the outer container | | className | string | Additional class names for styling | | ContentTopSpace | string | Space above the content body (default: "0px") | | barrierStyle (unused) | React.CSSProperties | Reserved for background overlay (future use) |


🚀 Example Usage

import { ModalBottomSheet } from "open-node-ui";

<ModalBottomSheet
  open={isModalOpen}
  header={<h3>Wallet Connected</h3>}
  containerStyle={{ backgroundColor: "#fff", borderTopLeftRadius: 20, borderTopRightRadius: 20 }}
  ContentTopSpace="15px"
>
  <p>Your wallet is now connected. You may proceed with the transaction.</p>
</ModalBottomSheet>

🛡️ BarrierOverlay Component

<BarrierOverlay /> is a backdrop layer used behind modals and bottom sheets to dim the background and prevent interaction with the underlying UI.
It also handles dismissal actions when users tap outside a modal area.

✨ Features

  • 🕶️ Dynamic opacity and z-index control for smooth entrance/exit
  • 🔄 Click-to-close functionality via toggleModalState callback
  • 🎛️ Configurable animation properties for both open and close states

⚙️ Props Overview

| Prop | Type | Description | |------------------|-------------|-------------| | isOpen | boolean | Controls the visibility and layering of the overlay | | toggleModalState | () => void | Callback triggered on background click | | openZIndex | number | Z-index when overlay is active (default: 1000) | | closeZIndex | number | Z-index when overlay is hidden (default: -1) | | openOpacity | number | Opacity when overlay is active (default: 1) | | closeOpacity | number | Opacity when overlay is hidden (default: 0) |


🚀 Example Usage

import { BarrierOverlay } from "open-node-ui";

<BarrierOverlay
  isOpen={isModalVisible}
  toggleModalState={() => setIsModalVisible(false)}
  openOpacity={0.6}
  openZIndex={1300}
/>

🔄 CircularLoader & FixedNormalLoader Components

These two components offer loading spinners for various use cases in your dApp UI — from fullscreen blocking loaders to inline activity indicators.


🎡 CircularLoader

A fullscreen, center-aligned loader with optional blur, text, and customizable styles.
It’s commonly used to indicate blocking states such as wallet connection, transaction confirmation, or page transitions.

✨ Features

  • 🌀 Multiple built-in animation types
  • 🌫️ Optional blurred background
  • 🧾 Optional loading message
  • 🎨 Style overrides via loaderStyle object

⚙️ loaderStyle Props

| Prop | Type | Description | |------------------------|-----------------------|-------------| | type | 0 | 1 | 2 | 3 | Loader animation style (default: 0) | | barrierStyle | React.CSSProperties | Background container style | | loaderContainerStyle | React.CSSProperties | Loader inner wrapper styles | | loaderStyle | React.CSSProperties | Actual loader element styling | | text | string | Optional loading text | | textStyle | React.CSSProperties | Style for the loading text | | useBlur | boolean | Enables backdrop blur if true |

🚀 Example Usage

import { CircularLoader } from "open-node-ui";

<CircularLoader
  styles={{
    type: 1,
    text: "Connecting to wallet...",
    useBlur: true,
    textStyle: { color: "#fff", fontSize: "14px" },
  }}
/>

🔔 Toast Notification System

This module provides a React context-based toast notification system allowing easy global toast messages management throughout your app.


🧩 ToastProvider

A React context provider that manages a list of toast messages and handles their lifecycle including showing, auto-dismissing, and manual deletion.

Features

  • Generates unique IDs for each toast using uuid
  • Supports automatic removal of toast messages after a customizable duration (default 5000ms)
  • Gracefully handles exit animations by toggling isExiting flag before removing from state
  • Allows disabling auto-delete for persistent toasts
  • Passes showToast function via context for easy access in components
  • Renders all active toast messages via the internal Toast component

Props

| Prop | Type | Description | | -------- | ------------- | ----------------------------- | | children | ReactNode | Child components wrapped by this provider |

Usage Example

Wrap your app or part of the component tree where you want toast notifications:

import { ToastProvider } from "open-node-ui";

<ToastProvider>
  <YourApp />
</ToastProvider>

Use case


import { useToast } from "open-node-ui";

const MyComponent = () => {
  const { showToast } = useToast();

  const notify = () => {
    showToast({
      message: "This is a success notification!",
      duration: 3000,
      autoDelete: true,
      addDeleteAction: true,
      type: "success",
    });
  };

  return <button onClick={notify}>Notify</button>;
};

Toast Message type

type ToastMessage = {
  id?: string;
  message: React.ReactNode | string;
  type?: "success" | "error" | "info" | "warning";
  duration?: number; // in milliseconds
  autoDelete?: boolean; // defaults to true
  addDeleteAction?: boolean; // whether to show a manual close action
  isExiting?: boolean; // internal use for exit animation
};

WEB3 SDK FUNCTIONALIIES

This library also allows you to manage several aspects of connection management between an ethereum wallet (EVMS) and your application (Dapp).

Web3Provider Context

The Web3Provider component and its hook useWeb3 provide a React context for easy integration with Ethereum wallets and networks. It manages wallet connections, network switching, and ETH balance fetching for Ethereum and EVM-compatible blockchains.

Features

  • Connect to Ethereum wallets via the browser's injected ethereum provider (e.g., MetaMask).
  • Automatically switch networks if the connected wallet is on a different chain than specified.
  • Access the currently connected account and list of accounts.
  • Retrieve ETH balance of the connected account.
  • Disconnect and reset connection state.
  • Access the underlying web3 instance for advanced contract interactions.

Usage

Wrap your app or component tree with the Web3Provider component and pass the desired rpcUrl and chainId:

import { Web3Provider } from "open-node-ui";

function App() {
  return (
    <Web3Provider rpcUrl="https://mainnet.infura.io/v3/YOUR_INFURA_KEY" chainId={1}>
      <YourComponent />
    </Web3Provider>
  );
}

// in walletInfo.tsx

import { useWeb3 } from "open-node-ui";

function WalletInfo() {
  const { account, connect, disconnect, getEthBalance, isConnected } = useWeb3();

  return (
    <div>
      {isConnected ? (
        <>
          <p>Connected account: {account}</p>
          <button onClick={disconnect}>Disconnect</button>
          <p>ETH Balance: {getEthBalance()}</p>
        </>
      ) : (
        <button onClick={connect}>Connect Wallet</button>
      )}
    </div>
  );
}

Web3Utils Utility Class

The Web3Utils class provides helpful static utility functions related to Ethereum addresses, improving usability and display in your dApp.

Methods

  • truncatedAddress(address: string): string

    Takes a full Ethereum address and returns a shortened, user-friendly version by truncating the middle part of the address.
    This makes displaying addresses in the UI cleaner and more readable.

    Example:

    Web3Utils.truncatedAddress("0x1234567890abcdef1234567890abcdef12345678")
    // Returns: "0x1234...345678"

``

TokenStateLess and TokenStateFull Classes

These classes provide convenient interfaces to interact with ERC-20 token contracts using Web3, enabling read-only and state-changing operations respectively.


TokenStateLess

This class is designed for read-only interactions with a token contract. It requires a web3ContextType instance and the token's contract address during initialization.

Key Methods:

  • createContract()
    Initializes and returns a Web3 contract instance using the token ABI and contract address.

  • totalSupply()
    Fetches the total supply of the token from the blockchain and returns it as a decimal number (adjusted for 18 decimals).

  • balanceOf(address: string)
    Retrieves the token balance of a specific address, adjusted to decimal form.

  • allowance(owner: string, spender: string)
    Checks how many tokens the spender is allowed to spend on behalf of the owner.

  • throwError(error)
    Handles and rethrows errors consistently.


TokenStateFull

Extends TokenStateLess and adds write functionality such as approving token allowances.

Key Method:

  • Approve({ address, amount })
    Uses a TransactionSigner to send an approval transaction that authorizes the address to spend a specified amount of tokens on the user's behalf.

    • address: The spender's address.
    • amount: Number of tokens to approve (defaults to 100,000 tokens with 18 decimals).

    Throws errors if Metamask (or Ethereum provider) is not detected or if the transaction fails.


Usage Example

import { TokenStateFull } from "open-node-ui";
import { useWeb3 } from "open-node-ui/hooks/web3/web3_context";

const { web3, account } = useWeb3();
const tokenContractAddress = "0x...";

const token = new TokenStateFull(web3, tokenContractAddress);

// Read total supply
const supply = await token.totalSupply();

// Approve spender
await token.Approve({ address: "0xSpenderAddress", amount: 1000 * 1e18 });

TransactionSigner Class

The TransactionSigner class is designed to simplify the process of signing and sending Ethereum transactions using Web3 and the injected Ethereum provider (such as MetaMask). It encapsulates transaction preparation, gas estimation, and sending logic into one reusable class.

import { type web3ContextType } from "../hooks/web3/web3_context";
import type { ResponseMessage } from "../types/types";

export class TransactionSigner {
  public web3: web3ContextType;

  constructor(web3: web3ContextType) {
    this.web3 = web3;
  }

  signAndSendTransaction = async ({
    from,
    to,
    value,
    data,
  }: {
    from: string;
    to: string;
    value: number;
    data: string;
  }): Promise<ResponseMessage> => {
    try {
      const ethereum = this.web3.ethereum;
      const params = { from, to, value, data };

      // Estimate gas needed for the transaction
      const estimatedGas = await this.web3.web3!.eth.estimateGas(params);
      console.log("estimate fees: ", estimatedGas);

      // Round down gas limit
      const gasLimit = Math.floor(Number(estimatedGas));
      console.log("Estimated gas:", estimatedGas);
      console.log("Adjusted gas limit:", gasLimit);

      // Request Ethereum provider to send the transaction
      const receipt = await ethereum.request({
        method: "eth_sendTransaction",
        params: [
          {
            ...params,
            value: this.web3.web3.utils.toHex(params.value),
            gas: this.web3.web3.utils.toHex(gasLimit),
          },
        ],
      });

      // Return success response with transaction receipt
      if (receipt) {
        if (typeof receipt === "string") {
          return { success: true, message: receipt };
        } else {
          return { success: true, message: JSON.stringify(receipt) };
        }
      } else {
        throw Error("Failed to Register");
      }
    } catch (error) {
      console.error(error);
      return {
        success: false,
        message: typeof error === "string" ? error : JSON.stringify(error),
      };
    }
  };
}