@chainrails/react
v0.3.0
Published
React components and hooks for integrating Chainrails payments and blockchain utilities into your app.
Downloads
2,019
Readme
@chainrails/react
React components and hooks for integrating Chainrails payments and blockchain utilities into your app.
What's New in v0.1.5 (January 2026)
Major Refactor: Session-Based Payment Flows
The payment modal integration has been completely redesigned around session tokens for improved security and flexibility:
- New Hook:
usePaymentSessionreplacesusePaymentModalwith full session lifecycle management - Enhanced Modal:
PaymentModalcomponent now accepts session data with improved iframe communication - Better State Management: Valtio-based reactive state for session data, tokens, and error handling
- Automatic Expiration: Built-in session expiration tracking with configurable callbacks
- Message Protocol: Secure cross-frame communication via postMessage API
New Features
- Session Token Propagation: Automatic secure passing of session tokens to iframe
- Utility Functions: New
convertToBaseUnits()andconvertToNormalNumber()helpers for token amount conversions - Enhanced Error Handling: Better error state management and propagation
- Improved TypeScript Support: Full type definitions for session-based flows
Features
- PaymentModal: Drop-in modal for blockchain payments with session authentication
- usePaymentSession: Powerful React hook for complete session lifecycle management
- Auto-included styles: Importing the package automatically loads component CSS
- Chainrails SDK access: Re-exports Chainrails API and common utilities
- Session Management: Built-in session creation, expiration, and error handling
Installation
npm install @chainrails/react
# or
pnpm add @chainrails/reactUsage
Basic Usage with usePaymentSession
import { chains, tokens, PaymentModal, usePaymentSession, Chainrails } from "@chainrails/react"
Chainrails.config({ api_key: "your_api_key" })
function App() {
const session = usePaymentSession({
session_url: "http://localhost:4000/create-session",
destinationChain: chains.ARBITRUM,
token: tokens.USDC,
recipient: "0xb25aa807118aa401896826147a6ecdaae91f2f90",
amount: 100,
onSuccess: () => {
console.log("Payment Successful!")
},
onCancel: () => {
console.log("Payment Cancelled")
}
})
return (
<div>
<button onClick={session.open}>Pay with Chainrails</button>
<PaymentModal
{...session}
data={session.data}
amount={100}
/>
</div>
)
}
export default AppAdvanced Usage: Custom Session Management
import { usePaymentSession, PaymentModal } from "@chainrails/react"
function PaymentFlow() {
const session = usePaymentSession({
session_url: process.env.VITE_SESSION_URL,
destinationChain: "BASE",
token: "USDC",
recipient: userAddress,
amount: paymentAmount,
onSuccess: async () => {
// Handle successful payment
await completeOrder()
session.close()
},
onCancel: () => {
// Handle cancellation
setPaymentCancelled(true)
}
})
if (session.error) {
return <div>Error: {session.error}</div>
}
return (
<div>
<PaymentModal
{...session}
data={session.data}
isPending={session.isPending}
/>
{session.isOpen ? (
<button onClick={session.close}>Cancel</button>
) : (
<button onClick={session.open}>Open Payment</button>
)}
</div>
)
}API Reference
usePaymentSession Hook
Complete session-based payment flow management.
Parameters
interface UsePaymentSessionProps {
session_url: string // Endpoint to create sessions
destinationChain: chains // Target blockchain
token: tokens // Token to transfer
recipient: `0x${string}` // Recipient address
amount?: number // Transfer amount (optional)
onCancel?: () => void // Callback when payment cancelled
onSuccess?: () => void // Callback when payment succeeds
}Return Value
interface UsePaymentSessionReturn {
// State
data: {
sessionToken: string
sessionId: string
expiresAt: string
} | null
error: string | null
isPending: boolean
isOpen: boolean
// Methods
open: () => void // Open payment modal
close: () => void // Close payment modal
refresh: () => void // Refresh session
}Methods
open()- Opens the payment modal and displays the payment interfaceclose()- Closes the payment modalrefresh()- Refreshes the session token (useful for extending expiration)
Properties
data- Current session data including token and expirationerror- Any error that occurred during session creation or managementisPending- True while session is being created or updatedisOpen- True when modal is currently visible
PaymentModal Component
Drop-in payment modal component with session support.
Props
interface PaymentModalProps extends React.HTMLAttributes<HTMLDivElement> {
// Required
recipient: string // Recipient address
destinationChain: string // Target blockchain
token: string // Token symbol
open: () => void // Function to open modal
close: () => void // Function to close modal
isOpen: boolean // Whether modal is open
// Optional
amount?: number // Payment amount
data?: { // Session data from usePaymentSession
sessionToken: string
expiresAt: string
sessionId: string
} | null
isPending?: boolean // Loading state
onCancel?: () => void // Callback on cancel
onSuccess?: () => void // Callback on success
}Features
- Automatic document overflow management (prevents body scroll)
- Secure iframe communication via postMessage
- Loading state during session token propagation
- Automatic closing on completion
- Customizable callbacks for success/cancel events
Styling
The component comes with built-in styles that are automatically imported. You can customize the appearance:
/* Override default styles */
.payment-modal-wrapper {
/* Your custom styles */
}
.payment-modal-wrapper.open {
/* Opened state */
}
.payment-modal-wrapper.closed {
/* Closed state */
}
.payment-modal-loader {
/* Loading spinner */
}Utility Functions
convertToBaseUnits
Converts human-readable token amounts to blockchain base units (wei for ETH, etc.).
import { convertToBaseUnits } from "@chainrails/react"
const weiAmount = convertToBaseUnits("1.5", 18) // "1500000000000000000"
const usdcAmount = convertToBaseUnits("100", 6) // "100000000"Parameters
amount: string | number- Human-readable amountdecimals: number- Token decimals (18 for ETH, 6 for USDC, etc.)
Returns
string- Amount in base units
convertToNormalNumber
Converts blockchain base units to human-readable decimal numbers.
import { convertToNormalNumber } from "@chainrails/react"
const ethAmount = convertToNormalNumber("1500000000000000000", 18) // 1.5
const usdcAmount = convertToNormalNumber("100000000", 6) // 100Parameters
amount: string | number- Amount in base unitsdecimals: number- Token decimals
Returns
number- Human-readable amount
Re-exported from SDK
The package re-exports commonly used utilities from @chainrails/sdk:
import {
chains, // Chain constants (ARBITRUM, BASE, etc.)
tokens, // Token constants (USDC, ETH, etc.)
Chainrails, // Configuration and environment
crapi, // Full SDK API
environment // Environment constants
} from "@chainrails/react"Styling
Default Styles
Default styles are automatically loaded when you import from the package:
import { PaymentModal } from "@chainrails/react"
// Styles are automatically includedCustomization
To override default styles, import your CSS after the package:
import { PaymentModal } from "@chainrails/react"
import "./custom-payment-styles.css" // Your overridesOr use higher CSS specificity:
.payment-modal-wrapper.custom-theme {
--primary-color: #your-color;
/* other overrides */
}Configuration
Environment Setup
Configure the SDK before using components:
import { Chainrails } from "@chainrails/react"
// Production
Chainrails.config({
api_key: process.env.REACT_APP_CHAINRAILS_API_KEY
})
// Or development/staging
Chainrails.config({
api_key: process.env.REACT_APP_CHAINRAILS_API_KEY,
env: "staging"
})Session URL Configuration
The session URL should point to your backend endpoint that creates sessions:
const session = usePaymentSession({
session_url: process.env.REACT_APP_SESSION_URL, // e.g., http://localhost:4000/create-session
// ... other config
})Breaking Changes from v0.0.x
If you're upgrading from an older version, note these breaking changes:
Hook Replacement:
usePaymentModal→usePaymentSession// Old: usePaymentModal({ to, chain, token, ... }) // New: usePaymentSession({ session_url, destinationChain, token, recipient, ... })Session Data Required: PaymentModal now requires session data
<PaymentModal {...session} data={session.data} />Parameter Changes: Props have been renamed for clarity
to→recipientchain→destinationChain- New required:
session_url
Examples
Example 1: E-commerce Integration
function CheckoutModal({ total, currency }) {
const session = usePaymentSession({
session_url: "/api/create-payment-session",
destinationChain: chains.BASE,
token: tokens[currency],
recipient: process.env.REACT_APP_MERCHANT_ADDRESS,
amount: total,
onSuccess: () => {
completeOrder()
sendConfirmationEmail()
}
})
return (
<>
<button onClick={session.open}>Proceed to Payment</button>
<PaymentModal {...session} data={session.data} />
</>
)
}Example 2: Multi-Chain Payment Option
function MultiChainPayment() {
const [selectedChain, setSelectedChain] = useState(chains.ARBITRUM)
const session = usePaymentSession({
session_url: "/api/sessions",
destinationChain: selectedChain,
token: tokens.USDC,
recipient: recipientAddress,
amount: 100
})
return (
<div>
<select onChange={(e) => setSelectedChain(e.target.value)}>
{Object.entries(chains).map(([key, value]) => (
<option key={key} value={value}>{key}</option>
))}
</select>
<button onClick={session.open}>Pay on {selectedChain}</button>
<PaymentModal {...session} data={session.data} />
</div>
)
}Example 3: Error Handling
function SafePaymentFlow() {
const session = usePaymentSession({
session_url: "/api/create-session",
destinationChain: chains.BASE,
token: tokens.USDC,
recipient: recipientAddress,
onSuccess: () => showSuccessMessage(),
onCancel: () => showCancelledMessage()
})
if (session.error) {
return (
<div className="error">
<p>Failed to initialize payment: {session.error}</p>
<button onClick={session.refresh}>Retry</button>
</div>
)
}
return (
<>
<button onClick={session.open} disabled={session.isPending}>
{session.isPending ? "Loading..." : "Pay Now"}
</button>
<PaymentModal {...session} data={session.data} />
</>
)
}Aliases & Monorepo
- The package is aliased as
@chainrails/reactin Vite config for local development - Styles and components are bundled for both dev and production
- Works seamlessly in monorepo setups
TypeScript Support
Full TypeScript support with complete type definitions:
import { usePaymentSession, PaymentModal } from "@chainrails/react"
import type { UsePaymentSessionProps } from "@chainrails/react"
const props: UsePaymentSessionProps = {
session_url: "...",
destinationChain: "BASE",
token: "USDC",
recipient: "0x...",
}Browser Support
- Modern browsers with ES2020+ support
- Requires:
- Fetch API
- SessionStorage
- postMessage API for iframe communication
- Web Components support (for modal)
Version History
v0.1.5 (January 2026)
- Complete session-based payment flow refactor
- New usePaymentSession hook
- Enhanced PaymentModal component
- New utility functions
- Better error handling
v0.0.28 and earlier
- Legacy usePaymentModal hook (deprecated)
Related Packages
@chainrails/sdk- Core SDK with all APIs@chainrails/common- Shared types and utilities
License
MIT
Support
For issues and feature requests, visit: https://github.com/horuslabsio/chainrails-sdk
Last Updated: January 6, 2026
Current Version: v0.1.5
