NetLedger.Sdk
4.0.0
dotnet add package NetLedger.Sdk --version 4.0.0
NuGet\Install-Package NetLedger.Sdk -Version 4.0.0
<PackageReference Include="NetLedger.Sdk" Version="4.0.0" />
<PackageVersion Include="NetLedger.Sdk" Version="4.0.0" />
<PackageReference Include="NetLedger.Sdk" />
paket add NetLedger.Sdk --version 4.0.0
#r "nuget: NetLedger.Sdk, 4.0.0"
#:package NetLedger.Sdk@4.0.0
#addin nuget:?package=NetLedger.Sdk&version=4.0.0
#tool nuget:?package=NetLedger.Sdk&version=4.0.0
NetLedger SDK for .NET
A .NET SDK for interacting with the NetLedger Server REST API.
v4.0.0 Archive Support
NetLedger Server clients remain active-data clients. v4.0.0 adds Archive Server methods for cold reads, archive metadata inspection, and migration lifecycle operations. Keep active and archive clients configured with separate base URLs.
using NetLedger.Sdk;
using NetLedgerClient active = new NetLedgerClient("http://localhost:8080", token, tenantId);
using NetLedgerClient archive = new NetLedgerClient("http://localhost:8081", token, tenantId);
ArchiveHealth health = await archive.Archive.HealthAsync();
List<ArchiveManifestInfo> manifests = await archive.Archive.ManifestsAsync(new ArchiveQuery { MaxResults = 50 });
List<ArchiveStoragePoolInfo> pools = await archive.Archive.StoragePoolsAsync();
ArchiveStoragePoolHealthInfo poolHealth = await archive.Archive.StoragePoolHealthAsync(pools[0].Id!);
ArchiveExportResponse export = await active.Archive.ExportTenantAccountEntriesAsync(tenantId, accountId, new ArchiveExportRequest
{
ToUtc = DateTime.UtcNow.AddDays(-365),
DeleteAfterCommit = false
});
ArchiveMigrationInfo migration = await archive.Archive.MigrationAsync(export.MigrationId!);
List<ArchiveMigrationBatchInfo> batches = await archive.Archive.MigrationBatchesAsync(migration.Id!);
ArchiveExportResponse historyExport = await active.Archive.ExportRequestHistoryAsync(new ArchiveExportRequest
{
TenantId = tenantId,
ToUtc = DateTime.UtcNow.AddDays(-365)
});
EnumerationResult<Entry> coldEntries = await archive.Archive.TenantEntriesAsync(tenantId, accountId, new ArchiveQuery
{
MaxResults = 25,
Ordering = "CreatedDescending",
AllowPartial = true
});
ArchiveBalanceInfo coldBalance = await archive.Archive.TenantBalanceAsOfAsync(tenantId, accountId, DateTime.UtcNow.AddDays(-365));
ArchiveVerificationResult verification = await archive.Archive.VerifyTenantAccountAsync(tenantId, accountId);
EnumerationResult<RequestHistoryEntry> coldHistory = await archive.Archive.RequestHistoryAsync(new RequestHistoryQuery
{
MaxResults = 25,
AllowPartial = true
});
For externally prepared archive payloads, the Archive Server client also exposes the lower-level migration lifecycle: CreateMigrationAsync, CreateMigrationBatchAsync, UploadMigrationBatchContentAsync, SealMigrationAsync, CommitMigrationAsync, and AbortMigrationAsync.
For an end-to-end local validation that starts disposable active and archive servers, exports old entries, and verifies hot/cold retrieval seams, run dotnet run --project src/ArchivalValidation/ArchivalValidation.csproj --framework net8.0 from the repository root.
Installation
dotnet add package NetLedger.Sdk
Or add a project reference:
dotnet add reference path/to/NetLedger.Sdk.csproj
Quick Start
using NetLedger.Sdk;
// Create a client
using NetLedgerClient client = new NetLedgerClient("http://localhost:8080", "your-api-key");
// Check server health
bool isHealthy = await client.Service.HealthCheckAsync();
// Create an account
Account account = await client.Account.CreateAsync("My Account", "Optional notes");
// Add credits and debits
Entry credit = await client.Entry.AddCreditAsync(account.Id, 100.00m, "Initial deposit");
Entry debit = await client.Entry.AddDebitAsync(account.Id, 25.50m, "Purchase");
// Get balance
Balance balance = await client.Balance.GetAsync(account.Id);
Console.WriteLine($"Committed: {balance.CommittedBalance}, Pending: {balance.PendingBalance}");
// Commit pending entries
CommitResult result = await client.Balance.CommitAsync(account.Id);
Features
Service Operations
// Health check
bool healthy = await client.Service.HealthCheckAsync();
// Get service info
ServiceInfo info = await client.Service.GetInfoAsync();
// Get the OpenAPI document JSON used by the dashboard API Explorer
string openApiJson = await client.Service.GetOpenApiJsonAsync();
Account Management
// Create account
Account account = await client.Account.CreateAsync("Account Name", "Notes");
// Get account by ID
Account account = await client.Account.GetAsync(accountId);
// Get account by name
Account account = await client.Account.GetByNameAsync("Account Name");
// Check if account exists
bool exists = await client.Account.ExistsAsync(accountId);
// Delete account
await client.Account.DeleteAsync(accountId);
// Enumerate accounts with pagination
EnumerationResult<Account> result = await client.Account.EnumerateAsync(new AccountEnumerationQuery
{
MaxResults = 50,
Skip = 0,
SearchTerm = "search"
});
Entry Operations
// Add single credit
Entry credit = await client.Entry.AddCreditAsync(accountId, 100.00m, "Description");
// Add multiple credits
List<Entry> credits = await client.Entry.AddCreditsAsync(accountId, new List<EntryInput>
{
new EntryInput(50.00m, "First credit"),
new EntryInput(25.00m, "Second credit")
});
// Add single debit
Entry debit = await client.Entry.AddDebitAsync(accountId, 30.00m, "Description");
// Add multiple debits
List<Entry> debits = await client.Entry.AddDebitsAsync(accountId, new List<EntryInput>
{
new EntryInput(10.00m, "First debit"),
new EntryInput(15.00m, "Second debit")
});
// Get all entries
List<Entry> entries = await client.Entry.GetAllAsync(accountId);
// Enumerate with filters
EnumerationResult<Entry> result = await client.Entry.EnumerateAsync(accountId, new EntryEnumerationQuery
{
MaxResults = 100,
CreatedAfterUtc = DateTime.UtcNow.AddDays(-30),
AmountMinimum = 10.00m,
Ordering = EnumerationOrder.AmountDescending
});
// Enumerate debits between $5 and $50 with all metadata filters matched
EnumerationResult<Entry> blueDebits = await client.Entry.EnumerateAsync(accountId, new EntryEnumerationQuery
{
MaxResults = 50,
DebitMinimum = 5.00m,
DebitMaximum = 50.00m,
Labels = new List<string> { "blue" },
Tags = new Dictionary<string, string> { { "color", "blue" } },
Ordering = EnumerationOrder.AmountDescending
});
// Get pending entries
List<Entry> pending = await client.Entry.GetPendingAsync(accountId);
List<Entry> pendingCredits = await client.Entry.GetPendingCreditsAsync(accountId);
List<Entry> pendingDebits = await client.Entry.GetPendingDebitsAsync(accountId);
// Cancel a pending entry
await client.Entry.CancelAsync(accountId, entryId);
Balance Operations
// Get current balance
Balance balance = await client.Balance.GetAsync(accountId);
// Get historical balance
Balance historical = await client.Balance.GetAsOfAsync(accountId, DateTime.UtcNow.AddDays(-7));
// Get all account balances
List<Balance> balances = await client.Balance.GetAllAsync();
// Commit all pending entries
CommitResult result = await client.Balance.CommitAsync(accountId);
// Commit specific entries
CommitResult result = await client.Balance.CommitAsync(accountId, new List<string> { entry1Id, entry2Id });
// Verify balance chain integrity
bool isValid = await client.Balance.VerifyAsync(accountId);
API Key Management
// Create API key
CredentialCreateResponse apiKey = await client.ApiKey.CreateAsync("Key Name", isAdmin: false);
Console.WriteLine($"Key: {apiKey.SecretKey}"); // Only available on creation
// Enumerate API keys
EnumerationResult<ApiKeyInfo> result = await client.ApiKey.EnumerateAsync(new ApiKeyEnumerationQuery
{
MaxResults = 50,
Skip = 0
});
// Revoke API key
await client.ApiKey.RevokeAsync(apiKey.Credential?.Id ?? String.Empty);
Request History
Request history is available to administrators according to the server's tenant access rules. System administrators can inspect all tenants, while tenant administrators are scoped to their tenant.
EnumerationResult<RequestHistoryEntry> history = await client.RequestHistory.EnumerateAsync(new RequestHistoryQuery
{
TenantId = "default",
MaxResults = 25,
Skip = 0
});
RequestHistorySummary summary = await client.RequestHistory.SummarizeAsync(new RequestHistoryQuery
{
MaxResults = 100,
BucketMinutes = 15
});
RequestHistoryEntry entry = await client.RequestHistory.ReadAsync(history.Objects[0].Id);
Error Handling
The SDK throws specific exceptions for different error scenarios:
try
{
Account account = await client.Account.GetAsync(accountId);
}
catch (NetLedgerConnectionException ex)
{
// Unable to connect to the server
Console.WriteLine($"Connection error: {ex.Message}");
}
catch (NetLedgerApiException ex)
{
// Server returned an error
Console.WriteLine($"API error {ex.StatusCode}: {ex.Message}");
if (ex.Details != null)
Console.WriteLine($"Details: {ex.Details}");
}
catch (NetLedgerValidationException ex)
{
// Invalid input parameters
Console.WriteLine($"Validation error for {ex.ParameterName}: {ex.Message}");
}
Configuration
var client = new NetLedgerClient("http://localhost:8080", "your-api-key");
// Set custom timeout (default: 30 seconds)
client.TimeoutMs = 60000; // 60 seconds
Thread Safety
The NetLedgerClient is thread-safe and can be reused across multiple operations. It is recommended to create a single instance and share it across your application.
Disposal
The client implements IDisposable. Always dispose of it when done:
using NetLedgerClient client = new NetLedgerClient("http://localhost:8080", "your-api-key");
// Use client...
// Automatically disposed at end of scope
Or manually:
NetLedgerClient client = new NetLedgerClient("http://localhost:8080", "your-api-key");
try
{
// Use client...
}
finally
{
client.Dispose();
}
Running the Test Harness
dotnet run --project ../NetLedger.Sdk.Test/NetLedger.Sdk.Test.csproj -- http://localhost:8080 your-api-key
dotnet run --project ../NetLedger.Sdk.Test/NetLedger.Sdk.Test.csproj -- http://localhost:8080 your-api-key http://localhost:8081
The third argument is optional. When supplied, the harness also runs Archive Server health, storage-pool, metadata, request-history, and active export checks against the archive endpoint.
License
MIT License - see the LICENSE file for details.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 is compatible. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net10.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
NetLedger v4.0.0 SDK support for active/archive client separation, archive queries, archive metadata, and migration APIs.