React components and hooks for integrating Chainrails payments and blockchain utilities into your app.
npm install @chainrails/reactReact components and hooks for integrating Chainrails payments and blockchain utilities into your app.
The payment modal integration has been completely redesigned around session tokens for improved security and flexibility:
- New Hook: usePaymentSession replaces usePaymentModal with full session lifecycle management
- Enhanced Modal: PaymentModal component 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
- Session Token Propagation: Automatic secure passing of session tokens to iframe
- Utility Functions: New convertToBaseUnits() and convertToNormalNumber() helpers for token amount conversions
- Enhanced Error Handling: Better error state management and propagation
- Improved TypeScript Support: Full type definitions for session-based flows
- 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
``bash`
npm install @chainrails/reactor
pnpm add @chainrails/react
`tsx
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 (
export default App
`
`tsx
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
return (
API Reference
$3
Complete session-based payment flow management.
#### Parameters
`typescript
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
`typescript
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 interface
- close() - Closes the payment modal
- refresh() - Refreshes the session token (useful for extending expiration)#### Properties
-
data - Current session data including token and expiration
- error - Any error that occurred during session creation or management
- isPending - True while session is being created or updated
- isOpen - True when modal is currently visible$3
Drop-in payment modal component with session support.
#### Props
`typescript
interface PaymentModalProps extends React.HTMLAttributes {
// 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:
`css
/ 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
$3
Converts human-readable token amounts to blockchain base units (wei for ETH, etc.).
`typescript
import { convertToBaseUnits } from "@chainrails/react"const weiAmount = convertToBaseUnits("1.5", 18) // "1500000000000000000"
const usdcAmount = convertToBaseUnits("100", 6) // "100000000"
`#### Parameters
-
amount: string | number - Human-readable amount
- decimals: number - Token decimals (18 for ETH, 6 for USDC, etc.)#### Returns
-
string - Amount in base units$3
Converts blockchain base units to human-readable decimal numbers.
`typescript
import { convertToNormalNumber } from "@chainrails/react"const ethAmount = convertToNormalNumber("1500000000000000000", 18) // 1.5
const usdcAmount = convertToNormalNumber("100000000", 6) // 100
`#### Parameters
-
amount: string | number - Amount in base units
- decimals: number - Token decimals#### Returns
-
number - Human-readable amountRe-exported from SDK
The package re-exports commonly used utilities from
@chainrails/sdk:`typescript
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
$3
Default styles are automatically loaded when you import from the package:
`typescript
import { PaymentModal } from "@chainrails/react"
// Styles are automatically included
`$3
To override default styles, import your CSS after the package:
`typescript
import { PaymentModal } from "@chainrails/react"
import "./custom-payment-styles.css" // Your overrides
`Or use higher CSS specificity:
`css
.payment-modal-wrapper.custom-theme {
--primary-color: #your-color;
/ other overrides /
}
`Configuration
$3
Configure the SDK before using components:
`typescript
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"
})
`$3
The session URL should point to your backend endpoint that creates sessions:
`typescript
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:
1. Hook Replacement:
usePaymentModal → usePaymentSession
`typescript
// Old: usePaymentModal({ to, chain, token, ... })
// New: usePaymentSession({ session_url, destinationChain, token, recipient, ... })
`2. Session Data Required: PaymentModal now requires session data
`typescript
`3. Parameter Changes: Props have been renamed for clarity
-
to → recipient
- chain → destinationChain
- New required: session_urlExamples
$3
`tsx
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 (
<>
>
)
}
`$3
`tsx
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 (
)
}
`$3
`tsx
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 (
Failed to initialize payment: {session.error}
)
} return (
<>
>
)
}
`Aliases & Monorepo
- The package is aliased as
@chainrails/react in Vite config for local development
- Styles and components are bundled for both dev and production
- Works seamlessly in monorepo setupsTypeScript Support
Full TypeScript support with complete type definitions:
`typescript
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 utilitiesMIT
For issues and feature requests, visit:
https://github.com/horuslabsio/chainrails-sdk
---
Last Updated: January 6, 2026
Current Version: v0.1.5