Renaming various properties in the Payouts API (#6246)

* Rename Payouts Currency/OriginalCurrency

* Rename Payout Processor PayoutMethodIds

* Rename paymentMethods to payoutMethodIds

* Rename payoutMethodIds to payoutMethods
This commit is contained in:
Nicolas Dorier 2024-09-26 11:25:45 +09:00 committed by GitHub
parent 90635ffc4e
commit 363b60385b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 85 additions and 67 deletions

View file

@ -19,7 +19,7 @@ namespace BTCPayServer.Client.Models
public DateTimeOffset? ExpiresAt { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? StartsAt { get; set; }
public string[] PaymentMethods { get; set; }
public string[] PayoutMethods { get; set; }
public bool AutoApproveClaims { get; set; }
}
}

View file

@ -22,11 +22,12 @@ namespace BTCPayServer.Client.Models
public string PullPaymentId { get; set; }
public string Destination { get; set; }
public string PayoutMethodId { get; set; }
public string CryptoCode { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public decimal OriginalAmount { get; set; }
public string OriginalCurrency { get; set; }
public string PayoutCurrency { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? PaymentMethodAmount { get; set; }
public decimal? PayoutAmount { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public PayoutState State { get; set; }
public int Revision { get; set; }

View file

@ -4,6 +4,6 @@ namespace BTCPayServer.Client.Models
{
public string Name { get; set; }
public string FriendlyName { get; set; }
public string[] PaymentMethods { get; set; }
public string[] PayoutMethods { get; set; }
}
}

View file

@ -1104,7 +1104,7 @@ namespace BTCPayServer.Tests
Description = "Test description",
Amount = 12.3m,
Currency = "BTC",
PaymentMethods = new[] { "BTC" }
PayoutMethods = new[] { "BTC" }
});
void VerifyResult()
@ -1135,7 +1135,7 @@ namespace BTCPayServer.Tests
Name = "Test 2",
Amount = 12.3m,
Currency = "BTC",
PaymentMethods = new[] { "BTC" },
PayoutMethods = new[] { "BTC" },
BOLT11Expiration = TimeSpan.FromDays(31.0)
});
Assert.Equal(TimeSpan.FromDays(31.0), test2.BOLT11Expiration);
@ -1182,13 +1182,13 @@ namespace BTCPayServer.Tests
payouts = await unauthenticated.GetPayouts(pps[0].Id);
var payout2 = Assert.Single(payouts);
Assert.Equal(payout.Amount, payout2.Amount);
Assert.Equal(payout.OriginalAmount, payout2.OriginalAmount);
Assert.Equal(payout.Id, payout2.Id);
Assert.Equal(destination, payout2.Destination);
Assert.Equal(PayoutState.AwaitingApproval, payout.State);
Assert.Equal("BTC-CHAIN", payout2.PayoutMethodId);
Assert.Equal("BTC", payout2.CryptoCode);
Assert.Null(payout.PaymentMethodAmount);
Assert.Equal("BTC", payout2.PayoutCurrency);
Assert.Null(payout.PayoutAmount);
TestLogs.LogInformation("Can't overdraft");
@ -1230,7 +1230,7 @@ namespace BTCPayServer.Tests
Amount = 12.3m,
StartsAt = start,
Currency = "BTC",
PaymentMethods = new[] { "BTC" }
PayoutMethods = new[] { "BTC" }
});
Assert.Equal(start, inFuture.StartsAt);
Assert.Null(inFuture.ExpiresAt);
@ -1248,7 +1248,7 @@ namespace BTCPayServer.Tests
Amount = 12.3m,
ExpiresAt = expires,
Currency = "BTC",
PaymentMethods = new[] { "BTC" }
PayoutMethods = new[] { "BTC" }
});
await this.AssertAPIError("expired", async () => await unauthenticated.CreatePayout(inPast.Id, new CreatePayoutRequest()
{
@ -1272,7 +1272,7 @@ namespace BTCPayServer.Tests
Name = "Test USD",
Amount = 5000m,
Currency = "USD",
PaymentMethods = new[] { "BTC" }
PayoutMethods = new[] { "BTC" }
});
await this.AssertAPIError("lnurl-not-supported", async () => await unauthenticated.GetPullPaymentLNURL(pp.Id));
@ -1297,8 +1297,8 @@ namespace BTCPayServer.Tests
Revision = payout.Revision
});
Assert.Equal(PayoutState.AwaitingPayment, payout.State);
Assert.NotNull(payout.PaymentMethodAmount);
Assert.Equal(1.0m, payout.PaymentMethodAmount); // 1 BTC == 5000 USD in tests
Assert.NotNull(payout.PayoutAmount);
Assert.Equal(1.0m, payout.PayoutAmount); // 1 BTC == 5000 USD in tests
await this.AssertAPIError("invalid-state", async () => await client.ApprovePayout(storeId, payout.Id, new ApprovePayoutRequest()
{
Revision = payout.Revision
@ -1310,7 +1310,7 @@ namespace BTCPayServer.Tests
Name = "Test 2",
Amount = 12.303228134m,
Currency = "BTC",
PaymentMethods = new[] { "BTC" }
PayoutMethods = new[] { "BTC" }
});
destination = (await tester.ExplorerNode.GetNewAddressAsync()).ToString();
payout = await unauthenticated.CreatePayout(test3.Id, new CreatePayoutRequest()
@ -1320,8 +1320,8 @@ namespace BTCPayServer.Tests
});
payout = await client.ApprovePayout(storeId, payout.Id, new ApprovePayoutRequest());
// The payout should round the value of the payment down to the network of the payment method
Assert.Equal(12.30322814m, payout.PaymentMethodAmount);
Assert.Equal(12.303228134m, payout.Amount);
Assert.Equal(12.30322814m, payout.PayoutAmount);
Assert.Equal(12.303228134m, payout.OriginalAmount);
await client.MarkPayoutPaid(storeId, payout.Id);
payout = (await client.GetPayouts(payout.PullPaymentId)).First(data => data.Id == payout.Id);
@ -1334,7 +1334,7 @@ namespace BTCPayServer.Tests
Name = "Test 3",
Amount = 12.303228134m,
Currency = "BTC",
PaymentMethods = new[] { "BTC", "BTC-LightningNetwork", "BTC_LightningLike" }
PayoutMethods = new[] { "BTC", "BTC-LightningNetwork", "BTC_LightningLike" }
});
var lnrURLs = await unauthenticated.GetPullPaymentLNURL(test4.Id);
Assert.IsType<string>(lnrURLs.LNURLBech32);
@ -1409,7 +1409,7 @@ namespace BTCPayServer.Tests
Name = "Test SATS",
Amount = 21000,
Currency = "SATS",
PaymentMethods = new[] { "BTC", "BTC-LightningNetwork", "BTC_LightningLike" }
PayoutMethods = new[] { "BTC", "BTC-LightningNetwork", "BTC_LightningLike" }
});
lnrURLs = await unauthenticated.GetPullPaymentLNURL(testSats.Id);
Assert.IsType<string>(lnrURLs.LNURLBech32);
@ -1427,7 +1427,7 @@ namespace BTCPayServer.Tests
Amount = 100,
Currency = "USD",
Name = "pull payment",
PaymentMethods = new[] { "BTC" },
PayoutMethods = new[] { "BTC" },
AutoApproveClaims = true
});
});
@ -1447,7 +1447,7 @@ namespace BTCPayServer.Tests
Amount = 100,
Currency = "USD",
Name = "pull payment",
PaymentMethods = new[] { "BTC" },
PayoutMethods = new[] { "BTC" },
AutoApproveClaims = true
});
@ -4188,7 +4188,7 @@ namespace BTCPayServer.Tests
PayoutMethodId = "BTC_LightningNetwork",
Destination = customerInvoice.BOLT11
});
Assert.Equal(payout2.Amount, new Money(100, MoneyUnit.Satoshi).ToDecimal(MoneyUnit.BTC));
Assert.Equal(payout2.OriginalAmount, new Money(100, MoneyUnit.Satoshi).ToDecimal(MoneyUnit.BTC));
}
[Fact(Timeout = 60 * 2 * 1000)]
@ -4232,7 +4232,7 @@ namespace BTCPayServer.Tests
Amount = 100,
Currency = "USD",
Name = "pull payment",
PaymentMethods = new[] { "BTC" }
PayoutMethods = new[] { "BTC" }
});
var notapprovedPayoutWithPullPayment = await adminClient.CreatePayout(admin.StoreId, new CreatePayoutThroughStoreRequest()
@ -4258,7 +4258,7 @@ namespace BTCPayServer.Tests
Assert.Equal(3, payouts.Length);
Assert.Empty(payouts.Where(data => data.State == PayoutState.AwaitingApproval));
Assert.Empty(payouts.Where(data => data.PaymentMethodAmount is null));
Assert.Empty(payouts.Where(data => data.PayoutAmount is null));
Assert.Empty(await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC"));
@ -4271,12 +4271,12 @@ namespace BTCPayServer.Tests
Assert.Equal(3600, Assert.Single(await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC")).IntervalSeconds.TotalSeconds);
var tpGen = Assert.Single(await adminClient.GetPayoutProcessors(admin.StoreId));
Assert.Equal("BTC-CHAIN", Assert.Single(tpGen.PaymentMethods));
Assert.Equal("BTC-CHAIN", Assert.Single(tpGen.PayoutMethods));
//still too poor to process any payouts
Assert.Empty(await adminClient.ShowOnChainWalletTransactions(admin.StoreId, "BTC"));
await adminClient.RemovePayoutProcessor(admin.StoreId, tpGen.Name, tpGen.PaymentMethods.First());
await adminClient.RemovePayoutProcessor(admin.StoreId, tpGen.Name, tpGen.PayoutMethods.First());
Assert.Empty(await adminClient.GetStoreOnChainAutomatedPayoutProcessors(admin.StoreId, "BTC"));
Assert.Empty(await adminClient.GetPayoutProcessors(admin.StoreId));

View file

@ -1463,7 +1463,7 @@ namespace BTCPayServer.Tests
{
Currency = "BTC",
Amount = 1.0m,
PaymentMethods = [ "BTC-CHAIN" ]
PayoutMethods = [ "BTC-CHAIN" ]
});
var controller = user.GetController<UIInvoiceController>();
var invoice = await controller.CreateInvoiceCoreRaw(new()
@ -1479,7 +1479,7 @@ namespace BTCPayServer.Tests
var payout = Assert.Single(payouts);
Assert.Equal("TOPUP", payout.PayoutMethodId);
Assert.Equal(invoice.Id, payout.Destination);
Assert.Equal(-0.5m, payout.Amount);
Assert.Equal(-0.5m, payout.OriginalAmount);
});
}

View file

@ -446,7 +446,7 @@ namespace BTCPayServer.Controllers.Greenfield
Name = request.Name ?? $"Refund {invoice.Id}",
Description = request.Description,
StoreId = storeId,
PayoutMethodIds = new[] { payoutMethodId },
PayoutMethods = new[] { payoutMethodId },
};
if (request.RefundVariant != RefundVariant.Custom)

View file

@ -36,7 +36,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
Name = factory.Processor,
FriendlyName = factory.FriendlyName,
PaymentMethods = factory.GetSupportedPayoutMethods().Select(id => id.ToString())
PayoutMethods = factory.GetSupportedPayoutMethods().Select(id => id.ToString())
.ToArray()
}));
}

View file

@ -132,7 +132,7 @@ namespace BTCPayServer.Controllers.Greenfield
ModelState.AddModelError(nameof(request.BOLT11Expiration), $"The BOLT11 expiration should be positive");
}
PayoutMethodId?[]? payoutMethods = null;
if (request.PaymentMethods is { } payoutMethodsStr)
if (request.PayoutMethods is { } payoutMethodsStr)
{
payoutMethods = payoutMethodsStr.Select(s =>
{
@ -144,13 +144,13 @@ namespace BTCPayServer.Controllers.Greenfield
{
if (!supported.Contains(payoutMethods[i]))
{
request.AddModelError(paymentRequest => paymentRequest.PaymentMethods[i], "Invalid or unsupported payment method", this);
request.AddModelError(paymentRequest => paymentRequest.PayoutMethods[i], "Invalid or unsupported payment method", this);
}
}
}
else
{
ModelState.AddModelError(nameof(request.PaymentMethods), "This field is required");
ModelState.AddModelError(nameof(request.PayoutMethods), "This field is required");
}
if (!ModelState.IsValid)
return this.CreateValidationError(ModelState);
@ -364,16 +364,17 @@ namespace BTCPayServer.Controllers.Greenfield
Id = p.Id,
PullPaymentId = p.PullPaymentDataId,
Date = p.Date,
Amount = p.OriginalAmount,
PaymentMethodAmount = p.Amount,
OriginalCurrency = p.OriginalCurrency,
OriginalAmount = p.OriginalAmount,
PayoutCurrency = p.Currency,
PayoutAmount = p.Amount,
Revision = blob.Revision,
State = p.State,
PayoutMethodId = p.PayoutMethodId,
PaymentProof = p.GetProofBlobJson(),
Destination = blob.Destination,
Metadata = blob.Metadata?? new JObject(),
};
model.Destination = blob.Destination;
model.PayoutMethodId = p.PayoutMethodId;
model.CryptoCode = p.Currency;
model.PaymentProof = p.GetProofBlobJson();
return model;
}

View file

@ -46,7 +46,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
Stores = new[] { storeId },
Processors = new[] { LightningAutomatedPayoutSenderFactory.ProcessorName },
PayoutMethodIds = paymentMethodId is null ? null : new[] { paymentMethodId }
PayoutMethods = paymentMethodId is null ? null : new[] { paymentMethodId }
});
return Ok(configured.Select(ToModel).ToArray());
@ -88,7 +88,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
Stores = new[] { storeId },
Processors = new[] { LightningAutomatedPayoutSenderFactory.ProcessorName },
PayoutMethodIds = new[] { pmi }
PayoutMethods = new[] { pmi }
}))
.FirstOrDefault();
activeProcessor ??= new PayoutProcessorData();

View file

@ -47,7 +47,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
Stores = new[] { storeId },
Processors = new[] { OnChainAutomatedPayoutSenderFactory.ProcessorName },
PayoutMethodIds = paymentMethodId is null ? null : new[] { paymentMethodId }
PayoutMethods = paymentMethodId is null ? null : new[] { paymentMethodId }
});
return Ok(configured.Select(ToModel).ToArray());
@ -94,7 +94,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
Stores = new[] { storeId },
Processors = new[] { OnChainAutomatedPayoutSenderFactory.ProcessorName },
PayoutMethodIds = new[] { payoutMethodId }
PayoutMethods = new[] { payoutMethodId }
}))
.FirstOrDefault();
activeProcessor ??= new PayoutProcessorData();

View file

@ -39,7 +39,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
Name = datas.Key,
FriendlyName = _factories.FirstOrDefault(factory => factory.Processor == datas.Key)?.FriendlyName,
PaymentMethods = datas.Select(data => data.PayoutMethodId).ToArray()
PayoutMethods = datas.Select(data => data.PayoutMethodId).ToArray()
});
return Ok(configured);
@ -55,7 +55,7 @@ namespace BTCPayServer.Controllers.Greenfield
{
Stores = new[] { storeId },
Processors = new[] { processor },
PayoutMethodIds = new[] { PayoutMethodId.Parse(paymentMethod) }
PayoutMethods = new[] { PayoutMethodId.Parse(paymentMethod) }
})).FirstOrDefault();
if (matched is null)
{

View file

@ -413,7 +413,7 @@ namespace BTCPayServer.Controllers
createPullPayment = new CreatePullPayment
{
Name = $"Refund {invoice.Id}",
PayoutMethodIds = new[] { pmi },
PayoutMethods = new[] { pmi },
StoreId = invoice.StoreId,
BOLT11Expiration = store.GetStoreBlob().RefundBOLT11Expiration
};

View file

@ -150,7 +150,7 @@ namespace BTCPayServer.Controllers
Amount = model.Amount,
Currency = model.Currency,
StoreId = storeId,
PayoutMethodIds = selectedPaymentMethodIds,
PayoutMethods = selectedPaymentMethodIds,
BOLT11Expiration = TimeSpan.FromDays(model.BOLT11Expiration),
AutoApproveClaims = model.AutoApproveClaims
});
@ -586,7 +586,7 @@ namespace BTCPayServer.Controllers
private async Task<bool> HasPayoutProcessor(string storeId, PayoutMethodId payoutMethodId)
{
var processors = await _payoutProcessorService.GetProcessors(
new PayoutProcessorService.PayoutProcessorQuery { Stores = [storeId], PayoutMethodIds = [payoutMethodId] });
new PayoutProcessorService.PayoutProcessorQuery { Stores = [storeId], PayoutMethods = [payoutMethodId] });
return _payoutProcessorFactories.Any(factory => factory.GetSupportedPayoutMethods().Contains(payoutMethodId)) && processors.Any();
}
private async Task<bool> HasPayoutProcessor(string storeId, string payoutMethodId)

View file

@ -39,7 +39,7 @@ namespace BTCPayServer.HostedServices
public string Description { get; set; }
public decimal Amount { get; set; }
public string Currency { get; set; }
public PayoutMethodId[] PayoutMethodIds { get; set; }
public PayoutMethodId[] PayoutMethods { get; set; }
public bool AutoApproveClaims { get; set; }
public TimeSpan? BOLT11Expiration { get; set; }
}
@ -119,7 +119,7 @@ namespace BTCPayServer.HostedServices
Amount = request.Amount,
Currency = request.Currency,
StoreId = storeId,
PayoutMethodIds = request.PaymentMethods.Select(p => PayoutMethodId.Parse(p)).ToArray(),
PayoutMethods = request.PayoutMethods.Select(p => PayoutMethodId.Parse(p)).ToArray(),
AutoApproveClaims = request.AutoApproveClaims
});
}
@ -143,7 +143,7 @@ namespace BTCPayServer.HostedServices
{
Name = create.Name ?? string.Empty,
Description = create.Description ?? string.Empty,
SupportedPayoutMethods = create.PayoutMethodIds,
SupportedPayoutMethods = create.PayoutMethods,
AutoApproveClaims = create.AutoApproveClaims,
View = new PullPaymentBlob.PullPaymentView
{

View file

@ -37,8 +37,6 @@ namespace BTCPayServer.Models.WalletViewModels
public List<PullPaymentModel> PullPayments { get; set; } = new List<PullPaymentModel>();
public override int CurrentPageCount => PullPayments.Count;
public string PaymentMethodId { get; set; }
public IEnumerable<PaymentMethodId> PaymentMethods { get; set; }
public PullPaymentState ActiveState { get; set; } = PullPaymentState.Active;
}

View file

@ -54,7 +54,7 @@ public class UILightningAutomatedPayoutProcessorsController : Controller
{
Stores = new[] { storeId },
Processors = new[] { _lightningAutomatedPayoutSenderFactory.Processor },
PayoutMethodIds = new[]
PayoutMethods = new[]
{
PayoutTypes.LN.GetPayoutMethodId(cryptoCode)
}
@ -88,7 +88,7 @@ public class UILightningAutomatedPayoutProcessorsController : Controller
{
Stores = new[] { storeId },
Processors = new[] { _lightningAutomatedPayoutSenderFactory.Processor },
PayoutMethodIds = new[]
PayoutMethods = new[]
{
PayoutTypes.LN.GetPayoutMethodId(cryptoCode)
}

View file

@ -65,7 +65,7 @@ public class UIOnChainAutomatedPayoutProcessorsController : Controller
{
Stores = new[] { storeId },
Processors = new[] { _onChainAutomatedPayoutSenderFactory.Processor },
PayoutMethodIds = new[]
PayoutMethods = new[]
{
PayoutTypes.CHAIN.GetPayoutMethodId(cryptoCode)
}
@ -98,7 +98,7 @@ public class UIOnChainAutomatedPayoutProcessorsController : Controller
{
Stores = new[] { storeId },
Processors = new[] { OnChainAutomatedPayoutSenderFactory.ProcessorName },
PayoutMethodIds = new[]
PayoutMethods = new[]
{
PayoutTypes.CHAIN.GetPayoutMethodId(cryptoCode)
}

View file

@ -53,11 +53,11 @@ public class PayoutProcessorService : EventHostedServiceBase
public PayoutProcessorQuery(string storeId, PayoutMethodId payoutMethodId)
{
Stores = new[] { storeId };
PayoutMethodIds = new[] { payoutMethodId };
PayoutMethods = new[] { payoutMethodId };
}
public string[] Stores { get; set; }
public string[] Processors { get; set; }
public PayoutMethodId[] PayoutMethodIds { get; set; }
public PayoutMethodId[] PayoutMethods { get; set; }
}
public async Task<List<PayoutProcessorData>> GetProcessors(PayoutProcessorQuery query)
@ -73,9 +73,9 @@ public class PayoutProcessorService : EventHostedServiceBase
{
queryable = queryable.Where(data => query.Stores.Contains(data.StoreId));
}
if (query.PayoutMethodIds is not null)
if (query.PayoutMethods is not null)
{
var paymentMethods = query.PayoutMethodIds.Select(d => d.ToString()).Distinct().ToArray();
var paymentMethods = query.PayoutMethods.Select(d => d.ToString()).Distinct().ToArray();
queryable = queryable.Where(data => paymentMethods.Contains(data.PayoutMethodId));
}

View file

@ -531,7 +531,7 @@
"description": "Human name of the payout processor",
"type": "string"
},
"paymentMethods": {
"payoutMethods": {
"nullable": true,
"description": "Supported, payment methods by this processor",
"type": "array",

View file

@ -223,9 +223,9 @@
"nullable": true,
"description": "When this pull payment expires. Never expires if null or unspecified."
},
"paymentMethods": {
"payoutMethods": {
"type": "array",
"description": "The list of supported payment methods supported by this pull payment. Available options can be queried from the `StorePaymentMethods_GetStorePaymentMethods` endpoint",
"description": "The list of supported payout methods supported by this pull payment. Available options can be queried from the `StorePaymentMethods_GetStorePaymentMethods` endpoint",
"items": {
"type": "string",
"example": "BTC"
@ -1091,11 +1091,29 @@
"example": "1BvBMSEYstWetqTFn5Au4m4GFg7xJaNVN2",
"description": "The destination of the payout (can be an address or a BIP21 url)"
},
"amount": {
"originalCurrency": {
"type": "string",
"example": "USD",
"description": "The currency before being converted into the payout's currency"
},
"originalAmount": {
"type": "string",
"format": "decimal",
"nullable": false,
"example": "10399.18",
"description": "The amount of the payout in the currency of the pull payment (eg. USD)."
"description": "The amount in originalCurrency before being converted into the payout's currency"
},
"payoutCurrency": {
"type": "string",
"example": "BTC",
"description": "The currency of the payout after conversion."
},
"payoutAmount": {
"type": "string",
"format": "decimal",
"nullable": true,
"example": "0.1",
"description": "The amount in payoutCurrency after conversion. (This property is set after the payout has been Approved)"
},
"payoutMethodId": {
"$ref": "#/components/schemas/PayoutMethodId"