A modern, high-performance .NET library for building applications on the Solana blockchain with enterprise-grade wallet security.
SolanaSDK is a comprehensive .NET library designed to simplify interaction with the Solana blockchain. Built with performance, security, and developer experience in mind, it provides intuitive abstractions for wallet management, account derivation, and cryptographic operations using industry-standard protocols like BIP32, BIP44, and SLIP-39.
Key Innovation: Advanced SLIP-39 support enabling Shamir's Secret Sharing for enhanced wallet security and recovery flexibility.
β¨ Next-Generation Wallet Support
- SLIP-39 Hierarchical Deterministic (HD) Wallets - Enterprise-grade secret sharing with Shamir's Secret Sharing
- Multi-Account Management - Derive unlimited accounts with Solana-compatible BIP32 paths (m/44'/501'/x'/0')
- Flexible Recovery - Recover wallets from shares or raw seed bytes
- Secure Key Derivation - Industry-standard Ed25519 cryptography
π Advanced Cryptography
- Ed25519 digital signatures with Solana compatibility
- BIP32 hierarchical key derivation
- Shamir's Secret Sharing (SLIP-39) for distributed key storage
- Hardware wallet integration ready
πΌ Transaction Management
- Fluent transaction builder API
- Instruction composition and validation
- Support for complex transaction types
- Message signing and verification
π‘ RPC Integration (Foundation ready)
- Full Solana RPC API support architecture
- Connection pooling and retry logic
- WebSocket support for real-time updates
π Developer Experience
- Strongly-typed API design
- Comprehensive error handling
- Clear, chainable API patterns
- Full inline documentation
Install via NuGet Package Manager:
dotnet add package SolanaSDKOr via NuGet CLI:
Install-Package SolanaSDKManages wallets backed by SLIP-39 (Shamir's Secret Sharing) recovered secrets for enterprise-grade wallet security.
Standard wallet for mnemonic-based (BIP39) or seed-based wallet management.
Represents a derived Solana keypair with signing and verification capabilities.
Type-safe wrappers for Ed25519 cryptographic keys.
using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Bip39;
using System;
// Create a new wallet with 12-word mnemonic
var wallet = new SWallet(
wordCount: WordCount.Twelve,
wordList: WordList.English
);
// Access the primary account (m/44'/501'/0'/0')
var primaryAccount = wallet.Account;
Console.WriteLine($"Public Key: {primaryAccount.PublicKey}");
Console.WriteLine($"Mnemonic: {wallet.Mnemonic.ToString()}");
// Derive additional accounts
var account1 = wallet.GetAccount(0);
var account2 = wallet.GetAccount(1);using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Bip39;
// Use existing mnemonic words
string mnemonicPhrase = "abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon abandon about";
var wallet = new SWallet(
mnemonicPhrase,
wordList: WordList.English,
passphrase: "" // Optional additional security
);
var account = wallet.Account;
Console.WriteLine($"Restored Account: {account.PublicKey}");SLIP-39 enables Shamir's Secret Sharing, allowing you to split wallet secrets across multiple shares for enhanced security and recovery flexibility.
using Bifrost.Security;
using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Slip39;
using System;
// Setup Shamir's Secret Sharing implementation
IShamirsSecretSharing sss = new ShamirsSecretSharing();
// Your SLIP-39 shares (recovered from secure storage)
// In production, these would be stored securely across multiple locations
Share[] shares = new[]
{
new Share(/* share 1 bytes */),
new Share(/* share 2 bytes */),
new Share(/* share 3 bytes */)
};
// Create wallet from shares with optional passphrase
var wallet = new SolanaSDK.Wallet.Slip39.Slip39SWallet(
sss,
shares,
passphrase: "your-optional-passphrase"
);
// Access the primary account
var primaryAccount = wallet.Account;
Console.WriteLine($"Wallet Public Key: {primaryAccount.PublicKey}");using SolanaSDK.Wallet;
using System;
// For advanced use: create wallet from recovered raw seed bytes
// Minimum 32 bytes, typically 32+ for enhanced security
byte[] recoveredSeed = new byte[32]; // Your 32-byte seed
// ... populate with actual seed data
var wallet = new Slip39SWallet(
recoveredSeed,
passphrase: ""
);
// Proceed with account operations
var account = wallet.GetAccount(0);
Console.WriteLine($"Account Address: {account.PublicKey}");using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Bip39;
// Generate new wallet with passphrase protection
var wallet = new SWallet(
wordCount: WordCount.Twelve,
wordList: WordList.English,
passphrase: "my-secret-passphrase",
seedMode: SeedMode.Ed25519Bip32
);
var account = wallet.Account;
Console.WriteLine($"Account: {account.PublicKey}");
// Same mnemonic + different passphrase = different account!
var wallet2 = new SWallet(
wallet.Mnemonic,
passphrase: "different-passphrase"
);
Console.WriteLine($"Account 1: {wallet.Account.PublicKey}");
Console.WriteLine($"Account 2: {wallet2.Account.PublicKey}");
// These will be DIFFERENT addresses!using SolanaSDK.Wallet;
using System;
// Create wallet from a 32-byte seed
byte[] seed = new byte[32]; // Your Ed25519 seed
// ... populate seed bytes
var wallet = new SWallet(
seed: seed,
passphrase: "",
seedMode: SeedMode.Ed25519Bip32
);
var account = wallet.Account;using SolanaSDK.Wallet;
// Base58-encoded 64-byte secret key
string secretKey = "3z5w6h7j8k9l0m1n2o3p4q5r6s7t8u9v0w1x2y3z4a5b6c7d8e9f0g1h2i3j4";
var account = SAccount.FromSecretKey(secretKey);
Console.WriteLine($"Account: {account.PublicKey}");All accounts use the Solana standard BIP32 derivation path: m/44'/501'/x'/0'
using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Bip39;
using System;
using System.Collections.Generic;
var wallet = new SWallet(
wordCount: WordCount.Twelve,
wordList: WordList.English
);
// Derive multiple accounts for different purposes
var accounts = new List<SAccount>();
for (int i = 0; i < 5; i++)
{
var account = wallet.GetAccount(i);
accounts.Add(account);
Console.WriteLine($"Account {i}: {account.PublicKey}");
}
// Use different accounts for different operations
var userAccount = accounts[0]; // User transactions
var stakingAccount = accounts[1]; // Staking operations
var treasuryAccount = accounts[2]; // Treasury managementusing SolanaSDK.Wallet;
using System.Collections.Generic;
// Import from Base58 secret keys
var secretKeys = new List<string>
{
"3z5w6h7j8k9l0m1n2o3p4q5r6s7t8u9v0w1x2y3z4a5b6c7d8e9f0g1h2i3j4",
"4a6x7i8j9k0l1m2n3o4p5q6r7s8t9u0v1w2x3y4z5a6b7c8d9e0f1g2h3i4j5",
};
var accounts = SAccount.ImportMany(secretKeys);
foreach (var account in accounts)
{
Console.WriteLine($"Imported: {account.PublicKey}");
}using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Bip39;
using System;
using System.Text;
var wallet = new SWallet(
wordCount: WordCount.Twelve,
wordList: WordList.English
);
// Message to sign
byte[] message = Encoding.UTF8.GetBytes("Hello Solana!");
// Sign with primary account
byte[] signature = wallet.Sign(message);
Console.WriteLine($"Signature: {Convert.ToBase64String(signature)}");
// Verify signature with same account
bool isValid = wallet.Verify(message, signature);
Console.WriteLine($"Signature Valid: {isValid}");using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Bip39;
using System;
using System.Text;
var wallet = new SWallet(
wordCount: WordCount.Twelve,
wordList: WordList.English
);
byte[] message = Encoding.UTF8.GetBytes("Transaction Data");
// Sign with account at index 2
byte[] signature = wallet.Sign(message, accountIndex: 2);
// Verify with account at index 2
bool isValid = wallet.Verify(message, signature, accountIndex: 2);
Console.WriteLine($"Valid: {isValid}");using Bifrost.Security;
using SolanaSDK.Wallet;
using SolanaSDK.Wallet.Slip39;
using System;
using System.Text;
IShamirsSecretSharing sss = new ShamirsSecretSharing();
Share[] shares = new[] { /* your shares */ };
var wallet = new Slip39SWallet(sss, shares);
byte[] message = Encoding.UTF8.GetBytes("Important message");
// Sign with primary account
byte[] sig0 = wallet.Sign(message);
// Sign with account 1
byte[] sig1 = wallet.Sign(message, accountIndex: 1);
// Verify
bool valid0 = wallet.Verify(message, sig0, accountIndex: 0);
bool valid1 = wallet.Verify(message, sig1, accountIndex: 1);
Console.WriteLine($"Account 0 Valid: {valid0}");
Console.WriteLine($"Account 1 Valid: {valid1}");using SolanaSDK.Wallet;
// Validate a base58-encoded public key
string publicKeyString = "11111111111111111111111111111111";
bool isValid = PublicKey.IsValid(publicKeyString);
Console.WriteLine($"Valid: {isValid}");
// Validate with curve point check
bool isValidCurve = PublicKey.IsValid(publicKeyString, validateCurve: true);
Console.WriteLine($"Valid Curve: {isValidCurve}");
// Validate byte array
byte[] keyBytes = new byte[32]; // 32-byte public key
bool isBytesValid = PublicKey.IsValid(keyBytes);using SolanaSDK.Wallet;
using System;
using System.Collections.Generic;
using System.Text;
var publicKey = new PublicKey("11111111111111111111111111111111");
var programId = new PublicKey("TokenkegQfeZyiNwAJsyFbPVwwQQfaps9McVLcjZmE");
// Try to create a program address from seeds
var seeds = new List<byte[]>
{
Encoding.UTF8.GetBytes("my_seed"),
publicKey.KeyBytes
};
if (PublicKey.TryCreateProgramAddress(seeds, programId, out var derivedAddress))
{
Console.WriteLine($"Derived Address: {derivedAddress}");
}
else
{
Console.WriteLine("Failed to create program address");
}using SolanaSDK.Wallet;
using System;
using System.Collections.Generic;
using System.Text;
var programId = new PublicKey("TokenkegQfeZyiNwAJsyFbPVwwQQfaps9McVLcjZmE");
var seeds = new List<byte[]>
{
Encoding.UTF8.GetBytes("my_seed")
};
if (PublicKey.TryFindProgramAddress(seeds, programId, out var address, out byte bump))
{
Console.WriteLine($"Program Address: {address}");
Console.WriteLine($"Bump: {bump}");
}using SolanaSDK.Wallet;
var fromPublicKey = new PublicKey("11111111111111111111111111111111");
var programId = new PublicKey("TokenkegQfeZyiNwAJsyFbPVwwQQfaps9McVLcjZmE");
if (PublicKey.TryCreateWithSeed(fromPublicKey, "my_seed", programId, out var newAddress))
{
Console.WriteLine($"New Address: {newAddress}");
}π Production Best Practices:
- Private keys are never logged or exposed - By design
- SLIP-39 Shamir's Secret Sharing - Distribute trust across multiple shares
- Passphrase Protection - Add an additional security layer during recovery
- Use dedicated key storage - Consider HSM or secure enclave integration for production
- Hardware wallet ready - Designed to integrate with hardware security modules
- Audit your implementation - Security audits recommended for production use
-
Never Log Keys
// β DON'T DO THIS Console.WriteLine($"Secret Key: {account.PrivateKey}"); // β DO THIS // Only log the public key Console.WriteLine($"Public Key: {account.PublicKey}");
-
Store Seeds and Shares Securely
- β DON'T store in plain text
- β
DO store in:
- Hardware Security Modules (HSM)
- Encrypted vaults
- Secure key management systems
- Azure Key Vault / AWS Secrets Manager
-
Use SLIP-39 for High-Value Operations
- SLIP-39 provides Shamir's Secret Sharing
- Distribute trust across multiple shares
- No single point of failure
-
Production Checklist:
- β Never commit mnemonics, seeds, or passphrases to version control
- β Use environment variables or secure vaults for sensitive data
- β Implement proper key rotation strategies
- β Audit your implementation before production deployment
- β Use hardware wallets for high-value operations
- β Enable passphrase protection for SLIP-39 wallets
- β Validate all public keys before use
- β Implement proper error handling
- β Use HTTPS/TLS for all network communication
Follows Solana conventions:
m/44'/501'/x'/0'
βββ Purpose: 44 (BIP44)
βββ Coin Type: 501 (Solana)
βββ Account: x (0, 1, 2, ...)
βββ Change: 0 (External account)
SLIP-39 supports optional passphrases that affect key derivation:
// Same shares with different passphrases = different seeds
var wallet1 = new Slip39SWallet(sss, shares, "passphrase1");
var wallet2 = new Slip39SWallet(sss, shares, "passphrase2");
// wallet1.Account.PublicKey != wallet2.Account.PublicKey- Bifrost.Security - Ed25519 cryptography support
- .NET 6.0 or higher
- C# 10.0 or higher
SolanaSDK is optimized for production use:
- Minimal allocations in hot paths
- Efficient cryptographic operations
- Lazy initialization of derivation engine
- Zero-copy designs where applicable
We welcome contributions! Please feel free to submit pull requests or open issues for:
- Bug reports
- Feature requests
- Documentation improvements
- Performance enhancements
This project is licensed under the MIT License - see the LICENSE file for details.
For issues, questions, or suggestions, please open an issue on GitHub.
Built with β€οΈ for the Solana ecosystem
Combining modern .NET practices with enterprise-grade cryptographic standards for secure blockchain development.