Making payments as simple as sharing a link - powered by Neon EVM's Solana composability
TipCard enables users to create shareable payment links for instant SOL payments on Solana. Built with Neon EVM's composability features and Solana Native SDK, it offers ultra-low fees, actual SOL transfers, and native Solana wallet integration while providing the familiar Ethereum development experience.
- Real SOL Transfers: Actual SOL debiting/crediting using Solana's SystemProgram
- Solana Native SDK: Direct Solana wallet integration (Phantom, Solflare)
- Two-Step Payment: SOL transfer + contract recording for transparency
- Ultra-Low Fees: ~$0.0001 per transaction on Solana
- Smart Caching: 5-minute payment history cache with localStorage
- Toast Notifications: Modern UX with success/error feedback
- URL-based Routing: Automatic tab switching via payment links
- Dynamic UI: Real-time balance checks and airdrop functionality
- Sending crypto payments requires complex wallet addresses
- High gas fees make small payments uneconomical
- Cross-chain payments require complicated bridging
- Poor user experience for crypto newcomers
TipCard makes crypto payments as simple as sharing a link:
- Create: Connect Solana wallet, set amount, generate payment link
- Share: Copy link and share anywhere - social media, messaging, QR codes
- Pay: Recipients click link, connect Solana wallet, pay instantly with SOL
npm installnpx hardhat run scripts/deploy-solana-tipcard.js --network neondevnetcd frontend
npm install
npm run devVisit http://localhost:3000 to use the application.
npx hardhat test mocha ./test/tipcard-test.js --network neondevnetThe contract leverages Neon EVM's powerful precompiles for direct Solana integration:
| Precompile | Address | Purpose |
|---|---|---|
| ISPLTokenProgram | 0xFf00000000000000000000000000000000000004 |
Direct SPL token operations |
| ISolanaNative | 0xfF00000000000000000000000000000000000007 |
Solana address conversion & user registration |
| ICallSolana | 0xFF00000000000000000000000000000000000006 |
Advanced Solana program calls |
βββ contracts/
β βββ SolanaTipCard.sol # Main contract with Neon composability
β βββ precompiles/ # Neon precompile interfaces
β β βββ ISPLTokenProgram.sol
β β βββ ISolanaNative.sol
β β βββ ICallSolana.sol
β βββ utils/ # Helper libraries
βββ frontend/ # Next.js frontend application
β βββ app/ # Next.js 14 app directory
β βββ components/ # React components
β β βββ SimplePaymentLink.tsx # Payment link creation
β β βββ SimplePaymentProcessor.tsx # Payment processing
β β βββ MyLinks.tsx # Link management with caching
β β βββ Toast.tsx # Toast notification system
β β βββ Header.tsx # Application header
β βββ utils/ # Utility functions
β β βββ solana-native-contract.ts # Solana Native SDK integration
β β βββ simple-wallet-signer.ts # Wallet utilities
β βββ package.json
βββ scripts/
β βββ deploy-solana-tipcard.js # Contract deployment
βββ test/
β βββ solana-tipcard.test.js # Comprehensive tests
βββ types/ # TypeScript contract types- SOL-Only Payments: Simplified to only support native SOL for better UX
- Flexible Amounts: Fixed or user-determined payment amounts
- Link Management: Create, activate, deactivate payment links
- Cross-Chain Architecture: EVM contract orchestrating Solana operations
- Real-time Updates: Track payments and statistics
- User Registration: Automatic Solana user registration via Neon Native SDK
- Event Logging: Complete audit trail with SolanaLinkCreated and SolanaPaymentReceived events
struct SolanaPaymentLink {
address evmCreator; // EVM address of creator
bytes32 solanaCreator; // Solana address of creator (bytes32)
uint64 amount; // Amount in SOL lamports
bool isFlexible; // Allow flexible payment amounts
bool isActive; // Link activation status
uint64 totalReceived; // Total SOL received
uint32 paymentCount; // Number of payments
string description; // Payment description
}1. Frontend: SOL Transfer (SystemProgram.transfer)
βββ From: Payer's Solana wallet
βββ To: Recipient's Solana address
βββ Amount: Payment amount in lamports
2. Contract: Payment Recording (paySolanaLink)
βββ Updates: totalReceived, paymentCount
βββ Emits: SolanaPaymentReceived event
βββ Validates: Link exists and is active- Smart Caching: 5-minute localStorage cache for payment history with BigInt serialization
- Toast Notifications: Modern notification system replacing all alert() calls
- URL-based Navigation: Automatic tab switching when payment links are shared
- SOL Balance Integration: Real-time balance checks with airdrop functionality
- Error Handling: Comprehensive error handling with user-friendly messages
- Retry Mechanisms: Robust transaction processing with automatic retries
- Frontend: Next.js 14, React 18, TypeScript
- Styling: Tailwind CSS with custom theme
- Blockchain: Ethers.js for contract interaction
- Solana: @solana/web3.js + Solana Wallet Adapter
- Neon Integration: @neonevm/solana-sign (Solana Native SDK)
- Wallets: Phantom, Solflare, and other Solana wallets
- Icons: Lucide React
- State Management: React Context for toast notifications
- Caching: localStorage with TTL and BigInt serialization
- Creates payment links using Solana Native SDK
- Real-time SOL balance checking with airdrop integration
- Handles user registration with Neon EVM
- Generates shareable payment URLs with precise amount handling
- Processes payments with two-step approach
- Performs actual SOL transfers via SystemProgram
- Records payments in smart contract for tracking
- Supports both contract-based and demo payment links
- Smart caching system with 5-minute TTL
- BigInt serialization for localStorage compatibility
- SolanaβEVM address mapping for cache lookup
- Real-time refresh functionality with loading states
- Comprehensive notification system
- Success, error, and warning states with animations
- Context-based state management
- Auto-dismiss with customizable duration
# Run all tests
npx hardhat test mocha ./test/tipcard-test.js --network neondevnetSingle Wallet Solana TipCard Test
π Setting up Single Wallet Test...
π Decrypting keystore secrets...
NeonEVM owner address: 0xcf2A070357979D8Fa7c99F66ca43c6e0938F2403
NeonEVM user1 address: 0x02e47d2E10ac4024416703A9dde9057889C80222
NeonEVM user2 address: 0x8d39Fc73D7aa439B4ef773FF877223D32ED44068
Solana user1 address: GsWeXfqrmGLkN3fFUu5bdoDPDWJLf5LzAWjNfvctLuA6
Solana user2 address: C99PbkmvvkGVAhFXUab7Uj3Bzj3GvX4eSQ7FswtZBUQh
π Connecting to SolanaTipCard at: 0xCFE03c7c67456D094C0162F9030393FC2cCc40Cb
π Creating Solana payment link with first wallet...
Creator: 0x58ca66661ae3488f330aa66edc6f14e5a3ffc5f6
Current nonce: 12
β
User1: Solana GsWeXfqr... β EVM 0x58ca66...
Chain ID: 245022927
β
Transaction submitted!
π Signature: 31ATNNqVWYVwL5iQXxLvNwWRMcBUzQNtjqAG8CNfGTyxzbe71D1RG4ZCTANaSeGEMsiHniPwQm9PJx75znivpJaU
β
Transaction status: confirmed
β
Neon EVM transaction hash: 0x3b083c0a759bd9eb6d41f48422ec43608794c179a1b7f7899059b6b1a4f27b6a
β
Found 12 payment link(s) for this user!
Latest Link ID: 0x515ed5bad1fa34ad204e6a860dabc1c8da51a89118db65e31855bb6733e1e23a
π Payment Link Details:
Link ID: 0x515ed5bad1fa34ad204e6a860dabc1c8da51a89118db65e31855bb6733e1e23a
Creator EVM: 0x58ca66661aE3488f330Aa66EdC6F14e5A3FFc5F6
Creator Solana: 0xebcfddcaa195beb5390a5288d08d9ba9f34084e0b4224b0c752730feb510eca7
Amount: 0.5 SOL
Flexible: false
Active: true
Description: Payment link for testing
β Should create a Solana payment link using first wallet (31734ms)
π³ Paying created payment link with second wallet...
Payer: 0xab8d93b6dabb01953cf6c0360993ced34177e2ce
β
User2: Solana C99Pbkmv... β EVM 0xab8d93...
Current nonce: 6
β
Payment transaction submitted!
π Signature: 5zRFP9H8KT1EHABtdbNYVXfXc6DgtGvyizzd3WB14D47UuSorUGr9T7xyVeeo5pmCCMdqWCXTfZXQaS6jjfhvq23
π Payment transaction completed!
β Should pay the created payment link using second wallet (26768ms)
π Fetching all payment links for first user...
β
Found 12 payment link(s) for this user
π Link 12 (Latest):
Link ID: 0x515ed5bad1fa34ad204e6a860dabc1c8da51a89118db65e31855bb6733e1e23a
Amount: 0.5 SOL
Total Received: 0.5 SOL
Payment Count: 1
Description: "Payment link for testing"
π Verifying latest link matches created link:
β
Latest link matches the created link!
β Should fetch all payment links created by the first user (58478ms)
π€ Verifying both users initialization...
β
User1 EVM address: 0x58ca66661ae3488f330aa66edc6f14e5a3ffc5f6
β
User1 Solana address: GsWeXfqrmGLkN3fFUu5bdoDPDWJLf5LzAWjNfvctLuA6
β
User2 EVM address: 0xab8d93b6dabb01953cf6c0360993ced34177e2ce
β
User2 Solana address: C99PbkmvvkGVAhFXUab7Uj3Bzj3GvX4eSQ7FswtZBUQh
β
Chain ID: 245022927
β Should verify both users are properly initialized
π° Checking SOL balances...
User1 SOL balance: 1.871328415 SOL
User2 SOL balance: 7.995560083 SOL
β
Both users have sufficient SOL balance
β Should check both users' SOL balances (4021ms)
π Single Wallet Test Summary:
β
Two Solana users successfully initialized
β
Solana Native SDK integration working perfectly
β
Two-wallet payment flow implemented
β
Payment link creation and payment flow verified
β
Ready for production use
π Architecture Confirmed:
β’ β
Two Solana wallet approach working
β’ β
Proper EVM address derivation from Solana keypair
β’ β
Direct Solana wallet signing
β’ β
Payment link creation and payment flow
β’ β
Solana Native SDK correctly integrated
5 passing (2m)β
Contract deployment and initialization
β
Payment link creation with SOL
β
Solana payment processing
β
Link management (activate/deactivate)
β
Error handling and validation
β
Neon composability integration
β
User registration flow
β
Two-step payment verification
β
Event parsing and link ID extraction
β
Precision handling for SOL amounts
β
Multi-wallet interaction testing
β
Cross-chain address derivation
| Network | Address |
|---|---|
| Neon Devnet | 0xCFE03c7c67456D094C0162F9030393FC2cCc40Cb |
// Initialize Solana Native SDK
await solanaNativeContract.initWithSolanaWallet(wallet.adapter);
// Create fixed SOL payment link with precise amount handling
const result = await solanaNativeContract.createPaymentLink(
5.0, // 5 SOL (uses ethers.parseUnits for precision)
false, // Fixed amount
"Coffee tip"
);
console.log('Link ID:', result.linkId);
console.log('Transaction:', result.txHash);
// Create flexible payment link
const flexibleResult = await solanaNativeContract.createPaymentLink(
1.0, // Suggested amount
true, // Flexible
"Support our project"
);// Pay a payment link (two-step process)
const paymentResult = await solanaNativeContract.payLink(
linkId, // Payment link ID
10.0 // Amount in SOL
);
console.log('SOL Transfer:', paymentResult.transferSignature);
console.log('Contract Record:', paymentResult.txHash);// Smart caching with 5-minute TTL
const cachedData = loadFromCache(userAddress);
if (cachedData && isCacheValid(cachedData, userAddress)) {
// Load from cache
const displayLinks = cachedData.links.map(linkFromCache);
setLinks(displayLinks);
} else {
// Fetch fresh data
await fetchFromContract(userAddress);
}
// Toast notifications
showToast('success', 'Payment Successful!', 'Your payment has been sent successfully.');
showToast('error', 'Transaction Failed', 'Please check your balance and try again.');- Social Media Tips: Share payment links on Twitter, Discord
- Live Stream Donations: QR codes for instant viewer tips
- Content Monetization: Direct supporter payments
- Service Tips: Restaurant, delivery, service industry
- Freelancer Payments: Quick invoice and payment collection
- E-commerce: Instant payment processing
- DAO Contributions: Member dues and donations
- Group Expenses: Split bills and shared costs
- Yield Farming: Collect management and performance fees
- Solana transaction fees: ~$0.0001
- No bridging or wrapping costs
- Viable for micro-payments and tips
- Solana's ~400ms block times
- Instant payment confirmation
- No cross-chain delays
- Actual SOL debiting/crediting
- Direct SystemProgram transfers
- No wrapped tokens or IOUs
- Toast notifications for all actions
- Smart caching prevents redundant fetches
- URL-based navigation for seamless sharing
- Real-time balance checks and airdrop functionality
- Precise amount handling (no more 0.9960 vs 1.0 issues)
- Familiar Ethereum/Solidity development
- Rich TypeScript support
- Comprehensive testing framework
- Solana Native SDK integration
- Clean error handling without verbose logging
- Input Validation: SOL amount and address verification with ethers.parseUnits
- Access Control: Creator-only link management
- State Management: Proper active/inactive controls
- Two-Step Payment: SOL transfer + contract verification
- Error Handling: Custom errors with clear messages
- Audit Trail: Complete event logging for transparency
- User Registration: Automatic Solana user registration validation
- Nonce Management: Proper transaction ordering and conflict resolution
- Retry Mechanisms: Robust transaction processing with automatic retries
-
Install Dependencies:
npm install cd frontend && npm install
-
Configure Secrets:
# Set up Hardhat keystore (recommended) npx hardhat keystore set PRIVATE_KEY_OWNER npx hardhat keystore set PRIVATE_KEY_SOLANA
-
Deploy Contract:
npx hardhat run scripts/deploy-solana-tipcard.js --network neondevnet
-
Update Frontend Config:
# Update .env file with deployed contract address echo "NEXT_PUBLIC_TIPCARD_CONTRACT_ADDRESS=0x..." > frontend/.env echo "NEXT_PUBLIC_NEON_RPC_URL=https://devnet.neonevm.org" >> frontend/.env
-
Run Frontend:
cd frontend npm run dev
The project is configured for Neon EVM Devnet:
// hardhat.config.js
networks: {
neondevnet: {
url: "https://devnet.neonevm.org/sol",
accounts: [], // Uses keystore
chainId: 245022926,
allowUnlimitedContractSize: false,
gasMultiplier: 2,
maxFeePerGas: '10000000000000',
maxPriorityFeePerGas: '5000000000000'
}
}- Toast Notification System: Modern notifications replacing all alert() calls
- Smart Tab Detection: Automatic navigation based on URL parameters
- Dynamic Footer: Auto-updating copyright year
- Loading States: Improved feedback for all async operations
- Smart Caching: 5-minute localStorage cache with BigInt serialization
- Precision Fixes: Resolved SOL amount precision issues using ethers.parseUnits
- Event Parsing: Extract actual link IDs from SolanaLinkCreated events
- Retry Mechanisms: Robust transaction processing with automatic retries
- Error Handling: Maintained important error logs while removing verbose debugging
- SolanaβEVM Mapping: Efficient cache lookup using address mapping
- Cache-First Loading: Prevent redundant API calls with intelligent caching
- URL-based Routing: Deep linking support for payment links
- Nonce Management: Proper transaction ordering and conflict resolution
// Initialize with Solana wallet
const proxyApi = new NeonProxyRpcApi('https://devnet.neonevm.org/sol');
const initResult = await proxyApi.init(walletPublicKey);
// Automatic user registration
const solanaUser = initResult.solanaUser;
const isRegistered = await contract.isSolanaUser(solanaUser.neonWallet);1. User clicks payment link (auto-switches to Pay tab)
β
2. Frontend loads link details from contract (with caching)
β
3. User connects Solana wallet
β
4. Real-time SOL balance check with airdrop option
β
5. Frontend creates SOL transfer transaction
β
6. User signs transaction with wallet
β
7. SOL transfer executes on Solana
β
8. Frontend calls contract to record payment
β
9. Contract updates statistics and emits event
β
10. Toast notification confirms successinterface CachedData {
links: CachedDisplayLink[]
timestamp: number
userAddress: string
solanaPublicKey: string
}
// BigInt serialization helpers
const linkToCache = (link: DisplayLink): CachedDisplayLink => ({
...link,
amount: link.amount.toString(),
totalReceived: link.totalReceived.toString()
})
const linkFromCache = (cached: CachedDisplayLink): DisplayLink => ({
...cached,
amount: BigInt(cached.amount),
totalReceived: BigInt(cached.totalReceived)
})// Extract actual link ID from contract events
for (let attempt = 1; attempt <= 5; attempt++) {
const receiptResult = await getTransactionReceipt(neonTxHash);
if (receiptResult?.logs) {
for (const log of receiptResult.logs) {
const decoded = iface.parseLog(log);
if (decoded?.name === 'SolanaLinkCreated') {
return { linkId: decoded.args.linkId, txHash: neonTxHash };
}
}
break; // Receipt exists but no event
}
if (attempt < 5) await new Promise(resolve => setTimeout(resolve, 5000));
}class SolanaNativeContract {
// Initialize with Solana wallet
async initWithSolanaWallet(walletAdapter: any): Promise<void>
// Create payment link with event parsing
async createPaymentLink(
amountSOL: number,
isFlexible: boolean,
description: string
): Promise<{linkId: string, txHash: string}>
// Process payment (two-step: SOL transfer + contract recording)
async payLink(
linkId: string,
amountSOL: number
): Promise<{txHash: string, transferSignature?: string}>
// Get payment link details
async getPaymentLink(linkId: string): Promise<PaymentLink>
// Get user's links with caching support
async getUserLinks(userEVMAddress: string): Promise<string[]>
// Deactivate link
async deactivateLink(linkId: string): Promise<{txHash: string}>
// Create shareable URL
createPaymentURL(linkId: string): string
// Extract link ID from URL
static extractLinkIdFromURL(url: string): string | null
// Get user's EVM address
getUserEVMAddress(): string | null
}interface Toast {
id: string
type: 'success' | 'error' | 'warning'
title: string
message?: string
duration?: number
}
// Usage
const { showToast } = useToast()
showToast('success', 'Payment Successful!', 'Your payment has been sent.')
showToast('error', 'Transaction Failed', 'Please check your balance.')
showToast('warning', 'Low Balance', 'Consider getting more SOL for fees.')- Fork the repository
- Create feature branch:
git checkout -b feature/amazing-feature - Make changes and add tests
- Commit changes:
git commit -m 'Add amazing feature' - Push to branch:
git push origin feature/amazing-feature - Open Pull Request
- Follow TypeScript best practices
- Add tests for new features
- Update documentation
- Ensure SOL transfers work correctly
- Test with multiple Solana wallets
- Maintain important error logs
- Use toast notifications for user feedback
- Implement proper caching where beneficial
This project is licensed under the MIT License - see the LICENSE file for details.
- Neon EVM Team - For composability precompiles and Solana Native SDK
- Solana Foundation - For the underlying blockchain technology
- Next.js Team - For the incredible React framework
- Solana Wallet Adapter - For seamless wallet integration
Built with β€οΈ for the Solana ecosystem using Neon EVM's composability features
Making payments as simple as sharing a link - with real SOL transfers and modern UX.
Β© 2025 TipCard. Built with Neon EVM and Solana.