GreenField: Add FeeRate To Wallets API (#2375)

* GreenField: Add FeeRate To Wallets API

closes #1846

* make dedicated endpoint for fee rate

* remove unused call
This commit is contained in:
Andrew Camilleri 2021-04-07 08:16:17 +02:00 committed by GitHub
parent 475809b1a0
commit f367480857
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 126 additions and 3 deletions

View File

@ -19,6 +19,19 @@ namespace BTCPayServer.Client
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet"), token);
return await HandleResponse<OnChainWalletOverviewData>(response);
}
public virtual async Task<OnChainWalletFeeRateData> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null,
CancellationToken token = default)
{
Dictionary<string, object> queryParams = new Dictionary<string, object>();
if (blockTarget != null)
{
queryParams.Add("blockTarget",blockTarget);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/feeRate", queryParams), token);
return await HandleResponse<OnChainWalletFeeRateData>(response);
}
public virtual async Task<OnChainWalletAddressData> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false,
CancellationToken token = default)

View File

@ -0,0 +1,12 @@
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class OnChainWalletFeeRateData
{
[JsonConverter(typeof(FeeRateJsonConverter))]
public FeeRate FeeRate { get; set; }
}
}

View File

@ -5,7 +5,6 @@ namespace BTCPayServer.Client.Models
{
public class OnChainWalletOverviewData
{
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Balance { get; set; }
}

View File

@ -1435,6 +1435,10 @@ namespace BTCPayServer.Tests
var overview = await client.ShowOnChainWalletOverview(walletId.StoreId, walletId.CryptoCode );
Assert.Equal(0m, overview.Balance);
var fee = await client.GetOnChainFeeRate(walletId.StoreId, walletId.CryptoCode );
Assert.NotNull( fee.FeeRate);
await AssertHttpError(403, async () =>
{
await viewOnlyClient.GetOnChainWalletReceiveAddress(walletId.StoreId, walletId.CryptoCode );

View File

@ -44,6 +44,7 @@ namespace BTCPayServer.Controllers.GreenField
private readonly DelayedTransactionBroadcaster _delayedTransactionBroadcaster;
private readonly EventAggregator _eventAggregator;
private readonly WalletReceiveService _walletReceiveService;
private readonly IFeeProviderFactory _feeProviderFactory;
public StoreOnChainWalletsController(
IAuthorizationService authorizationService,
@ -57,7 +58,8 @@ namespace BTCPayServer.Controllers.GreenField
PayjoinClient payjoinClient,
DelayedTransactionBroadcaster delayedTransactionBroadcaster,
EventAggregator eventAggregator,
WalletReceiveService walletReceiveService)
WalletReceiveService walletReceiveService,
IFeeProviderFactory feeProviderFactory)
{
_authorizationService = authorizationService;
_btcPayWalletProvider = btcPayWalletProvider;
@ -71,6 +73,7 @@ namespace BTCPayServer.Controllers.GreenField
_delayedTransactionBroadcaster = delayedTransactionBroadcaster;
_eventAggregator = eventAggregator;
_walletReceiveService = walletReceiveService;
_feeProviderFactory = feeProviderFactory;
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
@ -87,6 +90,21 @@ namespace BTCPayServer.Controllers.GreenField
});
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/feerate")]
public async Task<IActionResult> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null)
{
if (IsInvalidWalletRequest(cryptoCode, out BTCPayNetwork network,
out DerivationSchemeSettings derivationScheme, out IActionResult actionResult)) return actionResult;
var feeRateTarget = blockTarget?? Store.GetStoreBlob().RecommendedFeeBlockTarget;
return Ok(new OnChainWalletFeeRateData()
{
FeeRate = await _feeProviderFactory.CreateFeeProvider(network)
.GetFeeRateAsync(feeRateTarget),
});
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address")]
public async Task<IActionResult> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false)
@ -332,7 +350,7 @@ namespace BTCPayServer.Controllers.GreenField
"You are sending your entire balance, you should subtract the fees from a destination", this);
}
var minRelayFee = this._nbXplorerDashboard.Get(network.CryptoCode).Status.BitcoinStatus?.MinRelayTxFee ??
var minRelayFee = _nbXplorerDashboard.Get(network.CryptoCode).Status.BitcoinStatus?.MinRelayTxFee ??
new FeeRate(1.0m);
if (request.FeeRate != null && request.FeeRate < minRelayFee)
{

View File

@ -56,6 +56,72 @@
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet/feeRate": {
"get": {
"tags": [
"Store Wallet (On Chain)"
],
"summary": "Get store on-chain wallet overview",
"parameters": [
{
"name": "storeId",
"in": "path",
"required": true,
"description": "The store to fetch",
"schema": {
"type": "string"
}
},
{
"name": "cryptoCode",
"in": "path",
"required": true,
"description": "The crypto code of the payment method to fetch",
"schema": {
"type": "string"
}
},
{
"name": "blockTarget",
"in": "query",
"required": false,
"description": "The number of blocks away you are willing to target for confirmation. Defaults to the wallet's configured `RecommendedFeeBlockTarget`",
"schema": {
"type": "number",
"minimum": 1
}
}
],
"description": "Get wallet onchain fee rate",
"operationId": "StoreOnChainWallets_GetOnChainFeeRate",
"responses": {
"200": {
"description": "fee rate",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainWalletFeeRateData"
}
}
}
},
"403": {
"description": "If you are authenticated but forbidden to view the specified store"
},
"404": {
"description": "The key is not found for this store/wallet"
}
},
"security": [
{
"API Key": [
"btcpay.store.canmodifystoresettings"
],
"Basic": []
}
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet/address": {
"get": {
"tags": [
@ -449,6 +515,17 @@
}
}
},
"OnChainWalletFeeRateData": {
"type": "object",
"additionalProperties": false,
"properties": {
"feeRate": {
"type": "number",
"format": "decimal",
"description": "The fee rate (sats per byte) based on the wallet's configured recommended block confirmation target"
}
}
},
"OnChainWalletAddressData": {
"type": "object",
"additionalProperties": false,