GreenField: Store OnChain Payment Method (#2157)

* GreenField: Store set payment methods

* add swagger docs

* fix swagger
This commit is contained in:
Andrew Camilleri 2020-12-23 06:00:38 +01:00 committed by GitHub
parent 9dbfe22171
commit 69eaaef963
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
7 changed files with 869 additions and 2 deletions

View file

@ -0,0 +1,74 @@
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<OnChainPaymentMethodData>> GetStoreOnChainPaymentMethods(string storeId,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain"), token);
return await HandleResponse<IEnumerable<OnChainPaymentMethodData>>(response);
}
public virtual async Task<OnChainPaymentMethodData> GetStoreOnChainPaymentMethod(string storeId,
string cryptoCode, CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}"), token);
return await HandleResponse<OnChainPaymentMethodData>(response);
}
public virtual async Task RemoveStoreOnChainPaymentMethod(string storeId,
string cryptoCode, CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}",
method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<OnChainPaymentMethodData> UpdateStoreOnChainPaymentMethod(string storeId,
string cryptoCode, OnChainPaymentMethodData paymentMethod,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}",
bodyPayload: paymentMethod, method: HttpMethod.Put), token);
return await HandleResponse<OnChainPaymentMethodData>(response);
}
public virtual async Task<OnChainPaymentMethodPreviewResultData>
PreviewProposedStoreOnChainPaymentMethodAddresses(
string storeId, string cryptoCode, OnChainPaymentMethodData paymentMethod, int offset = 0,
int amount = 10,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
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);
return await HandleResponse<OnChainPaymentMethodPreviewResultData>(response);
}
public virtual async Task<OnChainPaymentMethodPreviewResultData> PreviewStoreOnChainPaymentMethodAddresses(
string storeId, string cryptoCode, int offset = 0, int amount = 10,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
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);
}
}
}

View file

@ -0,0 +1,38 @@
namespace BTCPayServer.Client.Models
{
public class OnChainPaymentMethodData
{
/// <summary>
/// Whether the payment method is enabled
/// </summary>
public bool Enabled { get; set; }
/// <summary>
/// Whether the payment method is the default
/// </summary>
public bool Default { get; set; }
/// <summary>
/// Crypto code of the payment method
/// </summary>
public string CryptoCode { get; set; }
/// <summary>
/// The derivation scheme
/// </summary>
public string DerivationScheme { get; set; }
public OnChainPaymentMethodData()
{
}
public OnChainPaymentMethodData(string cryptoCode, string derivationScheme, bool enabled,
bool defaultMethod)
{
Enabled = enabled;
Default = defaultMethod;
CryptoCode = cryptoCode;
DerivationScheme = derivationScheme;
}
}
}

View file

@ -0,0 +1,23 @@
using System.Collections.Generic;
namespace BTCPayServer.Client.Models
{
public class OnChainPaymentMethodPreviewResultData
{
/// <summary>
/// a list of addresses generated by the derivation scheme
/// </summary>
public IList<OnChainPaymentMethodPreviewResultAddressItem> Addresses { get; set; } =
new List<OnChainPaymentMethodPreviewResultAddressItem>();
public class OnChainPaymentMethodPreviewResultAddressItem
{
/// <summary>
/// The key path relative to the account key path.
/// </summary>
public string KeyPath { get; set; }
//The address generated at the key path
public string Address { get; set; }
}
}
}

View file

@ -1210,6 +1210,59 @@ namespace BTCPayServer.Tests
Assert.Empty(await viewOnlyClient.GetNotifications(false)); Assert.Empty(await viewOnlyClient.GetNotifications(false));
} }
[Fact(Timeout = TestTimeout)]
[Trait("Integration", "Integration")]
public async Task OnChainPaymentMethodAPITests()
{
using var tester = ServerTester.Create();
await tester.StartAsync();
var user = tester.NewAccount();
await user.GrantAccessAsync(true);
var client = await user.CreateClient(Policies.CanModifyStoreSettings);
var viewOnlyClient = await user.CreateClient(Policies.CanViewStoreSettings);
var store = await client.CreateStore(new CreateStoreRequest() {Name = "test store"});
Assert.Empty(await client.GetStoreOnChainPaymentMethods(store.Id));
await AssertHttpError(403, async () =>
{
await viewOnlyClient.UpdateStoreOnChainPaymentMethod(store.Id, "BTC", new OnChainPaymentMethodData() { });
});
var xpriv = new Mnemonic("all all all all all all all all all all all all").DeriveExtKey()
.Derive(KeyPath.Parse("m/84'/0'/0'"));
var xpub = xpriv.Neuter().ToString(Network.RegTest);
var firstAddress = xpriv.Derive(KeyPath.Parse("0/0")).Neuter().GetPublicKey().GetAddress(ScriptPubKeyType.Segwit, Network.RegTest).ToString();
await AssertHttpError(404, async () =>
{
await client.PreviewStoreOnChainPaymentMethodAddresses(store.Id, "BTC");
});
Assert.Equal(firstAddress, (await viewOnlyClient.PreviewProposedStoreOnChainPaymentMethodAddresses(store.Id, "BTC",
new OnChainPaymentMethodData() {Default = true, Enabled = true, DerivationScheme = xpub})).Addresses.First().Address);
var method = await client.UpdateStoreOnChainPaymentMethod(store.Id, "BTC",
new OnChainPaymentMethodData() {Default = true, Enabled = true, DerivationScheme = xpub});
Assert.Equal(xpub,method.DerivationScheme);
method = await client.GetStoreOnChainPaymentMethod(store.Id, "BTC");
Assert.Equal(xpub,method.DerivationScheme);
Assert.Equal(firstAddress, (await viewOnlyClient.PreviewStoreOnChainPaymentMethodAddresses(store.Id, "BTC")).Addresses.First().Address);
await AssertHttpError(403, async () =>
{
await viewOnlyClient.RemoveStoreOnChainPaymentMethod(store.Id, "BTC");
});
await client.RemoveStoreOnChainPaymentMethod(store.Id, "BTC");
await AssertHttpError(404, async () =>
{
await client.GetStoreOnChainPaymentMethod(store.Id, "BTC");
});
}
[Fact(Timeout = TestTimeout)] [Fact(Timeout = TestTimeout)]

View file

@ -0,0 +1,235 @@
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Client;
using BTCPayServer.Client.Models;
using BTCPayServer.Data;
using BTCPayServer.Payments;
using BTCPayServer.Services.Stores;
using BTCPayServer.Services.Wallets;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using NBXplorer.DerivationStrategy;
using StoreData = BTCPayServer.Data.StoreData;
namespace BTCPayServer.Controllers.GreenField
{
[ApiController]
[Authorize(AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
public class StoreOnChainPaymentMethodsController : ControllerBase
{
private StoreData Store => HttpContext.GetStoreData();
private readonly StoreRepository _storeRepository;
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
private readonly BTCPayWalletProvider _walletProvider;
public StoreOnChainPaymentMethodsController(
StoreRepository storeRepository,
BTCPayNetworkProvider btcPayNetworkProvider,
BTCPayWalletProvider walletProvider)
{
_storeRepository = storeRepository;
_btcPayNetworkProvider = btcPayNetworkProvider;
_walletProvider = walletProvider;
}
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/" + BitcoinPaymentType.GreenFieldApiId)]
public ActionResult<IEnumerable<OnChainPaymentMethodData>> GetOnChainPaymentMethods(
[FromQuery] bool enabledOnly = false)
{
var blob = Store.GetStoreBlob();
var excludedPaymentMethods = blob.GetExcludedPaymentMethods();
var defaultPaymentId = Store.GetDefaultPaymentId(_btcPayNetworkProvider);
return Ok(Store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
.Where((method) => method.PaymentId.PaymentType == PaymentTypes.BTCLike)
.OfType<DerivationSchemeSettings>()
.Select(strategy =>
new OnChainPaymentMethodData(strategy.PaymentId.CryptoCode,
strategy.AccountDerivation.ToString(), !excludedPaymentMethods.Match(strategy.PaymentId),
defaultPaymentId == strategy.PaymentId))
.Where((result) => !enabledOnly || result.Enabled)
.ToList()
);
}
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/" + BitcoinPaymentType.GreenFieldApiId + "/{cryptoCode}")]
public ActionResult<OnChainPaymentMethodData> GetOnChainPaymentMethod(string cryptoCode)
{
if (!GetCryptoCodeWallet(cryptoCode, out BTCPayNetwork _, out BTCPayWallet _))
{
return NotFound();
}
var method = GetExistingBtcLikePaymentMethod(cryptoCode);
if (method is null)
{
return NotFound();
}
return Ok(method);
}
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpGet("~/api/v1/stores/{storeId}/payment-methods/" + BitcoinPaymentType.GreenFieldApiId +
"/{cryptoCode}/preview")]
public ActionResult<OnChainPaymentMethodPreviewResultData> GetOnChainPaymentMethodPreview(
string cryptoCode,
int offset = 0, int amount = 10)
{
if (!GetCryptoCodeWallet(cryptoCode, out var network, out BTCPayWallet _))
{
return NotFound();
}
var paymentMethod = GetExistingBtcLikePaymentMethod(cryptoCode);
if (string.IsNullOrEmpty(paymentMethod?.DerivationScheme))
{
return NotFound();
}
var strategy = DerivationSchemeSettings.Parse(paymentMethod.DerivationScheme, network);
var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit);
var line = strategy.AccountDerivation.GetLineFor(deposit);
var result = new OnChainPaymentMethodPreviewResultData();
for (var i = offset; i < amount; i++)
{
var address = line.Derive((uint)i);
result.Addresses.Add(
new OnChainPaymentMethodPreviewResultData.OnChainPaymentMethodPreviewResultAddressItem()
{
KeyPath = deposit.GetKeyPath((uint)i).ToString(),
Address = address.ScriptPubKey.GetDestinationAddress(strategy.Network.NBitcoinNetwork)
.ToString()
});
}
return Ok(result);
}
[Authorize(Policy = Policies.CanViewStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPost("~/api/v1/stores/{storeId}/payment-methods/" + BitcoinPaymentType.GreenFieldApiId +
"/{cryptoCode}/preview")]
public IActionResult GetProposedOnChainPaymentMethodPreview(string cryptoCode,
[FromBody] OnChainPaymentMethodData paymentMethodData,
int offset = 0, int amount = 10)
{
if (!GetCryptoCodeWallet(cryptoCode, out var network, out BTCPayWallet _))
{
return NotFound();
}
try
{
var strategy = DerivationSchemeSettings.Parse(paymentMethodData.DerivationScheme, network);
var deposit = new NBXplorer.KeyPathTemplates(null).GetKeyPathTemplate(DerivationFeature.Deposit);
var line = strategy.AccountDerivation.GetLineFor(deposit);
var result = new OnChainPaymentMethodPreviewResultData();
for (var i = offset; i < amount; i++)
{
var derivation = line.Derive((uint)i);
result.Addresses.Add(
new
OnChainPaymentMethodPreviewResultData.
OnChainPaymentMethodPreviewResultAddressItem()
{
KeyPath = deposit.GetKeyPath((uint)i).ToString(),
Address = strategy.Network.NBXplorerNetwork.CreateAddress(strategy.AccountDerivation,
line.KeyPathTemplate.GetKeyPath((uint)i),
derivation.ScriptPubKey).ToString()
});
}
return Ok(result);
}
catch
{
ModelState.AddModelError(nameof(OnChainPaymentMethodData.DerivationScheme),
"Invalid Derivation Scheme");
return this.CreateValidationError(ModelState);
}
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpDelete("~/api/v1/stores/{storeId}/payment-methods/" + BitcoinPaymentType.GreenFieldApiId +
"/{cryptoCode}")]
public async Task<ActionResult<OnChainPaymentMethodPreviewResultData>> RemoveOnChainPaymentMethod(
string cryptoCode,
int offset = 0, int amount = 10)
{
if (!GetCryptoCodeWallet(cryptoCode, out BTCPayNetwork _, out BTCPayWallet _))
{
return NotFound();
}
var id = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike);
var store = Store;
store.SetSupportedPaymentMethod(id, null);
await _storeRepository.UpdateStore(store);
return Ok();
}
[Authorize(Policy = Policies.CanModifyStoreSettings, AuthenticationSchemes = AuthenticationSchemes.Greenfield)]
[HttpPut("~/api/v1/stores/{storeId}/payment-methods/" + BitcoinPaymentType.GreenFieldApiId + "/{cryptoCode}")]
public async Task<IActionResult> UpdateOnChainPaymentMethod(string cryptoCode,
[FromBody] OnChainPaymentMethodData paymentMethodData)
{
var id = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike);
if (!GetCryptoCodeWallet(cryptoCode, out var network, out var wallet))
{
return NotFound();
}
try
{
var store = Store;
var storeBlob = store.GetStoreBlob();
var strategy = DerivationSchemeSettings.Parse(paymentMethodData.DerivationScheme, network);
if (strategy != null)
await wallet.TrackAsync(strategy.AccountDerivation);
store.SetSupportedPaymentMethod(id, strategy);
storeBlob.SetExcluded(id, !paymentMethodData.Enabled);
store.SetStoreBlob(storeBlob);
await _storeRepository.UpdateStore(store);
return Ok(GetExistingBtcLikePaymentMethod(cryptoCode, store));
}
catch
{
ModelState.AddModelError(nameof(OnChainPaymentMethodData.DerivationScheme),
"Invalid Derivation Scheme");
return this.CreateValidationError(ModelState);
}
}
private bool GetCryptoCodeWallet(string cryptoCode, out BTCPayNetwork network, out BTCPayWallet wallet)
{
network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(cryptoCode);
wallet = network != null ? _walletProvider.GetWallet(network) : null;
return wallet != null;
}
private OnChainPaymentMethodData GetExistingBtcLikePaymentMethod(string cryptoCode, StoreData store = null)
{
store ??= Store;
var storeBlob = store.GetStoreBlob();
var defaultPaymentMethod = store.GetDefaultPaymentId(_btcPayNetworkProvider);
var id = new PaymentMethodId(cryptoCode, PaymentTypes.BTCLike);
var paymentMethod = store
.GetSupportedPaymentMethods(_btcPayNetworkProvider)
.OfType<DerivationSchemeSettings>()
.FirstOrDefault(method => method.PaymentId == id);
var excluded = storeBlob.IsExcluded(id);
return paymentMethod == null
? null
: new OnChainPaymentMethodData(paymentMethod.PaymentId.CryptoCode,
paymentMethod.AccountDerivation.ToString(), !excluded,
defaultPaymentMethod == paymentMethod.PaymentId);
}
}
}

View file

@ -18,8 +18,8 @@ namespace BTCPayServer.Payments
public override string ToPrettyString() => "On-Chain"; public override string ToPrettyString() => "On-Chain";
public override string GetId() => "BTCLike"; public override string GetId() => "BTCLike";
public override string GetBadge() => "🔗"; public override string GetBadge() => "🔗";
public override string ToStringNormalized() => "OnChain"; public override string ToStringNormalized() => GreenFieldApiId;
public const string GreenFieldApiId = "OnChain";
public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str) public override CryptoPaymentData DeserializePaymentData(BTCPayNetworkBase network, string str)
{ {
return ((BTCPayNetwork)network)?.ToObject<BitcoinLikePaymentData>(str); return ((BTCPayNetwork)network)?.ToObject<BitcoinLikePaymentData>(str);

View file

@ -0,0 +1,444 @@
{
"paths": {
"/api/v1/stores/{storeId}/payment-methods/OnChain": {
"get": {
"tags": [
"Store Payment Methods (On Chain)"
],
"summary": "Get store on-chain payment methods",
"description": "View information about the stores' configured on-chain payment methods",
"operationId": "StoreOnChainPaymentMethods_GetOnChainPaymentMethods",
"responses": {
"200": {
"description": "list of payment methods",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainPaymentMethodDataList"
}
}
}
}
},
"security": [
{
"API Key": [
"btcpay.store.canviewstoresettings"
],
"Basic": []
}
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}": {
"get": {
"tags": [
"Store Payment Methods (On Chain)"
],
"summary": "Get store on-chain payment method",
"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"
}
}
],
"description": "View information about the specified payment method",
"operationId": "StoreOnChainPaymentMethods_GetOnChainPaymentMethod",
"responses": {
"200": {
"description": "specified payment method",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainPaymentMethodData"
}
}
}
},
"403": {
"description": "If you are authenticated but forbidden to view the specified store"
},
"404": {
"description": "The key is not found for this store/payment method"
}
},
"security": [
{
"API Key": [
"btcpay.store.canviewstoresettings"
],
"Basic": []
}
]
},
"put": {
"tags": [
"Store Payment Methods (On Chain)"
],
"summary": "Update store on-chain payment method",
"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 update",
"schema": {
"type": "string"
}
}
],
"description": "Update the specified store's payment method",
"requestBody": {
"x-name": "request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainPaymentMethodData"
}
}
},
"required": true,
"x-position": 1
},
"operationId": "StoreOnChainPaymentMethods_UpdateOnChainPaymentMethod",
"responses": {
"200": {
"description": "updated specified payment method",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainPaymentMethodData"
}
}
}
},
"400": {
"description": "A list of errors that occurred when updating the store payment method",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
}
}
},
"403": {
"description": "If you are authenticated but forbidden to update the specified store"
},
"404": {
"description": "The key is not found for this store"
}
},
"security": [
{
"API Key": [
"btcpay.store.canmodifystoresettings"
],
"Basic": []
}
]
},
"delete": {
"tags": [
"Store Payment Methods (On Chain)"
],
"summary": "Remove store on-chain payment method",
"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 update",
"schema": {
"type": "string"
}
}
],
"description": "Removes the specified store payment method.",
"responses": {
"200": {
"description": "The payment method has been removed"
},
"400": {
"description": "A list of errors that occurred when removing the payment method",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/ValidationProblemDetails"
}
}
}
},
"403": {
"description": "If you are authenticated but forbidden to remove the specified payment method"
},
"404": {
"description": "The key is not found for this store/payment-method"
}
},
"security": [
{
"API Key": [
"btcpay.store.canmodifystoresettings"
],
"Basic": []
}
]
}
},
"/api/v1/stores/{storeId}/payment-methods/OnChain/{cryptoCode}/preview": {
"get": {
"tags": [
"Store Payment Methods (On Chain)"
],
"summary": "Preview store on-chain payment method addresses",
"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": "offset",
"in": "query",
"required": false,
"description": "From which index to fetch the addresses",
"schema": {
"type": "number"
}
},
{
"name": "amount",
"in": "query",
"required": false,
"description": "Number of addresses to preview",
"schema": {
"type": "number"
}
}
],
"description": "View addresses of the current payment method of the store",
"operationId": "StoreOnChainPaymentMethods_GetOnChainPaymentMethodPreview",
"responses": {
"200": {
"description": "specified payment method addresses",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainPaymentMethodPreviewResultData"
}
}
}
},
"403": {
"description": "If you are authenticated but forbidden to view the specified store"
},
"404": {
"description": "The key is not found for this store/payment method"
}
},
"security": [
{
"API Key": [
"btcpay.store.canviewstoresettings"
],
"Basic": []
}
]
},
"post": {
"tags": [
"Store Payment Methods (On Chain)"
],
"summary": "Preview proposed store on-chain payment method addresses",
"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": "offset",
"in": "query",
"required": false,
"description": "From which index to fetch the addresses",
"schema": {
"type": "number"
}
},
{
"name": "amount",
"in": "query",
"required": false,
"description": "Number of addresses to preview",
"schema": {
"type": "number"
}
}
],
"description": "View addresses of a proposed payment method of the store",
"operationId": "StoreOnChainPaymentMethods_GetOnChainPaymentMethodPreview",
"requestBody": {
"x-name": "request",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainPaymentMethodData"
}
}
},
"required": true,
"x-position": 1
},
"responses": {
"200": {
"description": "specified payment method addresses",
"content": {
"application/json": {
"schema": {
"$ref": "#/components/schemas/OnChainPaymentMethodPreviewResultData"
}
}
}
},
"403": {
"description": "If you are authenticated but forbidden to view the specified store"
},
"404": {
"description": "The key is not found for this store"
}
},
"security": [
{
"API Key": [
"btcpay.store.canviewstoresettings"
],
"Basic": []
}
]
}
}
},
"components": {
"schemas": {
"OnChainPaymentMethodDataList": {
"type": "array",
"items": {
"$ref": "#/components/schemas/OnChainPaymentMethodData"
}
},
"OnChainPaymentMethodData": {
"type": "object",
"additionalProperties": false,
"properties": {
"enabled": {
"type": "boolean",
"description": "Whether the payment method is enabled"
},
"default": {
"type": "boolean",
"description": "Whether the payment method is the default"
},
"cryptoCode": {
"type": "string",
"description": "Crypto code of the payment method"
},
"derivationScheme": {
"type": "string",
"description": "The derivation scheme"
}
}
},
"OnChainPaymentMethodPreviewResultData": {
"type": "object",
"additionalProperties": false,
"properties": {
"addresses": {
"type": "array",
"description": "a list of addresses generated by the derivation scheme",
"items": {
"$ref": "#/components/schemas/OnChainPaymentMethodPreviewResultAddressItem"
}
}
}
},
"OnChainPaymentMethodPreviewResultAddressItem": {
"type": "object",
"additionalProperties": false,
"properties": {
"keyPath": {
"type": "string",
"description": "The key path relative to the account key path."
},
"address": {
"type": "string",
"description": "The address generated at the key path"
}
}
}
}
},
"tags": [
{
"name": "Store Payment Methods (On Chain)"
}
]
}