Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[New] RestServer Plugin #3390

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
47e11e0
Added `RestServer` Plugin
cschuchardt88 Jul 2, 2024
bd94807
Merge branch 'master' into add/plugins/rest-server
NGDAdmin Jul 5, 2024
e261aa6
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Jul 9, 2024
5e8d98f
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Jul 16, 2024
6ab87d5
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Jul 17, 2024
a8ac960
Update neo.sln
cschuchardt88 Jul 17, 2024
03e2298
Fixed issue with merging from master
cschuchardt88 Jul 17, 2024
287bbd7
Added @superboyiii request changes `PART-1`
cschuchardt88 Jul 17, 2024
08f74a6
Merge branch 'master' into add/plugins/rest-server
NGDAdmin Jul 17, 2024
8f0c919
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Jul 27, 2024
758894c
Update `sln` file
cschuchardt88 Jul 28, 2024
b45c59a
Added better checking for `IsNep11Supported` and `IsNep17Supported`
cschuchardt88 Jul 28, 2024
9dd47d9
Added `Confirmations` to `Block` JSON output
cschuchardt88 Jul 28, 2024
b310d99
variable name fixes
cschuchardt88 Jul 28, 2024
bcf109d
Merge branch 'master' into add/plugins/rest-server
NGDAdmin Aug 2, 2024
6d8f294
Merge branch 'master' into add/plugins/rest-server
NGDAdmin Aug 7, 2024
5240a05
Merge branch 'master' into add/plugins/rest-server
Jim8y Aug 14, 2024
498fd37
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Sep 1, 2024
7d9786e
Added `Signers` for `Invoking` contracts
cschuchardt88 Sep 1, 2024
5dd2083
Revert `Neo.CLI` Configuation file
cschuchardt88 Sep 1, 2024
698b88d
Merge branch 'master' into add/plugins/rest-server
NGDAdmin Sep 10, 2024
cc5ec4c
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Oct 3, 2024
5167332
Added `using` for `Neo.Extensions`
cschuchardt88 Oct 3, 2024
613e061
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Oct 13, 2024
91f3d42
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Oct 15, 2024
44d8edd
Update src/Plugins/RestServer/Helpers/ScriptHelper.cs
cschuchardt88 Nov 8, 2024
f34d387
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Nov 8, 2024
8c48031
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Nov 11, 2024
845c9ea
Merge branch 'master' into add/plugins/rest-server
Jim8y Nov 26, 2024
5c29eb7
Fixed InvokeMethod
cschuchardt88 Nov 26, 2024
3921d3f
Merge branch 'add/plugins/rest-server' of https://github.com/cschucha…
cschuchardt88 Nov 26, 2024
87dc996
dotnet format
cschuchardt88 Nov 26, 2024
b061e15
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Nov 27, 2024
2ef32eb
Merge branch 'master' into add/plugins/rest-server
cschuchardt88 Nov 28, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 108 additions & 0 deletions docs/RestServer/Addons.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
## RestServer Plugin
In this section of you will learn how to make a `neo-cli` plugin that integrates with `RestServer`
plugin. Lets take a look at [Example Plugin](/examples/RestServerPlugin).

- No reference to `RestServer` is required.
- Requires DotNet 7.0

## Folder Structure
```bash
Project
├── Controllers
│ └── ExampleController.cs
├── ExamplePlugin.cs
├── ExamplePlugin.csproj
├── Exceptions
│ └── CustomException.cs
└── Models
└── ErrorModel.cs
```
The only thing that is important here is the `controllers` folder. This folder is required for the `RestServer`
plugin to register the controllers in its web server. This location is where you put all your controllers.

## Controllers
The `controller` class is the same as ASP.Net Core's. Controllers must have their attribute set
as `[ApiController]` and inherent from `ControllerBase`.

## Swagger Controller
A `Swagger` controller uses special attributes that are set on your controller's class.

**Controller Class Attributes**
- `[Produces(MediaTypeNames.Application.Json)]` (_Required_)
- `[Consumes(MediaTypeNames.Application.Json)]` (_Required_)
- `[ApiExplorerSettings(GroupName = "v1")]`
- **GroupName** - _is which version of the API you are targeting._
- `[ProducesResponseType(StatusCodes.Status400BadRequest, Type = typeof(ErrorModel))]` (_Required_)
- **Type** - _Must have a base class of [error](#error-class)._

## Error Class
Needs to be the same as `RestServer` of else there will be some inconsistencies
with end users not knowing which type to use. This class can be `public` or `internal`.
Properties `Code`, `Name` and `Message` values can be whatever you desire.

**Model**
```csharp
public class ErrorModel
{
public int Code { get; set; };
public string Name { get; set; };
public string Message { get; set; };
}
```

## Controller Actions
Controller actions need to have special attributes as well as code comments.

- `[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]`

HTTP status code `200 (OK)` is required with return type defined. You can use more than one attribute. One per HTTP status code.

### Action Example
```csharp
[HttpGet("contracts/{hash:required}/sayHello", Name = "GetSayHello")]
[ProducesResponseType(StatusCodes.Status204NoContent)]
[ProducesResponseType(StatusCodes.Status200OK, Type = typeof(string))]
public IActionResult GetSayHello(
[FromRoute(Name = "hash")]
UInt160 scripthash)
{
if (scripthash == UInt160.Zero)
return NoContent();
return Ok($"Hello, {scripthash}");
}
```
Notice that the _above_ example also returns with HTTP status code of `204 No Content`.
This action `route` also extends the `contracts` API. Adding method `sayHello`. Routes
can be what you like as well. But if you want to extend on any existing controller you
must use existing routes paths.

### Path(s)
- `/api/v1/contracts/`
- `/api/v1/ledger/`
- `/api/v1/node/`
- `/api/v1/tokens`
- `/api/v1/Utils/`

### Excluded Path(s)
- `/api/v1/wallet/`

_for security reasons_.

### Code Comments for Swagger
```csharp
/// <summary>
///
/// </summary>
/// <param name="" example=""></param>
/// <returns></returns>
/// <response code="200">Successful</response>
/// <response code="400">An error occurred. See Response for details.</response>
```

Also note that you need to have `GenerateDocumentationFile` enabled in your
`.csproj` file. The `xml` file that is generated; in our case would be `RestServerPlugin.xml`.
This file gets put in same directory `Plugins/RestServerPlugin/` which is in the root of `neo-node`
executable folder. Where you will see `neo-cli.exe`.

File `RestServerPlugin.xml` will get added to `Swagger` automatically by the `RestServer`
plugin.
54 changes: 54 additions & 0 deletions docs/RestServer/ConfigFile.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
## Table

| Name | Type | Description |
| :--- | :---: | :--- |
|**Network**|_uint32_|_Network you would like the `RestServer` to be enabled on._|
|**BindAddress**|_string_|_Ip address of the interface you want to bind too._|
|**Port**|_uint32_|_Port number to bind too._|
|**KeepAliveTimeout**|_uint32_|_Time to keep the request alive, in seconds._|
|**SslCertFile**|_string_|_Is the path and file name of a certificate file, relative to the directory that contains the node's executable files._|
|**SslCertPassword**|_string_|_Is the password required to access the `X.509` certificate data._|
|**TrustedAuthorities**|_StringArray_|_Tumbprints of the of the last certificate authority in the chain._|
|**EnableBasicAuthentication**|_boolean_|_enables basic authentication._|
|**RestUser**|_string_|_Basic authentication's `username`._|
|**RestPass**|_string_|_Basic authentication's `password`._|
|**EnableCors**|_boolean_|_Enables Cross-origin resource sharing (`CORS`). Note by default it enables `*` any origin._|
|**AllowOrigins**|_StringArray_|_A list of the origins to allow. Note needs to add origins for basic auth to work with `CORS`._|
|**DisableControllers**|_StringArray_|_A list of `controllers` to be disabled. Requires restart of the node, if changed._|
|**EnableCompression**|_boolean_|_Enables `GZip` data compression._|
|**CompressionLevel**|_enum_|_Compression level. Values can be `Fastest`, `Optimal`, `NoCompression` or `SmallestSize`_|
|**EnableForwardedHeaders**|_boolean_|_Enables response/request headers for proxy forwarding. (data center usage)_|
|**EnableSwagger**|_boolean_|_Enables `Swagger` with `Swagger UI` for the rest services._|
|**MaxPageSize**|_uint32_|_Max page size for searches on `Ledger`/`Contracts` route._|
|**MaxConcurrentConnections**|_int64_|_Max allow concurrent HTTP connections._|
|**MaxInvokeGas**|_int64_|_Max gas to be invoked on the `Neo` virtual machine._|

## Default "Config.json" file
```json
{
"PluginConfiguration": {
"Network": 860833102,
"BindAddress": "127.0.0.1",
"Port": 10339,
"KeepAliveTimeout": 120,
"SslCertFile": "",
"SslCertPassword": "",
"TrustedAuthorities": [],
"EnableBasicAuthentication": false,
"RestUser": "",
"RestPass": "",
"EnableCors": true,
"AllowOrigins": [],
"DisableControllers": [ "WalletController" ],
"EnableCompression": true,
"CompressionLevel": "SmallestSize",
"EnableForwardedHeaders": false,
"EnableSwagger": true,
"MaxPageSize": 50,
"MaxConcurrentConnections": 40,
"MaxTransactionFee": 10000000,
"MaxInvokeGas": 20000000,
"WalletSessionTimeout": 120
}
}
```
144 changes: 144 additions & 0 deletions docs/RestServer/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
## RestServer
In this section you will learn about `RestServer` plugin and how it works.

See [config.json](ConfigFile.md) for information about the configurations.

## Dependencies
- **Microsoft.AspNetCore.JsonPatch.dll** `Required`
- **Microsoft.AspNetCore.Mvc.NewtonsoftJson.dll** `Required`
- **Microsoft.AspNetCore.Mvc.Versioning.ApiExplorer.dll** `Required`
- **Microsoft.AspNetCore.Mvc.Versioning.dll** `Required`
- **Microsoft.OpenApi.dll** `Required`
- **Newtonsoft.Json.Bson.dll** `Required`
- **Newtonsoft.Json.dll** `Required`
- **System.ServiceProcess.ServiceController.dll** `Required`
- **Microsoft.AspNetCore.Mvc.Versioning.dll** `Required`
- **Microsoft.AspNetCore.Mvc.Versioning.dll** `Required`
- **Microsoft.AspNetCore.Mvc.Versioning.dll** `Required`
- **Microsoft.OpenApi.dll** `Swagger`
- **Swashbuckle.AspNetCore.Swagger.dll** `Swagger`
- **Swashbuckle.AspNetCore.SwaggerGen.dll** `Swagger`
- **Swashbuckle.AspNetCore.SwaggerUI.dll** `Swagger`
- **Swashbuckle.AspNetCore.Newtonsoft.dll** `Swagger`
- **RestServer.xml** `Swagger UI`

These files go in the same directory as the `RestServer.dll`. In neo-cli
`plugins/RestServer/` folder.

## Response Headers
| Name | Value(s) | Description |
| :---: | --- | :--- |
|**server**|_neo-cli/3.6.0 RestServer/3.6.0_|_`neo-cli` and `RestServer` version._|

Custom headers can be added by [Neo RestServer Plugins](Addons.md).

## JSON Serializer
`RestServer` uses custom NewtonSoft JSON Converters to serialize controller action
responses and `route` parameters.

**One Way Binding** - `Write` only.
- `Neo.SmartContract.ContractState`
- `Neo.SmartContract.NefFile`
- `Neo.SmartContract.MethodToken`
- `Neo.SmartContract.Native.TrimmedBlock`
- `Neo.SmartContract.Manifest.ContractAbi`
- `Neo.SmartContract.Manifest.ContractGroup`
- `Neo.SmartContract.Manifest.ContractManifest`
- `Neo.SmartContract.Manifest.ContractPermission`
- `Neo.SmartContract.Manifest.ContractPermissionDescriptor`
- `Neo.Network.P2P.Payloads.Block`
- `Neo.Network.P2P.Payloads.Header`
- `Neo.Network.P2P.Payloads.Signer`
- `Neo.Network.P2P.Payloads.TransactionAttribute`
- `Neo.Network.P2P.Payloads.Transaction`
- `Neo.Network.P2P.Payloads.Witness`

**Two Way Binding** - `Read` & `Write`
- `System.Guid`
- `System.ReadOnlyMemory<T>`
- `Neo.BigDecimal`
- `Neo.UInt160`
- `Neo.UInt256`
- `Neo.Cryptography.ECC.ECPoint`
- `Neo.VM.Types.Array`
- `Neo.VM.Types.Boolean`
- `Neo.VM.Types.Buffer`
- `Neo.VM.Types.ByteString`
- `Neo.VM.Types.Integer`
- `Neo.VM.Types.InteropInterface`
- `Neo.VM.Types.Null`
- `Neo.VM.Types.Map`
- `Neo.VM.Types.Pointer`
- `Neo.VM.Types.StackItem`
- `Neo.VM.Types.Struct`

## Remote Endpoints
Parametes `{hash}` can be any Neo N3 address or scripthash; `{address}` can be any Neo N3 address **only**; `{number}` and `{index}` can be any _**uint32**_.

**Parameter Examples**
- `{hash}` - _0xef4073a0f2b305a38ec4050e4d3d28bc40ea63f5_ **or** _NiHURyS83nX2mpxtA7xq84cGxVbHojj5Wc_
- `{address}` - _NiHURyS83nX2mpxtA7xq84cGxVbHojj5Wc_
- `{number}` - _1_
- `{index}` - _2500000_

**Paths**
- Utils
- `[GET]` `/api/v1/utils/{hash}/address`
- `[GET]` `/api/v1/utils/{address}/scripthash`
- `[GET]` `/api/v1/utils/{hash}/{address}/validate`
- Node
- `[GET]` `/api/v1/node/peers`
- `[GET]` `/api/v1/node/plugins`
- `[GET]` `/api/v1/node/settings`
- Ledger
- `[GET]` `/api/v1/ledger/neo/accounts`
- `[GET]` `/api/v1/ledger/gas/accounts`
- `[GET]` `/api/v1/ledger/blocks?page={number}&size={number}`
- `[GET]` `/api/v1/ledger/blocks/height`
- `[GET]` `/api/v1/ledger/blocks/{index}`
- `[GET]` `/api/v1/ledger/blocks/{index}/header`
- `[GET]` `/api/v1/ledger/blocks/{index}/witness`
- `[GET]` `/api/v1/ledger/blocks/{index}/transactions?page={number}&size={number}`
- `[GET]` `/api/v1/ledger/transactions/{hash}`
- `[GET]` `/api/v1/ledger/transactions/{hash}/witnesses`
- `[GET]` `/api/v1/ledger/transactions/{hash}/signers`
- `[GET]` `/api/v1/ledger/transactions/{hash}/atributes`
- `[GET]` `/api/v1/ledger/memorypool?page={number}&size={number}`
- `[GET]` `/api/v1/ledger/memorypool/verified?page={number}&size={number}`
- `[GET]` `/api/v1/ledger/memorypool/unverified?page={number}&size={number}`
- `[GET]` `/api/v1/ledger/memorypool/count`
- Tokens
- `[GET]` `/api/v1/tokens/balanceof/{address}`
- NFTs
- `[GET]` `/api/v1/tokens/nep-11?page={number}&size={number}`
- `[GET]` `/api/v1/tokens/nep-11/count`
- `[GET]` `/api/v1/tokens/nep-11/{hash}/balanceof/{address}`
- NEP-17
- `[GET]` `/api/v1/tokens/nep-17?page={number}&size={number}`
- `[GET]` `/api/v1/tokens/nep-17/count`
- `[GET]` `/api/v1/tokens/nep-17/{hash}/balanceof/{address}`
- Contracts
- `[GET]` `/api/v1/contracts?page={number}&size={number}`
- `[GET]` `/api/v1/contracts/count`
- `[GET]` `/api/v1/contracts/{hash}`
- `[GET]` `/api/v1/contracts/{hash}/abi`
- `[GET]` `/api/v1/contracts/{hash}/manifest`
- `[GET]` `/api/v1/contracts/{hash}/nef`
- `[GET]` `/api/v1/contracts/{hash}/storage`
- Wallet
- `[POST]` `/api/v1/wallet/open`
- `[POST]` `/api/v1/wallet/create`
- `[POST]` `/api/v1/wallet/{session}/address/create`
- `[GET]` `/api/v1/wallet/{session}/address/list`
- `[GET]` `/api/v1/wallet/{session}/asset/list`
- `[GET]` `/api/v1/wallet/{session}/balance/list`
- `[POST]` `/api/v1/wallet/{session}/changepassword`
- `[GET]` `/api/v1/wallet/{session}/close`
- `[GET]` `/api/v1/wallet/{session}/delete/{address}`
- `[GET]` `/api/v1/wallet/{session}/export/{address}`
- `[GET]` `/api/v1/wallet/{session}/export`
- `[GET]` `/api/v1/wallet/{session}/gas/unclaimed`
- `[GET]` `/api/v1/wallet/{session}/key/list`
- `[POST]` `/api/v1/wallet/{session}/import`
- `[POST]` `/api/v1/wallet/{session}/import/multisigaddress`
- `[POST]` `/api/v1/wallet/{session}/transfer`
17 changes: 17 additions & 0 deletions neo.sln
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,17 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TokensTracker", "src\Plugin
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RpcClient", "src\Plugins\RpcClient\RpcClient.csproj", "{185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "RestServer", "src\Plugins\RestServer\RestServer.csproj", "{111264B9-A342-4AFF-B959-C82561299F9B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "docs", "docs", "{B753DC70-E313-4B73-B8F0-45D54126DE92}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "rest-server", "rest-server", "{40AB8866-F8A1-4DD4-868D-35F2B06ADEAB}"
ProjectSection(SolutionItems) = preProject
docs\RestServer\Addons.md = docs\RestServer\Addons.md
docs\RestServer\ConfigFile.md = docs\RestServer\ConfigFile.md
docs\RestServer\README.md = docs\RestServer\README.md
EndProjectSection
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -216,6 +227,10 @@ Global
{185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0}.Release|Any CPU.Build.0 = Release|Any CPU
{111264B9-A342-4AFF-B959-C82561299F9B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{111264B9-A342-4AFF-B959-C82561299F9B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{111264B9-A342-4AFF-B959-C82561299F9B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{111264B9-A342-4AFF-B959-C82561299F9B}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -255,6 +270,8 @@ Global
{FF76D8A4-356B-461A-8471-BC1B83E57BBC} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{5E4947F3-05D3-4806-B0F3-30DAC71B5986} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{185ADAFC-BFC6-413D-BC2E-97F9FB0A8AF0} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{111264B9-A342-4AFF-B959-C82561299F9B} = {C2DC830A-327A-42A7-807D-295216D30DBB}
{40AB8866-F8A1-4DD4-868D-35F2B06ADEAB} = {B753DC70-E313-4B73-B8F0-45D54126DE92}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BCBA19D9-F868-4C6D-8061-A2B91E06E3EC}
Expand Down
Loading
Loading