This is an example application for builders, not a production release. Use it as a starting point and reference for building your own Windows dVPN client with the Sentinel C# SDK.
A working example of a decentralized VPN desktop client built with C# / WPF / .NET 8.0 on the Sentinel Network. Demonstrates how to integrate the Sentinel C# SDK into a real desktop application with a complete UI.
A Windows-focused example application that shows builders how to build a dVPN desktop app using:
- WPF (Windows Presentation Foundation) for the UI layer
- Sentinel C# SDK for blockchain interaction, node discovery, session management, and tunnel creation
- WireGuard + V2Ray tunnel protocols
- Handshake DNS (103.196.38.38) for decentralized name resolution through the tunnel
This is not a production release or a library — it's a complete, runnable example that demonstrates every pattern you need to build your own client. Fork it, rip it apart, use whatever you need.
| Feature | Implementation |
|---|---|
| Wallet management | Create, import (mnemonic), persist encrypted |
| Node discovery | Query all active Sentinel nodes from chain |
| Node browser | Sidebar with search, country filter, protocol filter (WG/V2Ray) |
| Connection orb | Animated state indicator (off/connecting/connected) |
| WireGuard tunnels | Native WireGuard tunnel via SDK |
| V2Ray tunnels | VLess/VMess with multiple transports |
| Per-GB pricing | Pay per gigabyte of data used |
| Per-hour pricing | Pay per hour of connection time |
| Session management | View active sessions, data allocation, remaining bytes |
| Speed display | Real-time upload/download speed in status bar |
| IP display | Shows exit IP when connected |
| Node testing | Built-in test dashboard — test any node's speed and connectivity |
| Disk caching | Cache nodes, sessions, test results to local disk |
| Balance display | Live P2P token balance in topbar |
| Handshake DNS | All tunnel traffic resolves through HNS nameservers |
HandshakeDVPN/
App.xaml # Theme definition — colors, fonts, button styles
App.xaml.cs # Startup, backend initialization
MainWindow.xaml # Full UI layout (583 lines of XAML)
MainWindow.xaml.cs # All UI logic, event handlers, state management (3,669 lines)
Services/
IHnsVpnBackend.cs # Interface + all data models (403 lines)
NativeVpnClient.cs # SDK wrapper — wallet, nodes, connect, disconnect (1,076 lines)
DiskCache.cs # Local persistence for nodes, sessions, test results (62 lines)
Fonts/ # Inter font family (Regular, Medium, SemiBold, Bold)
HandshakeDVPN.csproj # Project file — references Sentinel C# SDK
app.manifest # Admin elevation manifest (required for WireGuard)
Total: ~5,980 lines of code across 7 source files.
The UI is built entirely in XAML with code-behind — no MVVM framework, no third-party UI libraries. This makes it easy to read and learn from.
Window (1360x920)
TopBar (56px)
Brand (Handshake logo + name)
Wallet address + P2P balance
Settings / Wallet / Logout buttons
Body
Sidebar (360px)
Tab bar: Nodes | Sessions | Plans | Test
Search box
Filter buttons: All | WG | V2
Scrollable node list
Footer: node count + refresh
Main Area
Node info card (selected node details + pricing)
Connection orb (animated circle — off/connecting/connected)
Status text + sub-status
Speed + IP bar (bottom)
Test Dashboard (toggled via Test tab)
Progress bar + stats
Scrollable results with FAST/SLOW/FAIL badges
Export (JSON/CSV) + Filter + Sort
All colors are defined as SolidColorBrush resources in App.xaml:
| Key | Color | Usage |
|---|---|---|
Bg0 |
#FFFFFF |
Primary background |
Bg1 |
#FAFAFA |
Sidebar background |
Bg2 |
#F2F2F2 |
Card backgrounds |
Bg3 |
#E8E8E8 |
Hover states |
Bdr |
#E0E0E0 |
Borders |
T1 |
#000000 |
Primary text |
T2 |
#555555 |
Secondary text |
T3 |
#999999 |
Muted text |
Green |
#22C55E |
Connected / pass states |
Red |
#DC2626 |
Disconnected / fail states |
Amber |
#D97706 |
Warning states |
Blue |
#4F8FFF |
Info accents |
Three reusable button styles defined in App.xaml:
BtnAcc— Primary action button (black background, white text, 8px corner radius)BtnGhost— Secondary button (transparent background, border, hover highlight)FilterBtn— Tab/filter button (no border, text-only, underline on active)
- Sans: Inter (bundled as resource — Regular, Medium, SemiBold, Bold)
- Mono: Cascadia Code / Consolas (system)
- Emoji: Segoe UI Emoji (system — used for country flags)
The app manages state through private fields — no viewmodels, no binding framework:
private string _connState = "off"; // "off" | "ing" | "on"
private string _activeFilter = ""; // "" | "wireguard" | "v2ray"
private string _payMode = "gb"; // "gb" | "hr"
private List<HnsNodeInfo> _allNodes = new();
private string? _selectedNode;UI updates happen on the dispatcher:
Dispatcher.Invoke(() => {
StatusText.Text = "Connected";
OrbBorderBrush.Color = Color.FromRgb(0x22, 0xC5, 0x5E);
});- User selects node from sidebar
- Node info card appears with pricing (per-GB / per-hour)
- User clicks the connection orb
ConnectAsync()→ SDK handles session creation, payment, handshake, tunnel setup- Orb animates to green, IP updates, speed polling starts
- Disconnect: orb click again →
DisconnectAsync()→ tunnel teardown
Three DispatcherTimer instances run while connected:
_statusPoll // 3s — check tunnel status, update speed display
_ipPoll // 60s — refresh exit IP
_balPoll // 5m — refresh P2P token balanceNodes are rendered as programmatic XAML Border elements in a StackPanel:
var card = new Border {
Background = isSelected ? AccLight : Transparent,
CornerRadius = new CornerRadius(8),
Padding = new Thickness(12, 10, 12, 10),
Cursor = Cursors.Hand,
};
// Flag image + moniker + country/city + protocol badge + peers + priceEach card is interactive — click to select, updates the main area node info card.
Defines the contract that NativeVpnClient implements:
interface IHnsVpnBackend {
Task<List<HnsNodeInfo>> GetNodesAsync();
Task<string> ConnectAsync(string nodeAddress, int gigabytes, string denom);
Task DisconnectAsync();
Task<HnsStatus> GetStatusAsync();
Task<string> GetBalanceAsync();
// ... more
}Key data models:
HnsNodeInfo— node address, moniker, country, city, protocol type, peers, pricingHnsStatus— connection state, speed up/down, bytes transferredActiveSession— session ID, node, allocation, bytes used/remaining
Direct integration with the Sentinel C# SDK:
// Query all active nodes from the blockchain
var nodes = await _chainClient.GetActiveNodesAsync();
// Connect to a node (handles payment + handshake + tunnel)
await _vpnClient.ConnectAsync(nodeAddress, new ConnectOptions {
Gigabytes = gigabytes,
Denom = "udvpn",
Dns = new[] { "103.196.38.38", "103.196.38.39" }, // Handshake DNS
});
// Disconnect and tear down tunnel
await _vpnClient.DisconnectAsync();Simple JSON file cache in %LocalAppData%\HandshakeDVPN\:
public static void Save<T>(string key, T data) {
var path = Path.Combine(CacheDir, $"{key}.json");
File.WriteAllText(path, JsonSerializer.Serialize(data));
}
public static T? Load<T>(string key) {
var path = Path.Combine(CacheDir, $"{key}.json");
if (!File.Exists(path)) return default;
return JsonSerializer.Deserialize<T>(File.ReadAllText(path));
}Used for: node list (avoid re-querying chain on every launch), test results (persist across sessions), user preferences.
The orb is a layered set of Ellipse elements with animated color transitions:
- Off: Gray rings, "Tap to connect" text
- Connecting: Pulsing amber animation
- Connected: Green rings, connected duration timer
Each node shows both per-GB and per-hour pricing. User toggles between them:
[Per GB 4.2 P2P] [Per Hour 0.8 P2P]
GB: [1] = 4.2 P2P
Bottom bar shows live speeds while connected:
Download: 12.4 Mbps | Upload: 3.2 Mbps | IP: 185.x.x.x (DE)
Built-in node testing with results table:
| Node | Protocol | Speed | Result |
|---|---|---|---|
| SuchNode (DE) | WireGuard | 18.3 Mbps | FAST |
| NodeRunner (US) | V2Ray | 6.1 Mbps | SLOW |
Export to JSON or CSV via SaveFileDialog.
- Windows 10/11
- .NET 8.0 SDK — download
- Administrator privileges — required for WireGuard tunnel creation
- Sentinel C# SDK — referenced as project dependency
- P2P tokens — needed to pay for node sessions (get from Osmosis DEX)
dotnet build HandshakeDVPN.csproj# Must run as administrator for WireGuard
dotnet run --project HandshakeDVPN.csprojThis app uses the Sentinel C# SDK:
Sentinel.SDK.Core— blockchain client, wallet, queriesSentinel.SDK.Node— node discovery, session managementSentinel.SDK.Tunnel— WireGuard and V2Ray tunnel creation
| File | Lines | What to Learn |
|---|---|---|
App.xaml |
125 | Complete WPF theme system — resource dictionaries, color tokens, reusable button styles with hover/disabled states, font loading |
App.xaml.cs |
62 | App startup, backend service initialization, unhandled exception setup |
MainWindow.xaml |
583 | Full WPF layout — Grid/StackPanel/Border composition, sidebar + main area split, node list template, connection orb, status bar, test dashboard |
MainWindow.xaml.cs |
3,669 | Event-driven UI logic — connection state machine, node rendering, search/filter, polling timers, test execution, export, animations |
IHnsVpnBackend.cs |
403 | Service interface pattern — all data models, enums, method contracts for a VPN backend |
NativeVpnClient.cs |
1,076 | SDK integration — wallet creation/import, chain queries, connect/disconnect flow, session management, Handshake DNS configuration |
DiskCache.cs |
62 | Simple JSON file persistence — generic save/load with LocalAppData storage |
This is currently an example for builders. If there's community interest, a production release could include:
| Feature | Description | Complexity |
|---|---|---|
| Windows installer | Inno Setup .exe — bundles app, WireGuard driver, V2Ray, .NET runtime. Start menu + auto-start. | Medium |
| Built-in Handshake browser | WebView2 tab for browsing Handshake TLD sites (.forever, .badass, etc.) directly in the app. When connected, Handshake DNS resolves these automatically. | Medium |
| Code signing | Signed installer removes "Unknown publisher" warning | Low (requires certificate) |
| Auto-updater | Background service checks for new versions and installs silently | Medium |
| System tray mode | Minimize to tray, quick connect/disconnect from tray icon | Low |
| Windows Service tunnel | VPN tunnel runs as system service (survives user logout) | High |
If you'd like to see this become a full release, open an issue or contribute.
MIT