XcavateProfileApiClient 1.0.61
dotnet add package XcavateProfileApiClient --version 1.0.61
NuGet\Install-Package XcavateProfileApiClient -Version 1.0.61
<PackageReference Include="XcavateProfileApiClient" Version="1.0.61" />
<PackageVersion Include="XcavateProfileApiClient" Version="1.0.61" />
<PackageReference Include="XcavateProfileApiClient" />
paket add XcavateProfileApiClient --version 1.0.61
#r "nuget: XcavateProfileApiClient, 1.0.61"
#:package XcavateProfileApiClient@1.0.61
#addin nuget:?package=XcavateProfileApiClient&version=1.0.61
#tool nuget:?package=XcavateProfileApiClient&version=1.0.61
XcavateProfileApiClient
C# client SDK for the Xcavate Profile API: a REST client for profiles, a StrawberryShake-generated GraphQL client for buckets, and the request signing both use.
Signs with Substrate sr25519 (hex) or Solana ed25519 (base58). Reads are public on both APIs; every write is signed.
Building a Solana-only application? XcavateProfileApiSolanaClient exposes this same API under the same namespaces without the
Substrate.NET.APIdependency — and therefore without StreamJsonRpc, Serilog, Newtonsoft.Json or MessagePack. Reference one or the other, never both: they define the same types.
dotnet add package XcavateProfileApiClient
Profiles (REST)
using Substrate.NetApi.Model.Types;
using XcavateProfile.Client;
using XcavateProfileApiClient.Signing;
using var client = new XcavateProfileClient(new XcavateProfileClientOptions
{
ApiUrl = "https://profile-api.xcavate.io"
});
// Reads need no signer.
var all = await client.GetProfilesAsync();
var one = await client.GetProfileAsync(address); // null when absent
var byNick = await client.GetProfileByNicknameAsync("myprofile");
// Writes take the signing account. Ss58Address and X25519Key are required.
var profile = new Profile
{
Ss58Address = account.Value,
X25519Key = "0x0123…",
Nickname = "myprofile",
Bio = "My Substrate profile"
};
await client.CreateProfileAsync(profile, account);
profile.Bio = "Updated bio";
await client.UpdateProfileAsync(account.Value, profile, account);
using (var image = File.OpenRead("profile.jpg"))
{
var imageUrl = await client.UploadImageAsync(account.Value, image, "profile.jpg", account);
}
await client.DeleteProfileAsync(account.Value, account);
Every write also has an IRequestSigner overload, which is how a non-Substrate scheme is selected:
await client.CreateProfileAsync(profile, new SolanaRequestSigner(solanaAccount));
All methods take an optional CancellationToken. The client is safe to use from concurrent calls,
and a second constructor accepts your own HttpClient — an IHttpClientFactory one, for
instance — which it will not dispose:
var client = new XcavateProfileClient(options, httpClientFactory.CreateClient("xcavate"));
Failed requests throw HttpRequestException carrying the status code and the server's explanation.
Buckets (GraphQL)
The generated client is registered through DI. SigningHttpMessageHandler signs the outgoing
request body, so it must be the outermost handler that touches it — supply a signer only when the
client sends mutations, since queries are public:
using XcavateProfileApiClient;
using XcavateProfileApiClient.Buckets;
services
.AddXcavateBucketsClient()
.ConfigureHttpClient(
client => client.BaseAddress = new Uri("https://profile-api.xcavate.io/graphql"),
builder => builder.ConfigurePrimaryHttpMessageHandler(
_ => new SigningHttpMessageHandler(account))); // or any IRequestSigner
var result = await client.CreateNamespace.ExecuteAsync(
new NamespaceMetadataInput { Name = "my-namespace", SchemaUri = "ipfs://…" });
result.EnsureNoErrors();
Signing primitives
CryptoHelper is the seam the client, the server and both schemes share:
byte[] digest = CryptoHelper.Hash(input); // Blake2b-128
string hex = CryptoHelper.HashHex(input); // 0x-prefixed, uppercase
string payload = CryptoHelper.ConstructPayload(method, path, body, timestamp);
byte[] signature = await CryptoHelper.SignAsync(payload, account); // sr25519
bool ok = CryptoHelper.VerifySignature(payload, signature, address);
body is an IPayloadBody — the Profile being sent, or EmptyPayloadBody.Instance — not a
pre-computed hash string. path is the decoded path, matching the route the server binds.
Requests carry three headers: X-SS58-Address, X-Signature and X-Timestamp (ISO-8601 UTC,
accepted within five minutes of the server's clock).
License and source
See the repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | 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
- Blake2Core (>= 1.0.0)
- MessagePack (>= 3.1.8)
- Solnet.Wallet (>= 6.1.0)
- StrawberryShake.Server (>= 16.5.1)
- Substrate.NET.API (>= 0.9.24)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.0.61 | 1 | 7/27/2026 |
| 1.0.59 | 73 | 7/26/2026 |
| 1.0.58 | 64 | 7/26/2026 |
| 1.0.57 | 77 | 7/25/2026 |
| 1.0.56 | 86 | 7/25/2026 |
| 1.0.55 | 103 | 7/16/2026 |
| 1.0.54 | 93 | 7/16/2026 |
| 1.0.53 | 84 | 7/16/2026 |
| 1.0.52 | 83 | 7/16/2026 |
| 1.0.51 | 88 | 7/16/2026 |
| 1.0.50 | 84 | 7/16/2026 |
| 1.0.49 | 88 | 7/16/2026 |
| 1.0.48 | 84 | 7/16/2026 |
| 1.0.47 | 90 | 7/16/2026 |
| 1.0.46 | 86 | 7/16/2026 |
| 1.0.45 | 85 | 7/16/2026 |
| 1.0.44 | 85 | 7/15/2026 |
| 1.0.43 | 91 | 7/15/2026 |
| 1.0.42 | 90 | 7/15/2026 |
| 1.0.41 | 91 | 7/15/2026 |