Add transaction info PATCH endpoint (#3561)

* Add transaction info patch endpoint

* Add "#nullable enable" to LabelFactory

* Add Swagger docs

* Update OnChain to onchain

* update feeRate to feerate

* Add test

* replace "Onchain" with "onchain"
This commit is contained in:
Umar Bolatov
2022-04-13 21:17:22 -07:00
committed by GitHub
parent fb90ff2fbb
commit 23d383be67
9 changed files with 320 additions and 74 deletions

View File

@@ -20,7 +20,7 @@ namespace BTCPayServer.Client
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain",
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain",
query), token);
return await HandleResponse<IEnumerable<OnChainPaymentMethodData>>(response);
}
@@ -30,7 +30,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}"), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}"), token);
return await HandleResponse<OnChainPaymentMethodData>(response);
}
@@ -39,7 +39,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}",
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}",
method: HttpMethod.Delete), token);
await HandleResponse(response);
}
@@ -49,7 +49,7 @@ namespace BTCPayServer.Client
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}",
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}",
bodyPayload: paymentMethod, method: HttpMethod.Put), token);
return await HandleResponse<OnChainPaymentMethodData>(response);
}
@@ -61,7 +61,7 @@ namespace BTCPayServer.Client
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview",
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/preview",
bodyPayload: paymentMethod,
queryPayload: new Dictionary<string, object>() { { "offset", offset }, { "amount", amount } },
method: HttpMethod.Post), token);
@@ -73,7 +73,7 @@ namespace BTCPayServer.Client
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/preview",
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/preview",
queryPayload: new Dictionary<string, object>() { { "offset", offset }, { "amount", amount } },
method: HttpMethod.Get), token);
return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response);
@@ -84,7 +84,7 @@ namespace BTCPayServer.Client
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/generate",
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/generate",
bodyPayload: request,
method: HttpMethod.Post), token);
return await HandleResponse<OnChainPaymentMethodDataWithSensitiveData>(response);

View File

@@ -16,7 +16,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet"), token);
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,
@@ -29,7 +29,7 @@ namespace BTCPayServer.Client
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/feeRate", queryParams), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/feeRate", queryParams), token);
return await HandleResponse<OnChainWalletFeeRateData>(response);
}
@@ -38,7 +38,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address", new Dictionary<string, object>()
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address", new Dictionary<string, object>()
{
{"forceGenerate", forceGenerate}
}), token);
@@ -50,7 +50,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address", method: HttpMethod.Delete), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address", method: HttpMethod.Delete), token);
await HandleResponse(response);
}
@@ -65,7 +65,7 @@ namespace BTCPayServer.Client
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", query), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions", query), token);
return await HandleResponse<IEnumerable<OnChainWalletTransactionData>>(response);
}
@@ -75,7 +75,18 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions/{transactionId}"), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions/{transactionId}"), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
public virtual async Task<OnChainWalletTransactionData> PatchOnChainWalletTransaction(
string storeId, string cryptoCode, string transactionId,
PatchOnChainTransactionRequest request,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions/{transactionId}", queryPayload: null, bodyPayload: request, HttpMethod.Patch), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
@@ -85,7 +96,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/utxos"), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/utxos"), token);
return await HandleResponse<IEnumerable<OnChainWalletUTXOData>>(response);
}
@@ -100,7 +111,7 @@ namespace BTCPayServer.Client
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
@@ -115,7 +126,7 @@ namespace BTCPayServer.Client
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
return Transaction.Parse(await HandleResponse<string>(response), network);
}
}

View File

@@ -0,0 +1,12 @@
#nullable enable
using System.Collections.Generic;
namespace BTCPayServer.Client.Models
{
public class PatchOnChainTransactionRequest
{
public string? Comment { get; set; } = null;
public List<string>? Labels { get; set; } = null;
}
}

View File

@@ -1703,7 +1703,7 @@ namespace BTCPayServer.Tests
Assert.Equal(firstAddress, (await viewOnlyClient.PreviewProposedStoreOnChainPaymentMethodAddresses(store.Id, "BTC",
new UpdateOnChainPaymentMethodRequest() { Enabled = true, DerivationScheme = xpub })).Addresses.First().Address);
await AssertValidationError(new[] { "accountKeyPath" }, () => viewOnlyClient.SendHttpRequest<GreenfieldValidationError[]>(path: $"api/v1/stores/{store.Id}/payment-methods/Onchain/BTC/preview", method: HttpMethod.Post,
await AssertValidationError(new[] { "accountKeyPath" }, () => viewOnlyClient.SendHttpRequest<GreenfieldValidationError[]>(path: $"api/v1/stores/{store.Id}/payment-methods/onchain/BTC/preview", method: HttpMethod.Post,
bodyPayload: JObject.Parse("{\"accountKeyPath\": \"0/1\"}")));
var method = await client.UpdateStoreOnChainPaymentMethod(store.Id, "BTC",
@@ -2126,7 +2126,30 @@ namespace BTCPayServer.Tests
{
await viewOnlyClient.GetOnChainWalletTransaction(walletId.StoreId, walletId.CryptoCode, txdata.TransactionHash.ToString());
});
await client.GetOnChainWalletTransaction(walletId.StoreId, walletId.CryptoCode, txdata.TransactionHash.ToString());
var transaction = await client.GetOnChainWalletTransaction(walletId.StoreId, walletId.CryptoCode, txdata.TransactionHash.ToString());
Assert.Equal(transaction.TransactionHash, txdata.TransactionHash);
Assert.Equal(String.Empty, transaction.Comment);
Assert.Equal(new Dictionary<string, LabelData>(), transaction.Labels);
// transaction patch tests
var patchedTransaction = await client.PatchOnChainWalletTransaction(
walletId.StoreId, walletId.CryptoCode, txdata.TransactionHash.ToString(),
new PatchOnChainTransactionRequest() {
Comment = "test comment",
Labels = new List<string>
{
"test label"
}
});
Assert.Equal("test comment", patchedTransaction.Comment);
Assert.Equal(
new Dictionary<string, LabelData>()
{
{ "test label", new LabelData(){ Type = "raw", Text = "test label" } }
}.ToJson(),
patchedTransaction.Labels.ToJson()
);
await AssertHttpError(403, async () =>
{

View File

@@ -19,6 +19,7 @@ using BTCPayServer.Payments.PayJoin;
using BTCPayServer.Payments.PayJoin.Sender;
using BTCPayServer.Services;
using BTCPayServer.Services.Wallets;
using BTCPayServer.Services.Labels;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.Mvc;
@@ -50,6 +51,7 @@ namespace BTCPayServer.Controllers.Greenfield
private readonly EventAggregator _eventAggregator;
private readonly WalletReceiveService _walletReceiveService;
private readonly IFeeProviderFactory _feeProviderFactory;
private readonly LabelFactory _labelFactory;
public GreenfieldStoreOnChainWalletsController(
IAuthorizationService authorizationService,
@@ -64,7 +66,9 @@ namespace BTCPayServer.Controllers.Greenfield
DelayedTransactionBroadcaster delayedTransactionBroadcaster,
EventAggregator eventAggregator,
WalletReceiveService walletReceiveService,
IFeeProviderFactory feeProviderFactory)
IFeeProviderFactory feeProviderFactory,
LabelFactory labelFactory
)
{
_authorizationService = authorizationService;
_btcPayWalletProvider = btcPayWalletProvider;
@@ -79,6 +83,7 @@ namespace BTCPayServer.Controllers.Greenfield
_eventAggregator = eventAggregator;
_walletReceiveService = walletReceiveService;
_feeProviderFactory = feeProviderFactory;
_labelFactory = labelFactory;
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
@@ -229,6 +234,65 @@ namespace BTCPayServer.Controllers.Greenfield
return Ok(ToModel(walletTransactionsInfoAsync, tx, wallet));
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPatch("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions/{transactionId}")]
public async Task<IActionResult> PatchOnChainWalletTransaction(
string storeId,
string cryptoCode,
string transactionId,
[FromBody] PatchOnChainTransactionRequest request
)
{
if (IsInvalidWalletRequest(cryptoCode, out var network,
out var derivationScheme, out var actionResult))
return actionResult;
var wallet = _btcPayWalletProvider.GetWallet(network);
var tx = await wallet.FetchTransaction(derivationScheme.AccountDerivation, uint256.Parse(transactionId));
if (tx is null)
{
return this.CreateAPIError(404, "transaction-not-found", "The transaction was not found.");
}
var walletId = new WalletId(storeId, cryptoCode);
var walletTransactionsInfoAsync = _walletRepository.GetWalletTransactionsInfo(walletId);
if (!(await walletTransactionsInfoAsync).TryGetValue(transactionId, out var walletTransactionInfo))
{
walletTransactionInfo = new WalletTransactionInfo();
}
if (request.Comment != null)
{
walletTransactionInfo.Comment = request.Comment.Trim().Truncate(WalletTransactionDataExtensions.MaxCommentSize);
}
if (request.Labels != null)
{
var walletBlobInfo = await _walletRepository.GetWalletInfo(walletId);
foreach (string label in request.Labels)
{
var rawLabel = await _labelFactory.BuildLabel(
walletBlobInfo,
Request,
walletTransactionInfo,
walletId,
transactionId,
label
);
walletTransactionInfo.Labels.TryAdd(rawLabel.Text, rawLabel);
}
}
await _walletRepository.SetWalletTransactionInfo(walletId, transactionId, walletTransactionInfo);
var walletTransactionsInfo =
(await _walletRepository.GetWalletTransactionsInfo(walletId, new[] { transactionId }))
.Values
.FirstOrDefault();
return Ok(ToModel(walletTransactionsInfo, tx, wallet));
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/utxos")]
public async Task<IActionResult> GetOnChainWalletUTXOs(string storeId, string cryptoCode)

View File

@@ -122,20 +122,6 @@ namespace BTCPayServer.Controllers
_walletHistogramService = walletHistogramService;
}
// Borrowed from https://github.com/ManageIQ/guides/blob/master/labels.md
readonly string[] LabelColorScheme =
{
"#fbca04",
"#0e8a16",
"#ff7619",
"#84b6eb",
"#5319e7",
"#cdcdcd",
"#cc317c",
};
const int MaxLabelSize = 20;
const int MaxCommentSize = 200;
[HttpPost]
[Route("{walletId}")]
public async Task<IActionResult> ModifyTransaction(
@@ -173,33 +159,19 @@ namespace BTCPayServer.Controllers
var walletTransactionsInfo = await walletTransactionsInfoAsync;
if (addlabel != null)
{
addlabel = addlabel.Trim().TrimStart('{').ToLowerInvariant().Replace(',', ' ').Truncate(MaxLabelSize);
var labels = _labelFactory.GetWalletColoredLabels(walletBlobInfo, Request);
if (!walletTransactionsInfo.TryGetValue(transactionId, out var walletTransactionInfo))
{
walletTransactionInfo = new WalletTransactionInfo();
}
if (!labels.Any(l => l.Text.Equals(addlabel, StringComparison.OrdinalIgnoreCase)))
{
List<string> allColors = new List<string>();
allColors.AddRange(LabelColorScheme);
allColors.AddRange(labels.Select(l => l.Color));
var chosenColor =
allColors
.GroupBy(k => k)
.OrderBy(k => k.Count())
.ThenBy(k =>
{
var indexInColorScheme = Array.IndexOf(LabelColorScheme, k.Key);
// Ensures that any label color which may not be in our label color scheme is given the least priority
return indexInColorScheme == -1 ? double.PositiveInfinity : indexInColorScheme;
})
.First().Key;
walletBlobInfo.LabelColors.Add(addlabel, chosenColor);
await WalletRepository.SetWalletInfo(walletId, walletBlobInfo);
}
var rawLabel = new RawLabel(addlabel);
var rawLabel = await _labelFactory.BuildLabel(
walletBlobInfo,
Request,
walletTransactionInfo,
walletId,
transactionId,
addlabel
);
if (walletTransactionInfo.Labels.TryAdd(rawLabel.Text, rawLabel))
{
await WalletRepository.SetWalletTransactionInfo(walletId, transactionId, walletTransactionInfo);
@@ -224,7 +196,7 @@ namespace BTCPayServer.Controllers
}
else if (addcomment != null)
{
addcomment = addcomment.Trim().Truncate(MaxCommentSize);
addcomment = addcomment.Trim().Truncate(WalletTransactionDataExtensions.MaxCommentSize);
if (!walletTransactionsInfo.TryGetValue(transactionId, out var walletTransactionInfo))
{
walletTransactionInfo = new WalletTransactionInfo();

View File

@@ -17,6 +17,8 @@ namespace BTCPayServer.Data
}
public static class WalletTransactionDataExtensions
{
public static int MaxCommentSize = 200;
public static WalletTransactionInfo GetBlobInfo(this WalletTransactionData walletTransactionData)
{
WalletTransactionInfo blobInfo;

View File

@@ -1,23 +1,30 @@
#nullable enable
using System;
using System.Collections.Generic;
using System.Drawing;
using Amazon.Util.Internal.PlatformServices;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Routing;
using Newtonsoft.Json.Linq;
using BTCPayServer.Data;
using BTCPayServer.Client.Models;
using BTCPayServer.Abstractions.Extensions;
namespace BTCPayServer.Services.Labels
{
public class LabelFactory
{
private readonly LinkGenerator _linkGenerator;
private readonly WalletRepository _walletRepository;
public LabelFactory(LinkGenerator linkGenerator)
public LabelFactory(
LinkGenerator linkGenerator,
WalletRepository walletRepository
)
{
_linkGenerator = linkGenerator;
_walletRepository = walletRepository;
}
public IEnumerable<ColoredLabel> ColorizeTransactionLabels(WalletBlobInfo walletBlobInfo, WalletTransactionInfo transactionInfo,
@@ -39,7 +46,7 @@ namespace BTCPayServer.Services.Labels
}
const string DefaultColor = "#000";
private ColoredLabel CreateLabel(LabelData uncoloredLabel, string color, HttpRequest request)
private ColoredLabel CreateLabel(LabelData uncoloredLabel, string? color, HttpRequest request)
{
ArgumentNullException.ThrowIfNull(uncoloredLabel);
color ??= DefaultColor;
@@ -93,6 +100,68 @@ namespace BTCPayServer.Services.Labels
return coloredLabel;
}
// Borrowed from https://github.com/ManageIQ/guides/blob/master/labels.md
readonly string[] LabelColorScheme =
{
"#fbca04",
"#0e8a16",
"#ff7619",
"#84b6eb",
"#5319e7",
"#cdcdcd",
"#cc317c",
};
readonly int MaxLabelSize = 20;
async public Task<RawLabel> BuildLabel(
WalletBlobInfo walletBlobInfo,
HttpRequest request,
WalletTransactionInfo walletTransactionInfo,
WalletId walletId,
string transactionId,
string label
)
{
label = label.Trim().TrimStart('{').ToLowerInvariant().Replace(',', ' ').Truncate(MaxLabelSize);
var labels = GetWalletColoredLabels(walletBlobInfo, request);
if (!labels.Any(l => l.Text.Equals(label, StringComparison.OrdinalIgnoreCase)))
{
var chosenColor = ChooseBackgroundColor(walletBlobInfo, request);
walletBlobInfo.LabelColors.Add(label, chosenColor);
await _walletRepository.SetWalletInfo(walletId, walletBlobInfo);
}
return new RawLabel(label);
}
private string ChooseBackgroundColor(
WalletBlobInfo walletBlobInfo,
HttpRequest request
)
{
var labels = GetWalletColoredLabels(walletBlobInfo, request);
List<string> allColors = new List<string>();
allColors.AddRange(LabelColorScheme);
allColors.AddRange(labels.Select(l => l.Color));
var chosenColor =
allColors
.GroupBy(k => k)
.OrderBy(k => k.Count())
.ThenBy(k =>
{
var indexInColorScheme = Array.IndexOf(LabelColorScheme, k.Key);
// Ensures that any label color which may not be in our label color scheme is given the least priority
return indexInColorScheme == -1 ? double.PositiveInfinity : indexInColorScheme;
})
.First().Key;
return chosenColor;
}
private string TextColor(string bgColor)
{
int nThreshold = 105;

View File

@@ -1,6 +1,6 @@
{
"paths": {
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet": {
"/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet": {
"get": {
"tags": [
"Store Wallet (On Chain)"
@@ -57,7 +57,7 @@
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet/feeRate": {
"/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/feerate": {
"get": {
"tags": [
"Store Wallet (On Chain)"
@@ -124,7 +124,7 @@
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet/address": {
"/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address": {
"get": {
"tags": [
"Store Wallet (On Chain)"
@@ -239,7 +239,7 @@
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet/transactions": {
"/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions": {
"get": {
"tags": [
"Store Wallet (On Chain)"
@@ -405,7 +405,7 @@
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet/transactions/{transactionId}": {
"/api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions/{transactionId}": {
"get": {
"tags": [
"Store Wallet (On Chain)"
@@ -469,9 +469,83 @@
"Basic": []
}
]
},
"patch": {
"tags": [
"Store Wallet (On Chain)"
],
"summary": "Patch store on-chain wallet transaction info",
"parameters": [
{
"name": "storeId",
"in": "path",
"required": true,
"description": "The store to fetch",
"schema": {
"type": "string"
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/wallet/utxos": {
{
"name": "cryptoCode",
"in": "path",
"required": true,
"description": "The crypto code of the wallet to fetch",
"schema": {
"type": "string"
},
"example": "BTC"
},
{
"name": "transactionId",
"in": "path",
"required": true,
"description": "The transaction id to fetch",
"schema": {
"type": "string"
}
}
],
"requestBody": {
"required": true,
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/PatchOnChainTransactionRequest"
}
}
}
},
"description": "Patch store on-chain wallet transaction info",
"operationId": "StoreOnChainWallets_PatchOnChainWalletTransaction",
"responses": {
"200": {
"description": "transaction",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainWalletTransactionData"
}
}
}
},
"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/utxos": {
"get": {
"tags": [
"Store Wallet (On Chain)"
@@ -559,7 +633,7 @@
"type": "object",
"additionalProperties": false,
"properties": {
"feeRate": {
"feerate": {
"type": "number",
"format": "decimal",
"description": "The fee rate (sats per byte) based on the wallet's configured recommended block confirmation target"
@@ -758,7 +832,7 @@
"$ref": "#/components/schemas/CreateOnChainTransactionRequestDestination"
}
},
"feeRate": {
"feerate": {
"type": "number",
"format": "decimal or long (sats/byte)",
"description": "Transaction fee."
@@ -795,6 +869,25 @@
}
}
}
},
"PatchOnChainTransactionRequest": {
"type": "object",
"additionalProperties": false,
"properties": {
"comment": {
"nullable": true,
"type": "string",
"description": "Transaction comment"
},
"labels": {
"nullable": true,
"description": "Transaction labels",
"type": "array",
"items": {
"type": "string"
}
}
}
}
}
},