1. Visit Chrome Web Store
2. Search for "Cland"
3. Click "Add to Chrome"
4. Confirm installation
5. Pin extension to toolbar1. Download source code from GitHub
2. Extract to local directory
3. Open Chrome Extensions (chrome://extensions/)
4. Enable "Developer mode"
5. Click "Load unpacked"
6. Select the `dist-extension` folder
7. Extension appears in toolbar5KJvsngHeMpm884wtkJNzQGaCErckhHJBGFsvd3VyK5qMZpJ85n
3WUX7GvHfnujuKvzdPHjHLpNnguGgdGKRiLHodk17VoS
2B5VsY98Rlann35t19J2AB1yms5MiH8PxMV6Qpn3GpkKMainnet: https://api.mainnet-beta.solana.com
Helius: https://rpc.helius.xyz/?api-key=YOUR_KEY
QuickNode: https://your-endpoint.solana-mainnet.quiknode.pro/TOKEN/// Supported RPC Providers
const rpcProviders = {
mainnet: "https://api.mainnet-beta.solana.com",
helius: "https://rpc.helius.xyz/?api-key=",
quicknode: "https://endpoint.solana-mainnet.quiknode.pro/",
custom: "YOUR_CUSTOM_ENDPOINT"
}// Private keys are never stored permanently
const temporaryKeyStorage = {
location: "Browser Memory",
encryption: "Chrome Extension Sandbox",
persistence: "Session Only",
transmission: "Never"
}{
"manifest_version": 3,
"permissions": ["storage"],
"content_security_policy": {
"extension_pages": "script-src 'self' 'wasm-unsafe-eval'; object-src 'self'"
}
}Base Transaction Fee: 0.000005 SOL (~$0.0001)
Priority Fee (Optional): 0.00001-0.0001 SOL
Account Rent: 0.00203928 SOL per account
Close Account Refund: Full rent amount returnedScanning Phase: 0 SOL (read-only operations)
Collection Phase: 0.000005 SOL per transaction
Token Account Closure: 0.000005 SOL per account
Net Cost: ~0.00001 SOL per wallet with collectible rentTotal Scanning: Free
Total Collection: ~0.0001 SOL ($0.002)
Expected Rent Recovery: ~0.02039 SOL ($0.40)
Net Profit: ~0.02029 SOL ($0.398)
ROI: ~98.5%Total Scanning: Free
Total Collection: ~0.001 SOL ($0.02)
Expected Rent Recovery: ~0.2039 SOL ($4.00)
Net Profit: ~0.2029 SOL ($3.98)
ROI: ~99.5%Total Scanning: Free
Total Collection: ~0.01 SOL ($0.20)
Expected Rent Recovery: ~2.039 SOL ($40.00)
Net Profit: ~2.029 SOL ($39.80)
ROI: ~99.5%Cland Extension
├── Popup Interface (React)
├── Storage Service (Chrome API)
├── Wallet Manager (Solana Web3)
├── Rent Collector (Core Logic)
└── Utilities (Helpers)class WalletManager {
// Load wallets from file content
static async loadWalletsFromContent(content: string): Promise<WalletInfo[]>
// Validate private key format
static validatePrivateKey(privateKey: string): boolean
// Create Keypair from private key
static createKeypairFromPrivateKey(privateKey: string): Keypair
// Get wallet public key
static getPublicKey(privateKey: string): PublicKey
}class RentCollector {
// Scan wallets for rent
async scanWallets(
wallets: WalletInfo[],
onProgress?: (progress: ProcessingProgress) => void
): Promise<void>
// Collect rent from accounts
async collectRent(
feePayerPrivateKey: string,
onProgress?: (progress: ProcessingProgress) => void
): Promise<RentCollectionSummary>
// Get collection statistics
getStats(): RentCollectionSummary
}class StorageService {
// Save configuration
static async saveConfig(config: ExtensionConfig): Promise<void>
// Load configuration
static async loadConfig(): Promise<ExtensionConfig>
// Clear all data
static async clearConfig(): Promise<void>
}interface WalletInfo {
privateKey: string;
publicKey: string;
balance: number;
tokenAccounts: TokenAccountInfo[];
rentEligibleAccounts: TokenAccountInfo[];
totalRent: number;
status: 'pending' | 'scanning' | 'scanned' | 'collecting' | 'collected' | 'error';
}interface TokenAccountInfo {
address: string;
mint: string;
balance: number;
decimals: number;
rentEpoch: number;
executable: boolean;
owner: string;
lamports: number;
data: {
parsed: {
info: {
isNative: boolean;
mint: string;
owner: string;
state: string;
tokenAmount: {
amount: string;
decimals: number;
uiAmount: number;
};
};
type: string;
};
program: string;
space: number;
};
}interface ProcessingProgress {
current: number;
total: number;
wallet: string;
status: string;
}// vite-extension.config.ts
export default defineConfig({
build: {
outDir: 'dist-extension',
rollupOptions: {
input: {
popup: resolve(__dirname, 'popup.html')
}
}
},
define: {
global: 'globalThis',
'process.env': {}
},
resolve: {
alias: {
buffer: 'buffer'
}
},
optimizeDeps: {
exclude: ['@solana/web3.js']
}
});{
"compilerOptions": {
"target": "ES2020",
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"moduleResolution": "bundler",
"types": ["chrome", "node", "react", "react-dom"]
},
"include": [
"popup/**/*",
"services/**/*",
"utils/**/*",
"types/**/*"
]
}┌─────────────────────────────────────┐
│ [C] Cland │
│ Solana Rent Recovery │
└─────────────────────────────────────┘┌─────────────────────────────────────┐
│ ○ Load ○ Scan ○ Collect │
└─────────────────────────────────────┘┌─────────────────────────────────────┐
│ RPC Endpoint: [________________] │
│ Fee Payer: [________________] │
│ [Save Settings] │
└─────────────────────────────────────┘┌─────────────────────────────────────┐
│ [Choose Files] or drag & drop │
│ Supported: .txt files │
│ Status: 0 wallets loaded │
└─────────────────────────────────────┘┌─────────────────────────────────────┐
│ [Scan Wallets] │
│ Progress: ████████░░ 80% │
│ Status: Scanning wallet 8/10 │
└─────────────────────────────────────┘┌─────────────────────────────────────┐
│ Total Wallets: 100 │
│ With Rent: 45 │
│ Available Rent: 0.9234 SOL │
│ Est. Fees: 0.0012 SOL │
│ Net Profit: 0.9222 SOL │
└─────────────────────────────────────┘┌─────────────────────────────────────┐
│ [Collect Rent] │
│ Progress: ██████░░░░ 60% │
│ Collected: 15/45 wallets │
│ Success: 14 Failed: 1 │
└─────────────────────────────────────┘:root {
--background-color: #0a0a0a; /* Deep black */
--surface-color: #1a1a1a; /* Dark gray */
--surface-hover: #2a2a2a; /* Lighter gray */
--border-color: #333333; /* Border gray */
--border-hover: #444444; /* Hover border */
--text-color: #ffffff; /* Pure white */
--text-secondary: #b0b0b0; /* Light gray */
--accent-color: #4299e1; /* Blue accent */
--accent-hover: #3182ce; /* Darker blue */
--success-color: #48bb78; /* Green success */
--error-color: #f56565; /* Red error */
--warning-color: #ed8936; /* Orange warning */
}/* Primary heading */
h1 {
font-size: 2rem;
font-weight: 700;
letter-spacing: -0.025em;
}
/* Body text */
body {
font-family: 'Inter', -apple-system, system-ui, sans-serif;
font-size: 0.875rem;
line-height: 1.5;
font-weight: 400;
}
/* Labels */
label {
font-size: 0.75rem;
font-weight: 500;
text-transform: uppercase;
letter-spacing: 0.05em;
}.card {
background: var(--surface-color);
border: 1px solid var(--border-color);
border-radius: 12px;
padding: 1.5rem;
transition: all 0.2s ease;
}
.card:hover {
background: var(--surface-hover);
border-color: var(--border-hover);
}.btn-primary {
background: var(--accent-color);
color: white;
border: 1px solid var(--accent-color);
border-radius: 8px;
padding: 0.75rem 1.5rem;
font-weight: 500;
transition: all 0.2s ease;
}
.btn-primary:hover {
background: var(--accent-hover);
transform: translateY(-1px);
}# Processing large wallet sets
Max Wallets: 10,000+ per session
Batch Size: 20 operations per transaction
Memory Usage: ~50MB for 1000 wallets
Processing Time: ~1 second per wallet// Advanced RPC settings
const rpcConfig = {
endpoint: "https://your-custom-rpc.com",
commitment: "confirmed",
timeout: 30000,
retries: 3,
priorityFees: true
}// Multi-network support
const networks = {
mainnet: "https://api.mainnet-beta.solana.com",
devnet: "https://api.devnet.solana.com",
testnet: "https://api.testnet.solana.com",
localnet: "http://localhost:8899"
}# Organized file structure
wallet-files/
├── mainnet/
│ ├── batch-001.txt
│ ├── batch-002.txt
│ └── batch-003.txt
├── devnet/
│ └── test-wallets.txt
└── processed/
├── completed-001.txt
└── completed-002.txt// Operation logging
interface OperationLog {
timestamp: number;
walletCount: number;
rentCollected: number;
feesSpent: number;
netProfit: number;
successRate: number;
}// Custom RPC endpoints
const customRPC = {
helius: "https://rpc.helius.xyz/?api-key=YOUR_KEY",
quicknode: "https://endpoint.solana-mainnet.quiknode.pro/TOKEN/",
alchemy: "https://solana-mainnet.g.alchemy.com/v2/API_KEY",
triton: "https://your-triton-endpoint.com"
}// Performance configuration
const performanceConfig = {
batchSize: 20, // Operations per transaction
concurrency: 5, // Parallel requests
retryAttempts: 3, // Error recovery
timeoutMs: 30000, // Request timeout
progressThrottle: 100 // UI update frequency
}Symptoms: Extension icon missing or grayed out
Causes: Browser compatibility, corrupted download
Solution:
1. Update Chrome to latest version
2. Clear browser cache and cookies
3. Disable other extensions temporarily
4. Reinstall extension from fresh downloadSymptoms: "Extension blocked" messages
Causes: Browser security settings, admin restrictions
Solution:
1. Check browser security settings
2. Add extension to allowed list
3. Contact system administrator if on managed deviceSymptoms: "Invalid file format" error
Causes: Wrong file type, encoding issues
Solution:
1. Ensure file is plain text (.txt)
2. Check UTF-8 encoding
3. Verify one private key per line
4. Remove extra spaces or charactersSymptoms: "Invalid private key" warnings
Causes: Incorrect key format, corrupted data
Solution:
1. Verify base58 encoding
2. Check key length (32 bytes)
3. Test keys in other Solana tools
4. Re-export from original sourceSymptoms: "Failed to connect to RPC" error
Causes: Network issues, wrong endpoint, rate limiting
Solution:
1. Check internet connection
2. Verify RPC endpoint URL
3. Try alternative RPC provider
4. Check firewall settingsSymptoms: Frequent "Too many requests" errors
Causes: Exceeded RPC provider limits
Solution:
1. Reduce batch size in operations
2. Add delays between requests
3. Upgrade to premium RPC service
4. Use multiple RPC endpointsSymptoms: "Transaction failed" with fee errors
Causes: Fee payer wallet has insufficient SOL
Solution:
1. Check fee payer balance
2. Add more SOL to fee payer wallet
3. Reduce batch size to lower fees
4. Use lower priority feesSymptoms: Transactions taking too long or failing
Causes: High network traffic, low priority fees
Solution:
1. Increase priority fees
2. Wait for off-peak hours
3. Reduce transaction complexity
4. Use confirmed commitment levelE001: Extension not installed properly
E002: Permissions denied
E003: Storage access failed
E004: Invalid configurationW001: File format not supported
W002: Private key validation failed
W003: Duplicate wallet detected
W004: Wallet limit exceededN001: RPC connection failed
N002: Network timeout
N003: Rate limit exceeded
N004: Invalid endpointT001: Insufficient fees
T002: Transaction failed
T003: Account not found
T004: Invalid signature// Enable console logging
localStorage.setItem('cland_debug', 'true');
// Set log level
localStorage.setItem('cland_log_level', 'verbose');// Available debug data
const debugInfo = {
version: "1.0.0",
browser: navigator.userAgent,
storage: await chrome.storage.local.get(),
walletCount: wallets.length,
lastOperation: operationLog,
networkStats: connectionStats
}class WalletManager {
// Load wallets from text content
static async loadWalletsFromContent(content: string): Promise<WalletInfo[]>
// Load wallets from file list
static async loadWalletsFromFiles(files: FileList): Promise<WalletInfo[]>
// Validate private key format
static validatePrivateKey(privateKey: string): boolean
// Create Keypair from private key
static createKeypairFromPrivateKey(privateKey: string): Keypair
// Get public key from private key
static getPublicKey(privateKey: string): PublicKey
// Read file content as text
private static readFileContent(file: File): Promise<string>
}class RentCollector {
private connection: Connection;
private wallets: WalletInfo[];
private stats: RentCollectionSummary;
constructor(rpcUrl: string)
// Load wallets for processing
setWallets(wallets: WalletInfo[]): void
// Scan wallets for rent
async scanWallets(
wallets: WalletInfo[],
onProgress?: (progress: ProcessingProgress) => void
): Promise<void>
// Collect rent from all eligible accounts
async collectRent(
feePayerPrivateKey: string,
onProgress?: (progress: ProcessingProgress) => void
): Promise<RentCollectionSummary>
// Get current statistics
getStats(): RentCollectionSummary
// Private helper methods
private async scanWallet(wallet: WalletInfo): Promise<void>
private async collectFromWallet(
wallet: WalletInfo,
feePayerKeypair: Keypair
): Promise<void>
private async getTokenAccounts(publicKey: PublicKey): Promise<any[]>
private isRentEligible(account: any): boolean
private async closeTokenAccount(
accountAddress: string,
owner: Keypair,
feePayer: Keypair
): Promise<string>
}class StorageService {
private static readonly CONFIG_KEY = 'solana_rent_collector_config';
// Save complete configuration
static async saveConfig(config: ExtensionConfig): Promise<void>
// Load complete configuration
static async loadConfig(): Promise<ExtensionConfig>
// Clear all stored data
static async clearConfig(): Promise<void>
// Save RPC URL
static async saveRpcUrl(rpcUrl: string): Promise<void>
// Save fee payer private key
static async saveFeePayerKey(feePayerKey: string): Promise<void>
// Get stored RPC URL
static async getRpcUrl(): Promise<string>
// Get stored fee payer key
static async getFeePayerKey(): Promise<string>
}// Wallet information structure
interface WalletInfo {
privateKey: string;
publicKey: string;
balance: number;
tokenAccounts: TokenAccountInfo[];
rentEligibleAccounts: TokenAccountInfo[];
totalRent: number;
status: 'pending' | 'scanning' | 'scanned' | 'collecting' | 'collected' | 'error';
}
// Token account details
interface TokenAccountInfo {
address: string;
mint: string;
balance: number;
decimals: number;
rentEpoch: number;
executable: boolean;
owner: string;
lamports: number;
data: TokenAccountData;
}
// Token account data structure
interface TokenAccountData {
parsed: {
info: {
isNative: boolean;
mint: string;
owner: string;
state: string;
tokenAmount: {
amount: string;
decimals: number;
uiAmount: number;
};
};
type: string;
};
program: string;
space: number;
}
// Collection operation summary
interface RentCollectionSummary {
totalWallets: number;
scannedWallets: number;
walletsWithRent: number;
totalRentAvailable: number;
totalRentCollected: number;
totalFeesPaid: number;
successfulCollections: number;
failedCollections: number;
netProfit: number;
}
// Progress tracking for operations
interface ProcessingProgress {
current: number;
total: number;
wallet: string;
status: string;
}
// Extension configuration
interface ExtensionConfig {
rpcUrl?: string;
feePayerKey?: string;
}// Solana token program IDs
export const TOKEN_PROGRAM_ID = new PublicKey(
'TokenkegQfeZyiNwAJbNbGKPFXCWuBvf9Ss623VQ5DA'
);
export const TOKEN_2022_PROGRAM_ID = new PublicKey(
'TokenzQdBNbLqP5VEhdkAS6EPFLC1PHnBqCXEpPxuEb'
);// Default configuration values
export const DEFAULT_RPC_URL = 'https://api.mainnet-beta.solana.com';
export const DEFAULT_COMMITMENT = 'confirmed';
export const RENT_EXEMPT_THRESHOLD = 0.00203928; // SOL
export const MAX_BATCH_SIZE = 20;
export const REQUEST_TIMEOUT = 30000; // milliseconds// Progress callback function type
type ProgressCallback = (progress: ProcessingProgress) => void;
// Usage example
const onProgress: ProgressCallback = (progress) => {
console.log(`Processing ${progress.current}/${progress.total}: ${progress.status}`);
};// Error handling
interface OperationError {
code: string;
message: string;
wallet?: string;
transaction?: string;
details?: any;
}// DO: Use secure key handling
const secureKeyHandling = {
storage: "Memory only during operation",
transmission: "Never over network",
logging: "Never log private keys",
cleanup: "Clear after each operation"
};
// DON'T: Store keys permanently
// localStorage.setItem('privateKey', key); // NEVER DO THIS# DO: Use reputable RPC providers
✅ Helius (https://helius.xyz)
✅ QuickNode (https://quicknode.com)
✅ Triton (https://triton.one)
✅ Solana Foundation (https://api.mainnet-beta.solana.com)
# DON'T: Use untrusted endpoints
❌ Random public RPCs
❌ HTTP (non-HTTPS) endpoints
❌ Unverified custom servers// DO: Validate before operations
const secureOperation = {
validateKeys: true,
checkBalances: true,
simulateFirst: true,
confirmTransactions: true
};
// DON'T: Skip validation
const unsafeOperation = {
blindlyTrust: false,
skipConfirmation: false,
ignoreErrors: false
};// Optimal batch sizes for different operations
const batchSizes = {
scanning: 10, // RPC calls per batch
collection: 20, // Transactions per batch
validation: 50 // Key validations per batch
};// Memory and CPU optimization
const resourceManagement = {
maxMemoryMB: 100,
maxConcurrentOps: 5,
progressUpdateMs: 100,
timeoutMs: 30000
};// Robust error handling strategy
const errorHandling = {
retryAttempts: 3,
retryDelayMs: 1000,
failFast: false,
continueOnError: true
};# Recommended file structure
crypto-operations/
├── wallets/
│ ├── mainnet/
│ │ ├── batch-001.txt (≤ 1000 wallets)
│ │ ├── batch-002.txt
│ │ └── batch-003.txt
│ └── testnet/
│ └── test-wallets.txt
├── results/
│ ├── 2024-01-15-operation.log
│ └── 2024-01-16-operation.log
└── backups/
├── original-wallets.zip
└── processed-wallets.zip// Testing progression
const testingSteps = {
1: "Test with 1-2 wallets on devnet",
2: "Test with 10 wallets on devnet",
3: "Test with 1-2 wallets on mainnet",
4: "Scale to full operation on mainnet"
};// Operation monitoring
const monitoring = {
preOperation: "Check all configurations",
duringOperation: "Monitor progress and errors",
postOperation: "Verify results and profitability"
};// Smart fee strategies
const feeStrategies = {
offPeakHours: "Lower network congestion = lower fees",
batchOptimization: "More operations per transaction",
priorityFeeControl: "Balance speed vs cost",
profitabilityCheck: "Ensure positive ROI before operation"
};# Best times for operations (UTC)
Low Traffic: 02:00 - 08:00 UTC (lowest fees)
Medium: 08:00 - 14:00 UTC
High Traffic: 14:00 - 02:00 UTC (highest fees)
# Days of week
Best: Sunday, Monday
Good: Tuesday, Wednesday
Busy: Thursday, Friday, Saturday// Pre-operation profitability check
const profitabilityCheck = {
minRentThreshold: 0.01, // SOL per account
maxFeeRatio: 0.05, // 5% of collected rent
minNetProfit: 0.001, // SOL minimum profit
breakEvenPoint: "Calculate before starting"
};# Required software
Node.js 18+
npm 8+
Git 2.30+
Chrome 88+# Clone repository
git clone https://github.com/Cland0x/Cland-collector.git
cd Cland-collector
# Install dependencies
npm install
# Start development server
npm run dev
# Build for production
npm run build
# Load in Chrome
# 1. Open chrome://extensions/
# 2. Enable Developer mode
# 3. Click "Load unpacked"
# 4. Select dist-extension folderCland-collector/
├── popup/ # UI components
│ ├── App.tsx # Main React component
│ ├── main.tsx # Entry point
│ └── styles.css # Styling
├── services/ # Core business logic
│ ├── rent-collector.ts
│ └── storage.ts
├── utils/ # Utility functions
│ └── wallet-manager.ts
├── types/ # TypeScript definitions
│ └── index.ts
├── public/ # Static assets
├── manifest.json # Extension manifest
└── package.json # Dependencies// Use explicit types
interface WalletInfo {
privateKey: string;
publicKey: string;
balance: number;
}
// Prefer async/await over promises
async function loadWallets(): Promise<WalletInfo[]> {
try {
const result = await walletManager.load();
return result;
} catch (error) {
console.error('Failed to load wallets:', error);
throw error;
}
}
// Use proper error handling
class WalletError extends Error {
constructor(message: string, public code: string) {
super(message);
this.name = 'WalletError';
}
}// Use functional components with hooks
const WalletManager: React.FC = () => {
const [wallets, setWallets] = useState<WalletInfo[]>([]);
const [loading, setLoading] = useState(false);
useEffect(() => {
loadWallets();
}, []);
return (
<div>
{/* Component JSX */}
</div>
);
};
// Custom hooks for shared logic
const useWalletState = () => {
const [wallets, setWallets] = useState<WalletInfo[]>([]);
const loadWallets = useCallback(async () => {
// Implementation
}, []);
return { wallets, loadWallets };
};/* Use CSS custom properties */
:root {
--primary-color: #4299e1;
--spacing-md: 1rem;
}
/* Component-specific styles */
.wallet-card {
background: var(--surface-color);
padding: var(--spacing-md);
border-radius: 8px;
}
/* Responsive design */
@media (max-width: 768px) {
.wallet-card {
padding: var(--spacing-sm);
}
}// Test wallet manager functionality
describe('WalletManager', () => {
test('validates private keys correctly', () => {
const validKey = '5KJvsngHeMpm884wtkJNzQGaCErckhHJBGFsvd3VyK5qMZpJ85n';
const invalidKey = 'invalid-key';
expect(WalletManager.validatePrivateKey(validKey)).toBe(true);
expect(WalletManager.validatePrivateKey(invalidKey)).toBe(false);
});
test('loads wallets from content', async () => {
const content = 'key1\nkey2\nkey3';
const wallets = await WalletManager.loadWalletsFromContent(content);
expect(wallets).toHaveLength(3);
expect(wallets[0].privateKey).toBe('key1');
});
});// Test complete workflow
describe('Rent Collection Workflow', () => {
test('completes full scan and collect cycle', async () => {
const wallets = await loadTestWallets();
const collector = new RentCollector(TEST_RPC_URL);
collector.setWallets(wallets);
await collector.scanWallets(wallets);
const stats = collector.getStats();
expect(stats.scannedWallets).toBe(wallets.length);
});
});## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Testing
- [ ] Unit tests pass
- [ ] Integration tests pass
- [ ] Manual testing completed
- [ ] Security review done
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Documentation updated
- [ ] No security vulnerabilities introduced# Semantic versioning
Major: Breaking changes (2.0.0)
Minor: New features (1.1.0)
Patch: Bug fixes (1.0.1)5KJvsngHeMpm884wtkJNzQGaCErckhHJBGFsvd3VyK5qMZpJ85n
3WUX7GvHfnujuKvzdPHjHLpNnguGgdGKRiLHodk17VoS
2B5VsY98Rlann35t19J2AB1yms5MiH8PxMV6Qpn3GpkK