|
| 1 | +# Sentinel dVPN SDK for C# / .NET |
| 2 | + |
| 3 | +Native C# SDK for building Windows desktop VPN applications on the Sentinel dVPN network. Enables NordVPN-grade native apps using WPF, WinUI, MAUI, or any .NET framework. |
| 4 | + |
| 5 | +## Architecture |
| 6 | + |
| 7 | +``` |
| 8 | +Sentinel.SDK.Core -- Wallet, chain client, TX building, 17 message types, error handling, helpers |
| 9 | +Sentinel.SDK.Node -- V3 handshake, node status, session management, SentinelVpnClient |
| 10 | +Sentinel.SDK.Tunnel -- WireGuard tunnel service + V2Ray process management (Windows) |
| 11 | +``` |
| 12 | + |
| 13 | +## Quick Start |
| 14 | + |
| 15 | +The simplest path: `SentinelVpnClient` orchestrates everything -- balance check, node selection, session creation, handshake, and tunnel installation. |
| 16 | + |
| 17 | +```csharp |
| 18 | +using Sentinel.SDK.Core; |
| 19 | +using Sentinel.SDK.Node; |
| 20 | + |
| 21 | +// 1. Create or restore wallet |
| 22 | +using var wallet = SentinelWallet.FromMnemonic("your twelve word mnemonic phrase goes here ..."); |
| 23 | + |
| 24 | +// 2. Create VPN client |
| 25 | +using var vpn = new SentinelVpnClient(wallet, new SentinelVpnOptions |
| 26 | +{ |
| 27 | + Gigabytes = 1, |
| 28 | + FullTunnel = true, |
| 29 | +}); |
| 30 | + |
| 31 | +// 3. Subscribe to progress events |
| 32 | +vpn.Progress += (_, e) => Console.WriteLine($"[{e.Step}] {e.Detail}"); |
| 33 | +vpn.Error += (_, e) => Console.WriteLine($"Error: {e.Exception.Message}"); |
| 34 | + |
| 35 | +// 4. Auto-pick best node and connect |
| 36 | +var result = await vpn.ConnectAutoAsync(new ConnectAutoOptions |
| 37 | +{ |
| 38 | + Countries = new[] { "DE", "US" }, |
| 39 | + ServiceType = "wireguard", |
| 40 | + MaxAttempts = 3, |
| 41 | +}); |
| 42 | + |
| 43 | +Console.WriteLine($"VPN connected! Node: {result.NodeAddress}, Session: {result.SessionId}"); |
| 44 | +Console.ReadKey(); |
| 45 | + |
| 46 | +// 5. Disconnect (or let Dispose handle it) |
| 47 | +await vpn.DisconnectAsync(); |
| 48 | +``` |
| 49 | + |
| 50 | +## Features |
| 51 | + |
| 52 | +### SentinelVpnClient (High-Level Orchestrator) |
| 53 | + |
| 54 | +- **ConnectAsync** -- Direct connection to a specific node (pay-per-GB) |
| 55 | +- **ConnectAutoAsync** -- Auto-select best node with country/type filters and retry |
| 56 | +- **ConnectViaSubscriptionAsync** -- Connect using an existing plan subscription |
| 57 | +- **DisconnectAsync** -- Clean tunnel teardown |
| 58 | +- **Events** -- `Progress`, `Connected`, `Disconnected`, `Error` for UI binding |
| 59 | +- **Session reuse** -- Detects existing active sessions to avoid double-paying |
| 60 | +- **409 recovery** -- Automatically creates new session on handshake conflict |
| 61 | +- **Connection mutex** -- Prevents concurrent connect races |
| 62 | +- **Clock drift detection** -- Skips V2Ray nodes with >120s drift (VMess AEAD failure) |
| 63 | + |
| 64 | +### Wallet (SentinelWallet) |
| 65 | + |
| 66 | +- BIP39 mnemonic generation (12/15/18/21/24 words) |
| 67 | +- BIP44 key derivation (`m/44'/118'/0'/0/0`) |
| 68 | +- secp256k1 signing (compact 64-byte signatures) |
| 69 | +- Bech32 address encoding (sent1, sentnode1, sentprov1) |
| 70 | +- Address comparison across prefixes (`IsSameKey`) |
| 71 | +- `IDisposable` for key material lifecycle |
| 72 | + |
| 73 | +### Chain Client (ChainClient) |
| 74 | + |
| 75 | +- LCD REST API queries with endpoint failover (4 LCD endpoints) |
| 76 | +- Automatic retry on network errors |
| 77 | +- Broken pagination handling (fallback to `limit=5000`) |
| 78 | +- Node, subscription, session, plan, and fee grant queries |
| 79 | +- Plan discovery by probing individual IDs |
| 80 | +- Available nodes through subscription lookup |
| 81 | + |
| 82 | +### Transaction Builder |
| 83 | + |
| 84 | +- SIGN_MODE_DIRECT protobuf wire-format encoding |
| 85 | +- Automatic gas estimation per message type (1.4x safety multiplier) |
| 86 | +- Sequence mismatch recovery (up to 3 retries) |
| 87 | +- Double-spend detection before retry |
| 88 | +- Batch message support (multiple messages per TX) |
| 89 | + |
| 90 | +### Message Builder (17 Message Types) |
| 91 | + |
| 92 | +| Category | Messages | |
| 93 | +|----------|----------| |
| 94 | +| Session | `StartSession`, `EndSession` | |
| 95 | +| Subscription | `StartSubscription`, `SubStartSession`, `PlanStartSession` | |
| 96 | +| Plan | `CreatePlan`, `UpdatePlanStatus`, `LinkNode`, `UnlinkNode` | |
| 97 | +| Provider | `RegisterProvider`, `UpdateProviderDetails`, `UpdateProviderStatus` | |
| 98 | +| Lease | `StartLease`, `EndLease` | |
| 99 | +| Bank | `Send` | |
| 100 | +| Fee Grant | `GrantFeeAllowance`, `RevokeFeeAllowance` | |
| 101 | + |
| 102 | +### Error Handling |
| 103 | + |
| 104 | +- **Typed exceptions** -- `SentinelException` base with `Code`, `Details`, `Message` |
| 105 | +- **Hierarchy** -- `WalletException`, `ChainException`, `NodeException`, `TunnelException`, `HandshakeException` |
| 106 | +- **Error codes** -- Machine-readable constants (`ErrorCodes.NodeOffline`, etc.) |
| 107 | +- **Severity mapping** -- `ErrorSeverity.Get()` returns `"fatal"`, `"retryable"`, `"recoverable"` |
| 108 | +- **User messages** -- `ErrorSeverity.UserMessage()` returns UI-ready strings |
| 109 | + |
| 110 | +### Session Manager |
| 111 | + |
| 112 | +- Find existing active sessions (avoid double-paying) |
| 113 | +- Query bandwidth allocation (used/max/remaining bytes) |
| 114 | + |
| 115 | +### Display Helpers |
| 116 | + |
| 117 | +- `FormatP2P()` -- `40152030` to `"40.15 P2P"` |
| 118 | +- `ShortAddress()` -- Truncate bech32 addresses for display |
| 119 | +- `FormatBytes()` -- `1500000000` to `"1.4 GB"` |
| 120 | +- `FormatExpiry()` -- ISO timestamp to `"23d left"` |
| 121 | +- `FormatUptime()` -- TimeSpan to `"2h 15m"` |
| 122 | +- `ParseChainDuration()` -- `"557817.72s"` to structured data |
| 123 | + |
| 124 | +### Tunnel Management |
| 125 | + |
| 126 | +- **WireGuard** -- Windows service installation, MTU 1280, keepalive 15s, admin check |
| 127 | +- **V2Ray** -- Process lifecycle, JSON config generation, SOCKS5 with password auth |
| 128 | +- **V2Ray config** -- Matches sentinel-go-sdk format exactly (non-negotiable rules) |
| 129 | +- **Cleanup** -- Automatic on disconnect and dispose |
| 130 | + |
| 131 | +## Requirements |
| 132 | + |
| 133 | +- .NET 8.0+ |
| 134 | +- Windows 10/11 (for WireGuard tunnel management) |
| 135 | +- Admin privileges (for WireGuard service installation) |
| 136 | +- V2Ray 5.2.1 binary (for V2Ray nodes -- do NOT use 5.44.1+) |
| 137 | + |
| 138 | +## Dependencies |
| 139 | + |
| 140 | +| Package | Purpose | |
| 141 | +|---------|---------| |
| 142 | +| NBitcoin | BIP39, BIP44, secp256k1, Bech32 | |
| 143 | +| Google.Protobuf | Protobuf message encoding (for BroadcastProtobufAsync) | |
| 144 | +| NSec.Cryptography | X25519 (Curve25519) for WireGuard key generation | |
| 145 | + |
| 146 | +## NuGet Packages (Planned) |
| 147 | + |
| 148 | +```bash |
| 149 | +dotnet add package Sentinel.SDK # Meta-package (all three) |
| 150 | +dotnet add package Sentinel.SDK.Core # Wallet + chain only |
| 151 | +dotnet add package Sentinel.SDK.Node # + handshake + VPN client |
| 152 | +dotnet add package Sentinel.SDK.Tunnel # + WireGuard/V2Ray |
| 153 | +``` |
| 154 | + |
| 155 | +## Building |
| 156 | + |
| 157 | +```bash |
| 158 | +dotnet build |
| 159 | +dotnet test |
| 160 | +``` |
| 161 | + |
| 162 | +## Chain Info |
| 163 | + |
| 164 | +| Property | Value | |
| 165 | +|----------|-------| |
| 166 | +| Chain ID | `sentinelhub-2` | |
| 167 | +| Cosmos SDK | `0.47.17` | |
| 168 | +| Denom | `udvpn` (1 P2P = 1,000,000 udvpn) | |
| 169 | +| HD Path | `m/44'/118'/0'/0/0` | |
| 170 | +| Bech32 | `sent1` (account), `sentnode1` (node), `sentprov1` (provider) | |
| 171 | +| Gas Price | `0.2 udvpn` per gas unit | |
| 172 | + |
| 173 | +## Documentation |
| 174 | + |
| 175 | +- [Quick Start](docs/QUICK-START.md) -- Get running in under 50 lines |
| 176 | +- [API Reference](docs/API-REFERENCE.md) -- Complete public API catalog |
| 177 | +- [Edge Cases](docs/EDGE-CASES.md) -- Gotchas and production lessons learned |
| 178 | + |
| 179 | +## Protocol Specs |
| 180 | + |
| 181 | +See `sentinel-proto/` for protobuf definitions and `Sentinel SDK/docs/` for: |
| 182 | +- V3-HANDSHAKE-SPEC.md -- Handshake protocol |
| 183 | +- V2RAY-CONFIG-SPEC.md -- V2Ray transport mapping |
| 184 | +- WIREGUARD-CONFIG-SPEC.md -- WireGuard config mapping |
| 185 | +- LCD-API-REFERENCE.md -- Chain REST API reference |
0 commit comments