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-login
This library requires React as a peer dependency:
npm install react react-dom
All 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:
ProtectedRoute
must be used within aNEARLogin
component 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:coverage
The 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
maxAge
is 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 test
andpnpm 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 request
This 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
enhancement
label - π§ Contact: Open an issue for questions and support
Critical TypeScript Fix:
- TypeScript Compiler Recognition: Fixed issue where TypeScript compiler incorrectly interpreted
NEARLoginProps
interface - Component Export Enhancement: Added alternative
NEARLoginComponent
export for improved TypeScript compatibility - Interface Declaration: Enhanced component typing to ensure TypeScript properly recognizes the
config
prop 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
AuthConfig
properties directly instead of wrapped inconfig
prop - IDE/Editor TypeScript warnings about component interface mismatches
- Module export/import TypeScript resolution issues
Usage Notes:
- Use
NEARLogin
(recommended) orNEARLoginComponent
for maximum compatibility - All existing code continues to work unchanged
- Better TypeScript IntelliSense support in IDEs
Critical Fixes:
- TypeScript Interface Mismatch: Resolved duplicate
NEARLoginProps
interfaces 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
, andGuidedStakingWizard
components - 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.