Skip to content

Commit

Permalink
feat: Add swagger and explorer(GQL)
Browse files Browse the repository at this point in the history
  • Loading branch information
s2quake committed Aug 23, 2024
1 parent 5f6ffe1 commit 5dec07a
Show file tree
Hide file tree
Showing 14 changed files with 310 additions and 36 deletions.
42 changes: 42 additions & 0 deletions Libplanet.sln
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Libplanet.Node.Executable",
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Libplanet.Node.Tests", "sdk\node\Libplanet.Node.Tests\Libplanet.Node.Tests.csproj", "{C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Libplanet.Node.Swagger", "sdk\node\Libplanet.Node.Swagger\Libplanet.Node.Swagger.csproj", "{FC6FACBF-4529-4458-8317-FC4CB925C8A5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Libplanet.Node.Explorer", "sdk\node\Libplanet.Node.Explorer\Libplanet.Node.Explorer.csproj", "{BA40A654-5AF6-478E-9C1A-E20E046750B1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -697,6 +701,42 @@ Global
{C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}.ReleaseMono|x64.Build.0 = Debug|Any CPU
{C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}.ReleaseMono|x86.ActiveCfg = Debug|Any CPU
{C050C5F0-8A40-4CB1-9715-A55EBF94FBF2}.ReleaseMono|x86.Build.0 = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Debug|x64.ActiveCfg = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Debug|x64.Build.0 = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Debug|x86.ActiveCfg = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Debug|x86.Build.0 = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Release|Any CPU.Build.0 = Release|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Release|x64.ActiveCfg = Release|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Release|x64.Build.0 = Release|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Release|x86.ActiveCfg = Release|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.Release|x86.Build.0 = Release|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.ReleaseMono|Any CPU.ActiveCfg = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.ReleaseMono|Any CPU.Build.0 = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.ReleaseMono|x64.ActiveCfg = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.ReleaseMono|x64.Build.0 = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.ReleaseMono|x86.ActiveCfg = Debug|Any CPU
{FC6FACBF-4529-4458-8317-FC4CB925C8A5}.ReleaseMono|x86.Build.0 = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Debug|x64.ActiveCfg = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Debug|x64.Build.0 = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Debug|x86.ActiveCfg = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Debug|x86.Build.0 = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Release|Any CPU.Build.0 = Release|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Release|x64.ActiveCfg = Release|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Release|x64.Build.0 = Release|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Release|x86.ActiveCfg = Release|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.Release|x86.Build.0 = Release|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.ReleaseMono|Any CPU.ActiveCfg = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.ReleaseMono|Any CPU.Build.0 = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.ReleaseMono|x64.ActiveCfg = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.ReleaseMono|x64.Build.0 = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.ReleaseMono|x86.ActiveCfg = Debug|Any CPU
{BA40A654-5AF6-478E-9C1A-E20E046750B1}.ReleaseMono|x86.Build.0 = Debug|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -737,6 +777,8 @@ Global
{704BA731-9C70-4CBE-A607-1A2E1FB73753} = {8CA69CC9-3415-4484-9342-88D495AE2FF6}
{A0EAD8F0-B7A3-4112-9F3F-2D9922A500BA} = {8CA69CC9-3415-4484-9342-88D495AE2FF6}
{C050C5F0-8A40-4CB1-9715-A55EBF94FBF2} = {8CA69CC9-3415-4484-9342-88D495AE2FF6}
{FC6FACBF-4529-4458-8317-FC4CB925C8A5} = {8CA69CC9-3415-4484-9342-88D495AE2FF6}
{BA40A654-5AF6-478E-9C1A-E20E046750B1} = {8CA69CC9-3415-4484-9342-88D495AE2FF6}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DB552D2A-94E1-4A1C-9F3E-E0097C6158CD}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@
<ItemGroup>
<ProjectReference Include="..\Libplanet.Node.Extensions\Libplanet.Node.Extensions.csproj" />
<ProjectReference Include="..\Libplanet.Node\Libplanet.Node.csproj" />
<ProjectReference Include="..\Libplanet.Node.Swagger\Libplanet.Node.Swagger.csproj" />
<ProjectReference Include="..\Libplanet.Node.Explorer\Libplanet.Node.Explorer.csproj" />
</ItemGroup>

</Project>
84 changes: 49 additions & 35 deletions sdk/node/Libplanet.Node.Executable/Program.cs
Original file line number Diff line number Diff line change
@@ -1,48 +1,62 @@
using Libplanet.Node.API.Services;
using Libplanet.Node.Extensions;
using Libplanet.Node.Options.Schema;
using Microsoft.AspNetCore;
using Microsoft.AspNetCore.Server.Kestrel.Core;

SynchronizationContext.SetSynchronizationContext(new());
var builder = WebApplication.CreateBuilder(args);

builder.Logging.AddConsole();

if (builder.Environment.IsDevelopment())
var builder = WebHost.CreateDefaultBuilder(args);
var assemblies = new string[]
{
"Libplanet.Node.Swagger",
"Libplanet.Node.Explorer",
};
builder.UseSetting(WebHostDefaults.HostingStartupAssembliesKey, string.Join(';', assemblies));
builder.ConfigureLogging(logging =>
{
logging.AddConsole();
});
builder.ConfigureKestrel((context, options) =>
{
builder.WebHost.ConfigureKestrel(options =>
if (context.HostingEnvironment.IsDevelopment())
{
// Setup a HTTP/2 endpoint without TLS.
options.ListenLocalhost(5259, o => o.Protocols =
HttpProtocols.Http1AndHttp2);
});
}

// Additional configuration is required to successfully run gRPC on macOS.
// For instructions on how to configure Kestrel and gRPC clients on macOS,
// visit https://go.microsoft.com/fwlink/?linkid=2099682

// Add services to the container.
builder.Services.AddGrpc();
builder.Services.AddGrpcReflection();
var libplanetBuilder = builder.Services.AddLibplanetNode(builder.Configuration);

var app = builder.Build();
var handlerMessage = """
Communication with gRPC endpoints must be made through a gRPC client. To learn how to
create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909
""";
var schema = await OptionsSchemaBuilder.GetSchemaAsync(default);

// Configure the HTTP request pipeline.
app.MapGrpcService<BlockChainGrpcService>();
app.MapGrpcService<SchemaGrpcService>();
app.MapGet("/", () => handlerMessage);
app.MapGet("/schema", () => schema);

if (builder.Environment.IsDevelopment())
}
});
builder.ConfigureServices((context, services) =>
{
app.MapGrpcReflectionService().AllowAnonymous();
}
services.AddGrpc();
services.AddGrpcReflection();
services.AddLibplanetNode(context.Configuration);
});
builder.Configure((context, app) =>
{
app.UseRouting();
app.UseEndpoints(endPoint =>
{
var handlerMessage = """
Communication with gRPC endpoints must be made through a gRPC client. To learn how to
create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909
""";
string? schema = null;
endPoint.MapGet(string.Empty, async context =>
{
await context.Response.WriteAsync(handlerMessage);
});
endPoint.MapGet("/schema", async context =>
{
schema ??= await OptionsSchemaBuilder.GetSchemaAsync(context.RequestAborted);
await context.Response.WriteAsync(schema);
});
endPoint.MapGrpcService<BlockChainGrpcService>();
endPoint.MapGrpcService<SchemaGrpcService>();
if (context.HostingEnvironment.IsDevelopment())
{
endPoint.MapGrpcReflectionService().AllowAnonymous();
}
});
});

using var app = builder.Build();
await app.RunAsync();
30 changes: 30 additions & 0 deletions sdk/node/Libplanet.Node.Executable/appsettings-schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,28 @@
}
}
},
"Swagger": {
"title": "SwaggerOptions",
"type": "object",
"additionalProperties": false,
"properties": {
"IsEnabled": {
"type": "boolean",
"default": true
}
}
},
"Explorer": {
"title": "ExplorerOptions",
"type": "object",
"additionalProperties": false,
"properties": {
"IsEnabled": {
"type": "boolean",
"default": true
}
}
},
"Genesis": {
"title": "GenesisOptions",
"type": "object",
Expand Down Expand Up @@ -1221,6 +1243,14 @@
{
"type": "object",
"properties": {
"Swagger": {
"description": "Type 'SwaggerOptions' does not have a description.",
"$ref": "#/definitions/Swagger"
},
"Explorer": {
"description": "Type 'ExplorerOptions' does not have a description.",
"$ref": "#/definitions/Explorer"
},
"Genesis": {
"description": "Options for the genesis block.",
"$ref": "#/definitions/Genesis"
Expand Down
39 changes: 39 additions & 0 deletions sdk/node/Libplanet.Node.Explorer/BlockChainContext.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Reflection;
using Libplanet.Blockchain;
using Libplanet.Explorer.Indexing;
using Libplanet.Explorer.Interfaces;
using Libplanet.Net;
using Libplanet.Node.Services;
using Libplanet.Store;

namespace Libplanet.Node.Explorer;

internal sealed class BlockChainContext(
IBlockChainService blockChainService, ISwarmService swarmService) : IBlockChainContext
{
public bool Preloaded => false;

public BlockChain BlockChain => blockChainService.BlockChain;

#pragma warning disable S3011 // Reflection should not be used to increase accessibility ...
public IStore Store
{
get
{
var bindingFlags = BindingFlags.NonPublic | BindingFlags.Instance;
var propertyInfo = typeof(BlockChain).GetProperty("Store", bindingFlags) ??
throw new InvalidOperationException("Store property not found.");
if (propertyInfo.GetValue(BlockChain) is IStore store)
{
return store;
}

throw new InvalidOperationException("Store property is not IStore.");
}
}
#pragma warning restore S3011

public Swarm Swarm => swarmService.Swarm;

public IBlockChainIndex Index => throw new NotSupportedException();
}
46 changes: 46 additions & 0 deletions sdk/node/Libplanet.Node.Explorer/ExplorerHostingStartup.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Libplanet.Explorer;
using Libplanet.Node.Explorer;
using Libplanet.Node.Explorer.Options;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;

[assembly: HostingStartup(typeof(ExplorerHostingStartup))]

namespace Libplanet.Node.Explorer;

internal sealed class ExplorerHostingStartup : IHostingStartup, IStartupFilter
{
private ExplorerStartup<BlockChainContext>? _startUp;

public void Configure(IWebHostBuilder builder)
{
builder.ConfigureServices((context, services) =>
{
services.AddOptions<ExplorerOptions>()
.Bind(context.Configuration.GetSection(ExplorerOptions.Position));

var serviceProvider = services.BuildServiceProvider();
var options = serviceProvider.GetRequiredService<IOptions<ExplorerOptions>>().Value;

if (options.IsEnabled)
{
_startUp = new ExplorerStartup<BlockChainContext>(context.Configuration);
_startUp.ConfigureServices(services);
services.AddSingleton<IStartupFilter>(this);
}
});
}

public Action<IApplicationBuilder> Configure(Action<IApplicationBuilder> next)
{
return builder =>
{
var serviceProvider = builder.ApplicationServices;
var environment = serviceProvider.GetRequiredService<IWebHostEnvironment>();
_startUp?.Configure(builder, environment);
next(builder);
};
}
}
11 changes: 11 additions & 0 deletions sdk/node/Libplanet.Node.Explorer/Libplanet.Node.Explorer.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Libplanet.Node\Libplanet.Node.csproj" />
<ProjectReference Include="..\..\..\tools\Libplanet.Explorer.Executable\Libplanet.Explorer.Executable.csproj" />
</ItemGroup>

</Project>
13 changes: 13 additions & 0 deletions sdk/node/Libplanet.Node.Explorer/Options/ExplorerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.ComponentModel;
using Libplanet.Node.Options;

namespace Libplanet.Node.Explorer.Options;

[Options(Position)]
public sealed class ExplorerOptions : OptionsBase<ExplorerOptions>
{
public const string Position = "Explorer";

[DefaultValue(true)]
public bool IsEnabled { get; set; } = true;
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
using Libplanet.Blockchain;
using Libplanet.Node.Extensions.NodeBuilder;
using Libplanet.Node.Options;
using Libplanet.Node.Services;
Expand Down
14 changes: 14 additions & 0 deletions sdk/node/Libplanet.Node.Swagger/Libplanet.Node.Swagger.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<Project Sdk="Microsoft.NET.Sdk">

<ItemGroup>
<PackageReference Include="Swashbuckle.AspNetCore.Swagger" Version="6.7.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerGen" Version="6.7.0" />
<PackageReference Include="Swashbuckle.AspNetCore.SwaggerUI" Version="6.7.0" />
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.7" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Libplanet.Node\Libplanet.Node.csproj" />
</ItemGroup>

</Project>
13 changes: 13 additions & 0 deletions sdk/node/Libplanet.Node.Swagger/Options/SwaggerOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
using System.ComponentModel;
using Libplanet.Node.Options;

namespace Libplanet.Node.Swagger.Options;

[Options(Position)]
public sealed class SwaggerOptions : OptionsBase<SwaggerOptions>
{
public const string Position = "Swagger";

[DefaultValue(true)]
public bool IsEnabled { get; set; } = true;
}
Loading

0 comments on commit 5dec07a

Please sign in to comment.