A flexible React authentication library for NEAR Protocol with optional staking validation, multi-chain support, and educational onboarding features designed to simplify Web3 for mainstream users.
- π NEAR Authentication: Seamless wallet integration with NEAR Wallet Selector
- π₯© Staking Validation: Optional or required staking with configurable validator pools
- π Educational Components: Built-in tooltips, guided wizards, and progressive onboarding for crypto beginners
- π Multi-Chain Support: Chain signature functionality for cross-chain transactions
- βοΈ React Components: Ready-to-use components with customizable UI
- πͺ React Hooks: Powerful hooks for authentication state management
- π± Route Protection: Built-in protected route components
- π Session Management: Persistent sessions with security features
- π TypeScript: Full TypeScript support with comprehensive type definitions
npm install @vitalpointai/near-login
# or
yarn add @vitalpointai/near-login
# or
pnpm add @vitalpointai/near-loginThis library requires React as a peer dependency:
npm install react react-domAll NEAR wallet selector dependencies are included automatically.
π¦ Automated Publishing: This package is automatically published to npm when new versions are pushed to the main branch. Releases include automated testing, building, and GitHub release creation.
import { NEARLogin } from '@vitalpointai/near-login';
function App() {
const config = {
// Minimal configuration - only wallet connection required
// No networkId required - defaults to 'testnet'
};
return (
<NEARLogin config={config}>
<div>
<h1>My NEAR App</h1>
<p>This content is shown when authenticated</p>
</div>
</NEARLogin>
);
}import { NEARLogin } from '@vitalpointai/near-login';
function App() {
const config = {
nearConfig: { networkId: 'testnet' }
};
return (
<NEARLogin
config={config}
showHelp={true} // Enable help tooltips
helpTexts={{
walletConnection: "Connect your NEAR wallet to access this app. Your keys never leave your wallet!",
staking: "Staking helps secure the network and earns you rewards (typically 8-12% annually)."
}}
showEducation={true} // Show educational content for beginners
educationTopics={['what-is-wallet', 'why-near', 'security-tips']}
useGuidedStaking={true} // Use step-by-step staking wizard
>
<div>
<h1>My NEAR App</h1>
<p>This content is shown when authenticated</p>
</div>
</NEARLogin>
);
}import { EducationTooltip, WalletEducation, GuidedStakingWizard } from '@vitalpointai/near-login';
function MyComponent() {
return (
<div>
{/* Add helpful tooltips anywhere */}
<EducationTooltip
content="A crypto wallet is like a secure digital keychain for your tokens."
title="What is a wallet?"
position="top"
>
<button>Connect Wallet</button>
</EducationTooltip>
{/* Progressive education for beginners */}
<WalletEducation
topics={['what-is-wallet', 'why-near', 'how-staking-works']}
onComplete={() => console.log('Education completed!')}
/>
{/* Guided staking wizard */}
<GuidedStakingWizard
validator={{ poolId: 'validator.pool.near', displayName: 'My Validator' }}
onComplete={(amount) => console.log(`Staking ${amount} NEAR`)}
onCancel={() => console.log('Staking cancelled')}
/>
</div>
);
}import { NEARLogin } from '@vitalpointai/near-login';
function App() {
const config = {
nearConfig: {
networkId: 'testnet' // or 'mainnet'
},
walletConnectOptions: {
contractId: 'your-contract.testnet'
}
};
return (
<NEARLogin config={config}>
<div>
<h1>My NEAR App</h1>
<p>This content is shown when authenticated</p>
</div>
</NEARLogin>
);
}import { NEARLogin } from '@vitalpointai/near-login';
function App() {
const config = {
requireStaking: true,
validator: {
poolId: 'validator.pool.near',
minStake: '100' // Minimum 100 NEAR staked
},
nearConfig: {
networkId: 'testnet'
},
walletConnectOptions: {
contractId: 'your-contract.testnet'
}
};
return (
<NEARLogin
config={config}
useGuidedStaking={true} // Use the guided wizard for easier staking
showHelp={true}
helpTexts={{
staking: "This app requires staking to access premium features. You'll earn rewards while staked!"
}}
onToast={(toast) => console.log('Notification:', toast)}
>
<div>
<h1>Staking-Protected App</h1>
<p>Only staked users can see this content</p>
</div>
</NEARLogin>
);
}import { useNEARLogin } from '@vitalpointai/near-login';
function MyComponent() {
const {
isConnected,
isAuthenticated,
isStaked,
accountId,
signIn,
signOut,
stake
} = useNEARLogin();
if (!isConnected) {
return <button onClick={signIn}>Connect Wallet</button>;
}
return (
<div>
<p>Connected as: {accountId}</p>
{isStaked ? (
<p>β
Staking validated</p>
) : (
<button onClick={() => stake('100')}>
Stake 100 NEAR
</button>
)}
<button onClick={signOut}>Disconnect</button>
</div>
);
}import { NEARLogin, ProtectedRoute } from '@vitalpointai/near-login';
function App() {
const config = {
requireStaking: true,
validator: {
poolId: 'validator.pool.near'
},
nearConfig: {
networkId: 'testnet'
}
};
return (
<NEARLogin config={config}>
<div>
<h1>My App</h1>
<ProtectedRoute requireStaking={true}>
<div>This content requires staking validation</div>
</ProtectedRoute>
<ProtectedRoute requireStaking={false}>
<div>This content just requires wallet connection</div>
</ProtectedRoute>
</div>
</NEARLogin>
);
}Note:
ProtectedRoutemust be used within aNEARLogincomponent since it relies on the authentication context.
This library includes comprehensive educational components to help onboard users who are new to Web3 and cryptocurrency:
<NEARLogin
config={config}
// Enable help tooltips throughout the UI
showHelp={true}
helpTexts={{
walletConnection: "Your custom help text for wallet connection",
staking: "Your custom help text for staking process",
stakingAmount: "Your custom help text for choosing stake amount",
rewards: "Your custom help text about staking rewards"
}}
// Show educational content for crypto beginners
showEducation={true}
educationTopics={[
'what-is-wallet', // Explains crypto wallets
'why-near', // Benefits of NEAR Protocol
'how-staking-works', // How staking generates rewards
'security-tips' // Best practices for wallet security
]}
// Use guided wizard instead of direct staking UI
useGuidedStaking={true}
>
<YourAppContent />
</NEARLogin>Import and use educational components anywhere in your app:
import {
EducationTooltip,
WalletEducation,
GuidedStakingWizard
} from '@vitalpointai/near-login';
// Helpful tooltips
<EducationTooltip
content="Detailed explanation text..."
title="Tooltip Title"
position="top" // top, bottom, left, right
trigger="hover" // hover, click
>
<YourTriggerElement />
</EducationTooltip>
// Progressive education flow
<WalletEducation
topics={['what-is-wallet', 'why-near']}
showVideo={false} // Optional video content
onComplete={() => console.log('Education completed')}
/>
// Step-by-step staking wizard
<GuidedStakingWizard
validator={{
poolId: 'your-validator.pool.near',
displayName: 'Your Validator',
minStake: '1',
description: 'Description of your validator'
}}
minStake="1"
onComplete={(amount) => handleStaking(amount)}
onCancel={() => handleCancel()}
helpTexts={{
staking: "Custom help text for staking step",
stakingAmount: "Custom help text for amount selection",
rewards: "Custom help text about rewards"
}}
/>interface AuthConfig {
// Validator configuration (optional)
validator?: ValidatorConfig;
// NEAR network configuration (optional - defaults provided)
nearConfig?: Partial<NEARConfig>;
// Backend integration (optional)
backend?: AuthBackendConfig;
// Wallet connection options (optional)
walletConnectOptions?: {
contractId?: string;
theme?: 'auto' | 'light' | 'dark';
};
// Session configuration (optional)
sessionConfig?: {
duration?: number; // Session duration in milliseconds (DEPRECATED - use sessionSecurity.maxAge)
storageKey?: string; // Local storage key for session
rememberSession?: boolean; // Whether to persist sessions across browser sessions (default: true)
};
// Enhanced security configuration (optional)
sessionSecurity?: SessionSecurityConfig;
// Global staking requirement (optional)
requireStaking?: boolean; // Global flag to require staking (default: true if validator provided, false otherwise)
// Multi-chain configuration (optional)
chainSignature?: {
contractId?: string; // Optional - auto-selected: 'v1.signer' (mainnet) or 'v1.signer-prod.testnet' (testnet)
supportedChains?: string[]; // Optional - chains to enable for multi-chain signatures
};
}
interface NEARConfig {
networkId: 'mainnet' | 'testnet';
nodeUrl: string;
walletUrl: string;
helperUrl: string;
explorerUrl: string;
}
interface ValidatorConfig {
poolId: string; // e.g., 'vitalpoint.pool.near'
displayName?: string; // Human-readable validator name
description?: string; // Validator description
required?: boolean; // Whether staking is required (default: true)
minStake?: string; // Minimum stake amount in NEAR
}
interface SessionSecurityConfig {
// Session expiration and refresh
maxAge?: number; // Maximum session age in milliseconds (default: 7 days)
idleTimeout?: number; // Idle timeout in milliseconds (default: 24 hours)
refreshThreshold?: number; // Refresh token when this close to expiration (default: 25% of maxAge)
// Device and location binding
deviceFingerprinting?: boolean; // Enable device fingerprinting (default: true)
bindToIP?: boolean; // Bind session to IP address (default: false - can break mobile)
requireReauth?: number; // Require re-authentication after this time in milliseconds
// Storage security
encryptStorage?: boolean; // Encrypt session data in localStorage (default: true)
secureStorage?: boolean; // Use sessionStorage instead of localStorage (default: false)
// Session validation
validateOnFocus?: boolean; // Validate session when window gains focus (default: true)
validateInterval?: number; // Background validation interval in milliseconds (default: 5 minutes)
validateWithBackend?: string; // Backend endpoint for session validation
// Cleanup and rotation
rotateTokens?: boolean; // Rotate session tokens periodically (default: false)
preventConcurrent?: boolean; // Prevent multiple concurrent sessions (default: false)
clearOnError?: boolean; // Clear session on authentication errors (default: true)
// Event handlers
onSecurityViolation?: (violation: SecurityViolation) => void;
onSessionExpired?: () => void;
// Development vs Production
allowInsecure?: boolean; // Allow insecure practices in development (default: false)
}
interface AuthBackendConfig {
backendUrl?: string;
sessionEndpoint?: string;
verifyEndpoint?: string;
stakingEndpoint?: string;
}interface NEARLoginProps {
config: AuthConfig; // Configuration object (required)
children: ReactNode; // Content to show when authenticated
onToast?: (toast: ToastNotification) => void; // Toast notification handler
renderLoading?: () => ReactNode; // Custom loading component
renderError?: (error: string, retry: () => void) => ReactNode; // Custom error component
renderUnauthorized?: (signIn: () => Promise<void>, stake?: (amount: string) => Promise<void>) => ReactNode; // Custom unauthorized component
// Educational features
showHelp?: boolean; // Enable help tooltips
helpTexts?: Partial<HelpTexts>; // Custom help text overrides
showEducation?: boolean; // Show educational content for beginners
useGuidedStaking?: boolean; // Use guided staking wizard
educationTopics?: ('what-is-wallet' | 'why-near' | 'how-staking-works' | 'security-tips')[]; // Educational topics to show
}interface ProtectedRouteProps {
children: ReactNode; // Protected content
fallback?: ReactNode; // Content to show when not authenticated
requireStaking?: boolean; // Override staking requirement (default: checks parent NEARLogin config)
}Important: ProtectedRoute must be used within a NEARLogin component for authentication context.
The main hook for accessing NEAR authentication state:
const {
// Connection state
isConnected, // boolean - wallet connected
isAuthenticated, // boolean - wallet connected and session valid
isStaked, // boolean - has valid staking (if required)
isLoading, // boolean - loading state
// Account info
accountId, // string | null - connected account ID
stakingInfo, // StakingInfo | null - staking details
sessionToken, // string | null - current session token
error, // string | null - current error message
config, // AuthConfig | null - current configuration
// Actions
signIn, // () => Promise<void> - connect wallet
signOut, // () => Promise<void> - disconnect wallet
stake, // (amount: string) => Promise<void> - stake NEAR (renamed from stakeTokens)
unstake, // (amount: string) => Promise<void> - unstake NEAR (renamed from unstakeTokens)
refresh, // () => Promise<void> - refresh staking data
initialize, // (config: AuthConfig) => Promise<void> - initialize with config
// Computed values
canStake, // boolean - can perform staking
requiresStaking, // boolean - staking is required by config
// Utilities
getStakedAmount, // () => string - get staked amount
getUnstakedAmount, // () => string - get unstaked amount
getValidatorInfo, // () => ValidatorConfig | null - get validator info
} = useNEARLogin();For advanced multi-chain functionality:
import { useMultiChainAuth } from '@vitalpointai/near-login';
const multiChain = useMultiChainAuth({
config: nearConfig,
near: nearConnection,
selector: walletSelector
});import { useSimpleMultiChainAuth } from '@vitalpointai/near-login';
const {
isAuthenticated,
connectChain,
signAuthMessage
} = useSimpleMultiChainAuth(config, near, selector);interface UseNEARLogin {
// State
isLoading: boolean;
isConnected: boolean;
accountId: string | null;
isAuthenticated: boolean;
isStaked: boolean;
stakingInfo: StakingInfo | null;
sessionToken: string | null;
error: string | null;
config: AuthConfig | null;
// Actions
signIn: () => Promise<void>;
signOut: () => Promise<void>;
stake: (amount: string) => Promise<void>;
unstake: (amount: string) => Promise<void>;
refresh: () => Promise<void>;
initialize: (config: AuthConfig) => Promise<void>;
// Computed
canStake: boolean;
requiresStaking: boolean;
// Utilities
getStakedAmount: () => string;
getUnstakedAmount: () => string;
getValidatorInfo: () => ValidatorConfig | null;
}interface StakingInfo {
accountId: string;
stakedAmount: string; // Amount staked in yoctoNEAR
unstakedAmount: string; // Amount unstaked in yoctoNEAR
availableForWithdrawal: string; // Amount available for withdrawal in yoctoNEAR
rewards: string; // Rewards earned in yoctoNEAR
isStaking: boolean; // Whether currently staking
poolId: string; // Validator pool ID
}interface ToastNotification {
type: 'success' | 'error' | 'warning' | 'info';
title: string;
message: string;
duration?: number; // Display duration in milliseconds
}The library supports cross-chain authentication using NEAR's chain signature functionality with automatic MPC contract selection:
import {
useMultiChainAuth,
MultiChainAuthManager,
ChainSignatureContract,
MPC_CONTRACTS,
DEFAULT_CHAIN_CONFIGS
} from '@vitalpointai/near-login';
// MPC contracts are automatically selected based on network:
// Mainnet: 'v1.signer'
// Testnet: 'v1.signer-prod.testnet'
console.log(MPC_CONTRACTS.mainnet); // 'v1.signer'
console.log(MPC_CONTRACTS.testnet); // 'v1.signer-prod.testnet'
// Basic setup - contract ID is auto-selected based on networkId
const config = {
networkId: 'testnet', // or 'mainnet'
chainSignature: {
// contractId is automatically set to 'v1.signer-prod.testnet' for testnet
// or 'v1.signer' for mainnet
supportedChains: ['ethereum', 'bitcoin', 'solana'],
}
};
// Optional: Override with custom MPC contract
const customConfig = {
networkId: 'testnet',
chainSignature: {
contractId: 'my-custom-mpc.testnet', // Override default
supportedChains: ['ethereum', 'bitcoin'],
}
}
};
const multiChain = useMultiChainAuth({
config,
near: nearConnection,
selector: walletSelector
});
// Connect to multiple chains
await multiChain.connectMultipleChains(['ethereum', 'bitcoin']);
// Sign messages for different chains
const ethSignature = await multiChain.signAuthMessage('ethereum');
const btcSignature = await multiChain.signAuthMessage('bitcoin');The library automatically selects the correct MPC contract based on your network configuration:
// No need to specify contractId - automatically selected!
const config = {
nearConfig: { networkId: 'mainnet' }, // Uses 'v1.signer'
chainSignature: {
supportedChains: ['ethereum', 'bitcoin']
}
};
// Or for testnet
const testnetConfig = {
nearConfig: { networkId: 'testnet' }, // Uses 'v1.signer-prod.testnet'
chainSignature: {
supportedChains: ['ethereum', 'bitcoin']
}
};
// Access contract IDs directly if needed
import { MPC_CONTRACTS } from '@vitalpointai/near-login';
console.log(MPC_CONTRACTS.mainnet); // 'v1.signer'
console.log(MPC_CONTRACTS.testnet); // 'v1.signer-prod.testnet'The library provides various utility functions:
import {
formatNearAmount,
stakeTokens,
unstakeTokens,
getStakingInfo,
validateStakingAmount,
createNearConnection,
DEFAULT_NEAR_CONFIG,
getDefaultHelpTexts
} from '@vitalpointai/near-login';
// Format NEAR amounts
const formatted = formatNearAmount('1000000000000000000000000'); // "1 NEAR"
// Direct staking operations
await stakeTokens(near, 'validator.pool.near', '100');
await unstakeTokens(near, 'validator.pool.near', '50');
// Get staking information
const stakingInfo = await getStakingInfo(near, 'user.near', 'validator.pool.near');
// Validate stake amount
const isValid = validateStakingAmount('100', '1'); // amount >= minimum
// Create NEAR connection
const near = await createNearConnection(DEFAULT_NEAR_CONFIG.testnet);
// Get default help texts
const defaultTexts = getDefaultHelpTexts();
console.log(defaultTexts.walletConnection); // Default help text for wallet connection
console.log(defaultTexts.staking); // Default help text for staking
// Use with custom overrides
const customHelpTexts = {
...getDefaultHelpTexts(),
staking: "Your custom staking help text"
};You can customize the authentication flow with custom render functions:
<NEARLogin
config={config}
renderLoading={() => <div>Loading your custom spinner...</div>}
renderError={(error, retry) => (
<div>
<h2>Something went wrong!</h2>
<p>{error}</p>
<button onClick={retry}>Try Again</button>
</div>
)}
renderUnauthorized={(signIn, stake) => (
<div>
<h2>Welcome!</h2>
<button onClick={signIn}>Connect NEAR Wallet</button>
{stake && (
<button onClick={() => stake('100')}>
Stake 100 NEAR
</button>
)}
</div>
)}
>
<YourProtectedContent />
</NEARLogin>Explore complete examples in the /examples directory:
- educational-staking.tsx - Complete educational staking flow
- component-showcase.tsx - Individual educational components
- mpc-contract-demo.tsx - Automatic MPC contract selection demo
- simple-wallet.tsx - Simple wallet authentication
- required-staking.tsx - Required staking setup
import React from 'react';
import { NEARLogin, useNEARLogin } from '@vitalpointai/near-login';
// Protected content component
function Dashboard() {
const { accountId, isStaked, stakingInfo, stake, signOut } = useNEARLogin();
return (
<div>
<h1>Welcome, {accountId}!</h1>
{isStaked ? (
<div>
<p>β
Staking Status: Active</p>
<p>Staked Amount: {stakingInfo?.stakedAmount} yoctoNEAR</p>
<p>Validator: {stakingInfo?.poolId}</p>
</div>
) : (
<div>
<p>β Staking Required</p>
<button onClick={() => stake('100')}>
Stake 100 NEAR
</button>
</div>
)}
<button onClick={signOut}>Disconnect</button>
</div>
);
}
// Main app component with educational features
function App() {
const config = {
requireStaking: true,
validator: {
poolId: 'vitalpoint.pool.near',
minStake: '100',
displayName: 'VitalPoint Validator',
required: true
},
nearConfig: {
networkId: 'testnet'
},
walletConnectOptions: {
contractId: 'your-contract.testnet'
}
};
const handleToast = (toast) => {
// Handle toast notifications (integrate with your toast library)
console.log(`${toast.type}: ${toast.title} - ${toast.message}`);
};
return (
<NEARLogin
config={config}
onToast={handleToast}
// Educational features for better user onboarding
showHelp={true}
helpTexts={{
walletConnection: "Connect your NEAR wallet to access premium features. Your private keys never leave your wallet!",
staking: "This app requires staking 100 NEAR to access. You'll earn ~10% annual rewards on your staked tokens.",
stakingAmount: "Start with the minimum required amount. You can always add more later.",
rewards: "Rewards are automatically compounded and can be claimed anytime."
}}
showEducation={true}
educationTopics={['what-is-wallet', 'why-near', 'how-staking-works', 'security-tips']}
useGuidedStaking={true} // Use wizard instead of direct staking UI
>
<Dashboard />
</NEARLogin>
);
}
export default App;```tsx
// pages/_app.tsx or app/layout.tsx
import { NEARLogin } from '@vitalpointai/near-login';
export default function MyApp({ Component, pageProps }) {
const config = {
requireStaking: false, // Optional staking
nearConfig: {
networkId: 'mainnet'
}
};
return (
<NEARLogin config={config}>
<Component {...pageProps} />
</NEARLogin>
);
}// pages/protected.tsx import { useNEARLogin, ProtectedRoute } from '@vitalpointai/near-login';
function ProtectedPage() { const { isAuthenticated, accountId } = useNEARLogin();
if (!isAuthenticated) { return
return (
); }// Alternatively, use ProtectedRoute component function AltProtectedPage() { const config = { requireStaking: true, nearConfig: { networkId: 'mainnet' } };
return (
### Integration with Toast Libraries
```tsx
import { toast } from 'react-hot-toast'; // or your preferred toast library
import { NEARLogin } from '@vitalpointai/near-login';
function App() {
const handleToast = (notification) => {
switch (notification.type) {
case 'success':
toast.success(notification.message);
break;
case 'error':
toast.error(notification.message);
break;
case 'warning':
toast.warning(notification.message);
break;
default:
toast(notification.message);
}
};
return (
<NEARLogin
config={config}
onToast={handleToast}
>
<YourApp />
</NEARLogin>
);
}
## Development
### Setup
```bash
# Clone the repository
git clone https://github.com/VitalPointAI/NEAR-Login.git
cd NEAR-Login
# Install dependencies
pnpm install
# Start development server
pnpm dev
# Run tests
pnpm test
# Run tests in watch mode
pnpm test:watch
# Check test coverage
pnpm test:coverage
# Lint code
pnpm lint
# Build for production
pnpm build
src/
βββ components/ # React components
β βββ NEARLogin.tsx # Main authentication component
β βββ ProtectedRoute.tsx # Route protection component
βββ hooks/ # React hooks
β βββ useNEARLogin.ts # Main authentication hook
β βββ useMultiChainAuth.ts # Multi-chain authentication
βββ store/ # State management
β βββ auth.ts # Authentication store
βββ utils/ # Utility functions
β βββ near.ts # NEAR protocol utilities
β βββ multi-chain-auth.ts # Multi-chain functionality
β βββ chain-signature-contract.ts # Chain signature contract
βββ types/ # TypeScript type definitions
βββ index.ts # Main export file
The library includes comprehensive tests:
- Unit tests: Individual function and component testing
- Integration tests: Full authentication flow testing
- Hook tests: React hook behavior testing
- Multi-chain tests: Cross-chain functionality testing
Run tests with coverage:
pnpm test:coverageThe build process generates:
- ESM bundle (
dist/index.js) - Modern ES modules - CommonJS bundle (
dist/index.cjs) - Node.js compatibility - TypeScript declarations (
dist/index.d.ts) - Full type support
// β Incorrect - flat props
<NEARLogin networkId="testnet" contractId="test.near" />
// β
Correct - config object
<NEARLogin config={{ networkId: 'testnet', contractId: 'test.near' }} /># Install required peer dependencies
npm install react react-dom @near-wallet-selector/core @near-wallet-selector/my-near-wallet- Check browser localStorage availability
- Ensure
maxAgeis set appropriately in config - Verify no browser privacy settings blocking storage
- Verify validator pool ID is correct
- Check minimum stake amount configuration
- Ensure validator pool is active and accepting delegations
Enable debug logging by setting the environment variable:
# For Vite/React apps
VITE_DEBUG_NEAR_LOGIN=true npm start
# For Next.js apps
DEBUG_NEAR_LOGIN=true npm run dev- Modern browsers: Chrome 88+, Firefox 78+, Safari 14+, Edge 88+
- Required features: ES2020, LocalStorage, Fetch API, WebCrypto
- Polyfills: May be needed for older browsers
We welcome contributions! Here's how to get started:
- Fork the repository and create a feature branch
- Follow the coding standards: ESLint and Prettier configs provided
- Write tests for new features and bug fixes
- Update documentation including README and JSDoc comments
- Test your changes with
pnpm testandpnpm lint - Submit a pull request with a clear description of changes
- TypeScript: Use strict TypeScript with full type coverage
- React: Use modern hooks and functional components
- Testing: Jest and React Testing Library for all tests
- Linting: ESLint with TypeScript rules
- Formatting: Prettier for consistent code formatting
# 1. Fork and clone
git clone https://github.com/your-username/NEAR-Login.git
cd NEAR-Login
# 2. Create feature branch
git checkout -b feature/your-feature-name
# 3. Install dependencies
pnpm install
# 4. Make changes and test
pnpm test
pnpm lint
# 5. Commit and push
git commit -m "feat: add your feature"
git push origin feature/your-feature-name
# 6. Create pull requestThis project uses automated releases:
- Version bumping: Automatic semantic versioning
- Testing: All tests must pass before release
- Building: Automated build and type generation
- Publishing: Automatic npm publishing on merge to main
- GitHub Releases: Automated release notes generation
MIT License - see LICENSE file for details.
- π Documentation: This README and inline code documentation
- π Issues: Report bugs on GitHub Issues
- π‘ Feature Requests: Use GitHub Issues with the
enhancementlabel - π§ Contact: Open an issue for questions and support
Critical TypeScript Fix:
- TypeScript Compiler Recognition: Fixed issue where TypeScript compiler incorrectly interpreted
NEARLoginPropsinterface - Component Export Enhancement: Added alternative
NEARLoginComponentexport for improved TypeScript compatibility - Interface Declaration: Enhanced component typing to ensure TypeScript properly recognizes the
configprop interface - Development Experience: Eliminates TypeScript errors when using
<NEARLogin config={authConfig}>syntax
What This Fixes:
Type 'IntrinsicAttributes & AuthConfig' is not assignable to type 'NEARLoginProps'TypeScript errors- TypeScript compiler incorrectly expecting
AuthConfigproperties directly instead of wrapped inconfigprop - IDE/Editor TypeScript warnings about component interface mismatches
- Module export/import TypeScript resolution issues
Usage Notes:
- Use
NEARLogin(recommended) orNEARLoginComponentfor maximum compatibility - All existing code continues to work unchanged
- Better TypeScript IntelliSense support in IDEs
Critical Fixes:
- TypeScript Interface Mismatch: Resolved duplicate
NEARLoginPropsinterfaces causing compilation errors - Runtime Safety: Added null/undefined checks for config parameter to prevent "Cannot read properties of undefined" errors
- Component Safety: Enhanced error boundaries with meaningful error messages when configuration is missing
- Export/Import Consistency: Fixed type definition conflicts between .d.ts files and component implementations
What This Fixes:
TypeError: Cannot read properties of undefined (reading 'sessionConfig')- TypeScript compiler rejecting valid
<NEARLogin config={authConfig}>syntax - Component crashes when config prop is undefined
- Interface mismatches in TypeScript projects
Backward Compatibility: All existing working code continues to function unchanged.
New Features:
- Educational Components: Added
WalletEducation,EducationTooltip, andGuidedStakingWizardcomponents - Enhanced NEARLogin: New props
showHelp,helpTexts,showEducation,educationTopics, anduseGuidedStaking - Progressive Onboarding: Step-by-step education flow for crypto beginners
- Guided Staking Wizard: Three-step wizard to simplify the staking process
- Contextual Help: Tooltips and help text throughout the UI
Improvements:
- Better user experience for Web3 newcomers
- Reduced cognitive load with progressive disclosure
- Improved accessibility with proper ARIA labels
- Mobile-responsive educational components
See CHANGELOG.md for complete version history and breaking changes.
π Ready to build? Check out the examples directory for more usage patterns and integration guides.