Greenfield: Add balance endpoint (#3887)

* Greenfield: Add balance endpoint

* Remove superfluous try/catch
This commit is contained in:
d11n 2022-06-23 06:42:28 +02:00 committed by GitHub
parent c89f7aaaed
commit 61c6a2ab57
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
10 changed files with 296 additions and 2 deletions

View file

@ -17,6 +17,15 @@ namespace BTCPayServer.Client
method: HttpMethod.Get), token);
return await HandleResponse<LightningNodeInformationData>(response);
}
public virtual async Task<LightningNodeBalanceData> GetLightningNodeBalance(string cryptoCode,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/balance",
method: HttpMethod.Get), token);
return await HandleResponse<LightningNodeBalanceData>(response);
}
public virtual async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
CancellationToken token = default)

View file

@ -17,6 +17,15 @@ namespace BTCPayServer.Client
method: HttpMethod.Get), token);
return await HandleResponse<LightningNodeInformationData>(response);
}
public virtual async Task<LightningNodeBalanceData> GetLightningNodeBalance(string storeId, string cryptoCode,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/balance",
method: HttpMethod.Get), token);
return await HandleResponse<LightningNodeBalanceData>(response);
}
public virtual async Task ConnectToLightningNode(string storeId, string cryptoCode, ConnectToNodeRequest request,
CancellationToken token = default)

View file

@ -0,0 +1,52 @@
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.Lightning;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class LightningNodeBalanceData
{
[JsonProperty("onchain")]
public OnchainBalanceData OnchainBalance { get; set; }
[JsonProperty("offchain")]
public OffchainBalanceData OffchainBalance { get; set; }
public LightningNodeBalanceData()
{
}
public LightningNodeBalanceData(OnchainBalanceData onchain, OffchainBalanceData offchain)
{
OnchainBalance = onchain;
OffchainBalance = offchain;
}
}
public class OnchainBalanceData
{
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Confirmed { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Unconfirmed { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Reserved { get; set; }
}
public class OffchainBalanceData
{
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Opening { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Local { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Remote { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Closing { get; set; }
}
}

View file

@ -26,7 +26,6 @@ namespace BTCPayServer.Controllers.Greenfield
private readonly LightningClientFactoryService _lightningClientFactory;
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
public GreenfieldInternalLightningNodeApiController(
BTCPayNetworkProvider btcPayNetworkProvider, PoliciesSettings policiesSettings, LightningClientFactoryService lightningClientFactory,
IOptions<LightningNetworkOptions> lightningNetworkOptions,
@ -46,6 +45,14 @@ namespace BTCPayServer.Controllers.Greenfield
return base.GetInfo(cryptoCode, cancellationToken);
}
[Authorize(Policy = Policies.CanUseInternalLightningNode,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/server/lightning/{cryptoCode}/balance")]
public override Task<IActionResult> GetBalance(string cryptoCode, CancellationToken cancellationToken = default)
{
return base.GetBalance(cryptoCode, cancellationToken);
}
[Authorize(Policy = Policies.CanUseInternalLightningNode,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/server/lightning/{cryptoCode}/connect")]

View file

@ -40,6 +40,7 @@ namespace BTCPayServer.Controllers.Greenfield
_lightningClientFactory = lightningClientFactory;
_btcPayNetworkProvider = btcPayNetworkProvider;
}
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/info")]
@ -48,6 +49,14 @@ namespace BTCPayServer.Controllers.Greenfield
return base.GetInfo(cryptoCode, cancellationToken);
}
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/balance")]
public override Task<IActionResult> GetBalance(string cryptoCode, CancellationToken cancellationToken = default)
{
return base.GetBalance(cryptoCode, cancellationToken);
}
[Authorize(Policy = Policies.CanUseLightningNodeInStore,
AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/lightning/{cryptoCode}/connect")]

View file

@ -24,6 +24,7 @@ namespace BTCPayServer.Controllers.Greenfield
// Do not mark handled, it is possible filters above have better errors
}
}
public abstract class GreenfieldLightningNodeApiController : Controller
{
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
@ -49,6 +50,32 @@ namespace BTCPayServer.Controllers.Greenfield
});
}
public virtual async Task<IActionResult> GetBalance(string cryptoCode, CancellationToken cancellationToken = default)
{
var lightningClient = await GetLightningClient(cryptoCode, true);
var balance = await lightningClient.GetBalance(cancellationToken);
return Ok(new LightningNodeBalanceData
{
OnchainBalance = balance.OnchainBalance != null
? new OnchainBalanceData
{
Confirmed = balance.OnchainBalance.Confirmed,
Unconfirmed = balance.OnchainBalance.Unconfirmed,
Reserved = balance.OnchainBalance.Reserved
}
: null,
OffchainBalance = balance.OffchainBalance != null
? new OffchainBalanceData
{
Opening = balance.OffchainBalance.Opening,
Local = balance.OffchainBalance.Local,
Remote = balance.OffchainBalance.Remote,
Closing = balance.OffchainBalance.Closing,
}
: null
});
}
public virtual async Task<IActionResult> ConnectToNode(string cryptoCode, ConnectToNodeRequest request, CancellationToken cancellationToken = default)
{
var lightningClient = await GetLightningClient(cryptoCode, true);

View file

@ -533,6 +533,13 @@ namespace BTCPayServer.Controllers.Greenfield
await _storeLightningNodeApiController.GetInfo(cryptoCode, token));
}
public override async Task<LightningNodeBalanceData> GetLightningNodeBalance(string storeId, string cryptoCode,
CancellationToken token = default)
{
return GetFromActionResult<LightningNodeBalanceData>(
await _storeLightningNodeApiController.GetBalance(cryptoCode));
}
public override async Task ConnectToLightningNode(string storeId, string cryptoCode,
ConnectToNodeRequest request, CancellationToken token = default)
{
@ -587,6 +594,13 @@ namespace BTCPayServer.Controllers.Greenfield
await _lightningNodeApiController.GetInfo(cryptoCode));
}
public override async Task<LightningNodeBalanceData> GetLightningNodeBalance(string cryptoCode,
CancellationToken token = default)
{
return GetFromActionResult<LightningNodeBalanceData>(
await _lightningNodeApiController.GetBalance(cryptoCode));
}
public override async Task ConnectToLightningNode(string cryptoCode, ConnectToNodeRequest request,
CancellationToken token = default)
{

View file

@ -197,6 +197,68 @@
}
}
},
"LightningNodeBalanceData": {
"type": "object",
"properties": {
"onchain": {
"type": "object",
"description": "On-chain balance of the Lightning node",
"nullable": true,
"$ref": "#/components/schemas/OnchainBalanceData"
},
"offchain": {
"type": "object",
"description": "Off-chain balance of the Lightning node",
"nullable": true,
"$ref": "#/components/schemas/OffchainBalanceData"
}
}
},
"OnchainBalanceData": {
"type": "object",
"properties": {
"confirmed": {
"type": "string",
"description": "The confirmed amount in millisatoshi",
"nullable": true
},
"unconfirmed": {
"type": "string",
"description": "The unconfirmed amount in millisatoshi",
"nullable": true
},
"reserved": {
"type": "string",
"description": "The reserved amount in millisatoshi",
"nullable": true
}
}
},
"OffchainBalanceData": {
"type": "object",
"properties": {
"opening": {
"type": "string",
"description": "The amount of current channel openings in millisatoshi",
"nullable": true
},
"local": {
"type": "string",
"description": "The amount that is available on the local end of active channels in millisatoshi",
"nullable": true
},
"remote": {
"type": "string",
"description": "The amount that is available on the remote end of active channels in millisatoshi",
"nullable": true
},
"closing": {
"type": "string",
"description": "The amount of current channel closings in millisatoshi",
"nullable": true
}
}
},
"PayLightningInvoiceRequest": {
"type": "object",
"properties": {

View file

@ -48,6 +48,54 @@
]
}
},
"/api/v1/server/lightning/{cryptoCode}/balance": {
"get": {
"tags": [
"Lightning (Internal Node)"
],
"summary": "Get node balance",
"parameters": [
{
"name": "cryptoCode",
"in": "path",
"required": true,
"description": "The cryptoCode of the lightning-node to query",
"schema": {
"type": "string"
},
"example": "BTC"
}
],
"description": "View balance of the lightning node",
"operationId": "InternalLightningNodeApi_GetBalance",
"responses": {
"200": {
"description": "Lightning node balance for on-chain and off-chain funds",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LightningNodeBalanceData"
}
}
}
},
"503": {
"description": "Unable to access the lightning node"
},
"404": {
"description": "The lightning node configuration was not found"
}
},
"security": [
{
"API_Key": [
"btcpay.server.canuseinternallightningnode"
],
"Basic": []
}
]
}
},
"/api/v1/server/lightning/{cryptoCode}/connect": {
"post": {
"tags": [

View file

@ -50,7 +50,64 @@
"security": [
{
"API_Key": [
"btcpay.store.cancreatelightninginvoice"
"btcpay.store.canuselightningnode"
],
"Basic": []
}
]
}
},
"/api/v1/stores/{storeId}/lightning/{cryptoCode}/balance": {
"get": {
"tags": [
"Lightning (Store)"
],
"summary": "Get node balance",
"parameters": [
{
"name": "cryptoCode",
"in": "path",
"required": true,
"description": "The cryptoCode of the lightning-node to query",
"schema": {
"type": "string"
},
"example": "BTC"
},
{
"name": "storeId",
"in": "path",
"required": true,
"description": "The store id with the lightning-node configuration to query",
"schema": {
"type": "string"
}
}
],
"description": "View balance of the lightning node",
"operationId": "StoreLightningNodeApi_GetBalance",
"responses": {
"200": {
"description": "Lightning node balance for on-chain and off-chain funds",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/LightningNodeBalanceData"
}
}
}
},
"503": {
"description": "Unable to access the lightning node"
},
"404": {
"description": "The lightning node configuration was not found"
}
},
"security": [
{
"API_Key": [
"btcpay.store.canuselightningnode"
],
"Basic": []
}