Compare commits
265 Commits
v1.7.2
...
lnurl-hook
Author | SHA1 | Date | |
---|---|---|---|
72e66aa576 | |||
6388057806 | |||
1f197f6688 | |||
1055e61bb4 | |||
d3f5576570 | |||
45141d1391 | |||
de9ac9fd43 | |||
c53d5272d6 | |||
18c78192ec | |||
632d67eef4 | |||
c23aa48688 | |||
95f3e429b4 | |||
8635fcfe84 | |||
d861537d9a | |||
631ee99f60 | |||
ffa1441ccd | |||
2f3e947027 | |||
a62aecfdfe | |||
5f829c68f2 | |||
0290d74aeb | |||
f6bc16007d | |||
ad5752f09b | |||
55565f1718 | |||
5f96d17b8c | |||
fd22406e0a | |||
64fe542c1e | |||
fae1dc8dbb | |||
6f2b673021 | |||
b26679ca14 | |||
04ba1430ca | |||
53f3758abc | |||
c6742f5533 | |||
cb44591a47 | |||
e02abb509f | |||
eff6be9643 | |||
348dbd7107 | |||
f74ea14d8b | |||
a671632fde | |||
e344622c9e | |||
06d7483ca3 | |||
7fe041fc2c | |||
3f18e5476a | |||
2a31613fe8 | |||
ded0c8a3bc | |||
f3d9e07c5e | |||
eb3ba95114 | |||
7951dcada6 | |||
06951a39c6 | |||
abe29f21f0 | |||
f57eab3008 | |||
6d4b2348ac | |||
397ca6ef0c | |||
d6e5ee2851 | |||
98d62e826b | |||
7b5ce8f70c | |||
2010a9a458 | |||
f787058c17 | |||
87ccae0d90 | |||
07d95c6ed7 | |||
514823f7d2 | |||
fb4feb24f3 | |||
5caa0e0722 | |||
0406b420c8 | |||
9d72b9779e | |||
fdc47e4a38 | |||
0566e964c0 | |||
896fbf9a5c | |||
126c8c101e | |||
3cb7cc01e4 | |||
2b3d15bf45 | |||
4049bdadcb | |||
2042ba37d8 | |||
41a4ba62b0 | |||
21558d25b1 | |||
06622bfbfd | |||
16fd2e3938 | |||
040d7670ec | |||
23761eacc1 | |||
5790bed766 | |||
2f88da67e8 | |||
21091cbf1a | |||
808949a884 | |||
06334273dc | |||
5399c04dff | |||
cd051d4093 | |||
0ca6e8ccfb | |||
bd075919f3 | |||
c229425534 | |||
e89b1826ce | |||
4ef19e19cc | |||
ff58301729 | |||
4ae05272c3 | |||
d14dafc871 | |||
022a077726 | |||
d5bd86b07a | |||
66e1eee010 | |||
ddb125f458 | |||
e6a157a101 | |||
0a437fba6a | |||
39f2e80dc1 | |||
13f9eb0d18 | |||
575b829799 | |||
02e50fadae | |||
a02f191034 | |||
d73d0f178f | |||
d542a61f5a | |||
e0486aaa24 | |||
02bf76fb3c | |||
8a3ece4a70 | |||
c553dc02a9 | |||
ff71caa47e | |||
2bd8227e20 | |||
5c61de3ae9 | |||
cff46f2d59 | |||
bbbaacc350 | |||
60f84d5e30 | |||
5218aa3c43 | |||
4b2ea0c0c3 | |||
9b865ef849 | |||
9344113ae4 | |||
4448ac9d2a | |||
9aff143d40 | |||
fc14f418cb | |||
b99253ff47 | |||
9cb844cbbb | |||
285aedef2f | |||
5121d64022 | |||
8b80910d70 | |||
a5ff655eed | |||
cc9c63c33e | |||
87eef72289 | |||
8e8ba3d052 | |||
fea27b900c | |||
7ad91a76cd | |||
a62b674722 | |||
350f35b08d | |||
f405321abc | |||
0d077f6ce5 | |||
dffa6accb0 | |||
b5abcd5ae5 | |||
72a9e676c1 | |||
3658b396d3 | |||
537acab16d | |||
8c6fe91c71 | |||
3c344331af | |||
d14ce2a37f | |||
33d272d4b0 | |||
57f5c15670 | |||
487faa69c6 | |||
9148a1e564 | |||
4c3f5e1e1a | |||
b0bf0824dd | |||
dea5991e01 | |||
739932a280 | |||
1f8bc5b490 | |||
753ffd401b | |||
0d1bab45a0 | |||
17cc439de3 | |||
5d03e300fb | |||
a20408bed1 | |||
ed0ccd6f13 | |||
bb1138efb5 | |||
82b36aaca7 | |||
688044429e | |||
7bbfc8e6d4 | |||
85513aa5c3 | |||
67254cc30c | |||
b055844973 | |||
9ba03848f2 | |||
5b96ab89fd | |||
6a4d8f7404 | |||
219d03b8dd | |||
523654f2eb | |||
b9b8cb9f63 | |||
94f2cd4257 | |||
26248774c2 | |||
99299ba06f | |||
6e42eaa26c | |||
ae7b621e3d | |||
f2ced20c42 | |||
e4f256d5cd | |||
ca1dac4cc3 | |||
8fc2729fab | |||
24c19efd52 | |||
a3edd829a6 | |||
9ec475fa40 | |||
aad06c583e | |||
f821e35cb0 | |||
14313291d5 | |||
b818352a04 | |||
c0c34fbb41 | |||
b372dc21d6 | |||
3d576cd06b | |||
438dcc4c6f | |||
de4ac2c830 | |||
f46443a5e3 | |||
69e90b7ff1 | |||
5089ec9826 | |||
372df93c18 | |||
1d2ddeedde | |||
4df2f1f756 | |||
f10c1c4730 | |||
92b556e54f | |||
b46ae7a651 | |||
9f3a3c5f51 | |||
b5071237fd | |||
1d2bebf17a | |||
9086822b94 | |||
d90d3c5a0f | |||
a3203e5775 | |||
5f24b41250 | |||
b577c0adb7 | |||
a9ad0fde9e | |||
9974b6070e | |||
bd5e4f3d94 | |||
e0adb1133d | |||
3cdb4f5b2a | |||
248401f534 | |||
1228a06a90 | |||
b5cd215643 | |||
7604667b55 | |||
3a278d8079 | |||
adcc484528 | |||
798553e96a | |||
068b717a75 | |||
785cf597ad | |||
ee70fe85c0 | |||
2e31816979 | |||
e4237c9511 | |||
0bc6967dbc | |||
2301769419 | |||
42c5f732a2 | |||
2428b564fd | |||
bb0e96a163 | |||
bb733c5811 | |||
ffeaf55c4e | |||
a12bb1d9ce | |||
313f2a667e | |||
d5d0be5824 | |||
3fa28bb46d | |||
eb90fab640 | |||
099d65032a | |||
e96feb36cd | |||
eb6d01c21e | |||
03d7dc8971 | |||
09d5f5a083 | |||
1a41b3fb64 | |||
f958550061 | |||
1e8e7ec4a4 | |||
83c4e38fa5 | |||
607d2fedb7 | |||
627ada56b7 | |||
9ce06fdc4e | |||
bb63ae6d87 | |||
a4182621da | |||
0534261759 | |||
c7baa66a4d | |||
1732606581 | |||
68cdd2c2c8 | |||
ea03b6c19c | |||
b83eb41df3 | |||
e6c68dc5bc | |||
76a953819e | |||
3a2ad48bd6 | |||
674d5bae8a |
.editorconfigREADME.mdbtcpayserver.slnbuild.ps1build.sh
.github/ISSUE_TEMPLATE
.gitignore.run
BTCPayServer.Abstractions
Configuration
Contracts
Custodians
Client
AssetQuoteResult.cs
ICanTrade.csICanWithdraw.csICustodian.csException
AssetBalancesUnavailableException.csCustodianApiException.csCustodianFeatureNotImplementedException.csInsufficientFundsException.csTradeNotFoundException.csWrongTradingPairException.cs
SimulateWithdrawalResult.csExtensions
Form
Models
Security
TagHelpers
BTCPayServer.Client
BTCPayServer.Client.csprojBTCPayServerClient.APIKeys.csBTCPayServerClient.Apps.csBTCPayServerClient.CustodianAccounts.csBTCPayServerClient.Lightning.Internal.csBTCPayServerClient.Lightning.Store.csBTCPayServerClient.LightningAddresses.csBTCPayServerClient.OnChainWallet.Objects.csBTCPayServerClient.OnChainWallet.csBTCPayServerClient.PullPayments.csBTCPayServerClient.StorePayoutProcessors.csBTCPayServerClient.StoreRatesConfiguration.csBTCPayServerClient.Users.cs
JsonConverters
Models
AssetPairData.csCreateLightningInvoiceRequest.csCustodianAccountBaseData.csCustodianAccountResponse.csCustodianData.csDepositAddressData.csLedgerEntryData.csLightningAddressData.csLightningAutomatedPayoutSettings.csLightningInvoiceData.csLightningNodeBalanceData.csLightningPaymentData.csLockUserRequest.csMarketTradeResponseData.csNotificationData.csOnChainAutomatedPayoutSettings.csOpenLightningChannelRequest.csPayLightningInvoiceRequest.csPaymentMethodCriteriaData.csPointOfSaleAppData.csPullPaymentLNURL.csRateSource.csStoreBaseData.csStoreData.csStoreRatePreviewResult.csStoreRateResult.csTradeQuoteResponseData.csWithdrawRequestData.csWithdrawalBaseResponseData.csWithdrawalResponseData.csWithdrawalSimulationResponseData.cs
Permissions.csBTCPayServer.Common
BTCPayServer.Data
ApplicationDbContext.cs
Data
APIKeyData.csApplicationUser.csCustodianAccountData.csFido2Credential.csFormData.csIHasBlob.csInvoiceData.csLightingAddressData.csNotificationData.csPaymentData.csPaymentRequestData.csPayoutProcessorData.csStoreData.csStoreSettingData.csTradeResultData.csWalletObjectData.csWebhookData.csWebhookDeliveryData.cs
Migrations
20220115184620_AddCustodianAccountData.cs20220311135252_AddPayoutProcessors.cs20220414132313_AddLightningAddress.cs20220610090843_AddSettingsToStore.cs20220929132704_label.cs20230123062447_migrateoldratesource.cs20230125085242_AddForms.cs20230130040047_blob2.cs20230130062447_jsonb2.cs20230315062447_fixmaxlength.csApplicationDbContextModelSnapshot.cs
BTCPayServer.PluginPacker
BTCPayServer.Plugins.Test/Views/Shared
BTCPayServer.Rating
AvailableRateProvider.csBTCPayServer.Rating.csprojCurrencies.jsonCurrencyNameTable.cs
Providers
ArgoneumRateProvider.csBTCTurkRateProvider.csBackgroundFetcherRateProvider.csBitbankRateProvider.csBitflyerRateProvider.csBitpayRateProvider.csBudaRateProvider.csByllsRateProvider.csCoinGeckoRateProvider.csCryptoMarketExchangeRateProvider.csExchangeSharpRateProvider.csFallbackRateProvider.csHitBTCRateProvider.csIRateProvider.csKrakenExchangeRateProvider.csNullRateProvider.csRipioExchangeProvider.csYadioRateProvider.cs
RateSourceInfo.csServices
BTCPayServer.Tests
AltcoinTests
ApiKeysTests.csBTCPayServer.Tests.csprojBTCPayServerTester.csCheckoutUITests.csCheckoutv2Tests.csCrowdfundTests.csExtensions.csFastTests.csFormTes.csGreenfieldAPITests.csMockCustodian
Mocks
POSTests.csPSBTTests.csPayJoinTests.csSeleniumTester.csSeleniumTests.csServerTester.csTestAccount.csThirdPartyTests.csUnitTest1.csUtilitiesTests.csUtils.csdocker-compose.altcoins.ymldocker-compose.ymlBTCPayServer
BTCPayServer.csprojBufferizedFormFile.csColorPalette.csProgram.csRoles.csPoliciesSettings.cs
Components
AppSales
AppTopItems
LabelManager
MainNav
Notifications
QRCode
StoreLightningBalance
StoreLightningServices
StoreNumbers
StoreRecentInvoices
StoreRecentTransactions
StoreSelector
StoreWalletBalance
TruncateCenter
WalletNav
Configuration
Controllers
BitpayRateController.cs
GreenField
GreenfieldApiKeysController.csGreenfieldAppsController.csGreenfieldCustodianAccountController.csGreenfieldInvoiceController.csGreenfieldLightningNodeApiController.Internal.csGreenfieldLightningNodeApiController.Store.csGreenfieldLightningNodeApiController.csGreenfieldNotificationsController.csGreenfieldPayoutProcessorsController.csGreenfieldPullPaymentController.csGreenfieldStoreAutomatedLightningPayoutProcessorsController.csGreenfieldStoreAutomatedOnChainPayoutProcessorsController.csGreenfieldStoreEmailController.csGreenfieldStoreLNURLPayPaymentMethodsController.csGreenfieldStoreLightningAddressesController.csGreenfieldStoreLightningNetworkPaymentMethodsController.csGreenfieldStoreOnChainPaymentMethodsController.WalletGeneration.csGreenfieldStoreOnChainPaymentMethodsController.csGreenfieldStoreOnChainWalletsController.csGreenfieldStorePaymentMethodsController.csGreenfieldStorePayoutProcessorsController.csGreenfieldStoreRatesConfigurationController.csGreenfieldStoreRatesController.csGreenfieldStoreUsersController.csGreenfieldStoresController.csGreenfieldTestApiKeyController.csGreenfieldUsersController.csLocalBTCPayServerClient.cs
LightningAddressService.csLnurlAuthService.csUIAccountController.csUIAppsController.Dashboard.csUIAppsController.csUICustodianAccountsController.csUIHomeController.csUIInvoiceController.Testing.csUIInvoiceController.UI.csUIInvoiceController.csUILNURLAuthController.csUILNURLController.csUIManageController.APIKeys.csUIManageController.Notifications.csUIManageController.csUIPaymentRequestController.csUIPublicController.csUIPublicLightningNodeInfoController.csUIPullPaymentController.csUIServerController.Plugins.csUIServerController.Users.csUIServerController.csUIStorePullPaymentsController.PullPayments.csUIStoresController.Dashboard.csUIStoresController.Email.csUIStoresController.Integrations.csUIStoresController.LightningLike.csUIStoresController.Onchain.csUIStoresController.csUIUserStoresController.csUIWalletsController.PSBT.csUIWalletsController.csData
APIKeyDataExtensions.csCustodianAccountDataExtensions.csIHasBlobExtensions.csInvoiceDataExtensions.csPaymentDataExtensions.csPaymentRequestDataExtensions.cs
DerivationSchemeParser.csDerivationSchemeSettings.csPayouts
PullPayments
StoreBlob.csStoreDataExtensions.csWalletTransactionInfo.csWebhookDataExtensions.csEvents
Extensions.csExtensions
Fido2
FileTypeDetector.csFilters
Forms
FormComponentProviders.csFormDataExtensions.csFormDataService.csHtmlFieldsetFormProvider.csHtmlInputFormProvider.csHtmlSelectFormProvider.cs
Models
ModifyForm.csUIFormsController.csHostedServices
AppInventoryUpdaterHostedService.csBaseAsyncService.csEventHostedServiceBase.csInvoiceWatcher.csPullPaymentHostedService.csStoreEmailRuleProcessorSender.csTransactionLabelMarkerHostedService.csWebhookSender.cs
Hosting
BTCPayServerServices.csMigrationStartupTask.csStartup.csToPostgresMigrationStartupTask.csValidateControllerNameTransformer.cs
IHasAdditionalData.csModels
AccountViewModels
AppViewModels
BasePagingViewModel.csCustodianAccountViewModels
AssetBalanceInfo.csCreateCustodianAccountViewModel.csTradePrepareViewModel.csViewCustodianAccountBalancesViewModel.csWithdrawalPrepareViewModel.cs
InvoicingModels
PaymentRequestViewModels
PostRedictViewModel.csServerViewModels
StoreViewModels
CheckoutAppearanceViewModel.csCreateStoreViewModel.csGeneralSettingsViewModel.csRatesViewModel.csRecoverySeedBackupViewModel.cs
ViewPullPaymentModel.csWalletViewModels
PaymentRequest
Payments
Bitcoin
IPaymentMethodDetails.csIPaymentMethodHandler.csLNURLPay
Lightning
LightningLikePaymentData.csLightningLikePaymentHandler.csLightningLikePaymentMethodDetails.csLightningListener.csLightningPendingPayoutListener.csLightningSupportedPaymentMethod.cs
PayJoin
PayoutProcessors
AfterPayoutFilterData.csBaseAutomatedPayoutProcessor.csBeforePayoutFilterData.csIPayoutProcessorFactory.cs
Lightning
LightningAutomatedPayoutProcessor.csLightningAutomatedPayoutSenderFactory.csUILightningAutomatedPayoutProcessorsController.cs
OnChain
OnChainAutomatedPayoutBlob.csOnChainAutomatedPayoutProcessor.csOnChainAutomatedPayoutSenderFactory.csUIOnChainAutomatedPayoutProcessorsController.cs
PayoutProcessorService.csPayoutProcessorsExtensions.csSettings
UIPayoutProcessorsController.csPlugins
Crowdfund
NFC
PluginBuilderClient.csPluginManager.csPluginService.csPointOfSale
Shopify
Security
CookieAuthorizationHandler.cs
GreenField
Services
Altcoins
Apps
BTCPayServerEnvironment.csCustodian
DefaultSwaggerProvider.csDisplayFormatter.csInvoiceActivator.csInvoices
Mails
MigrationSettings.csNBXplorerConnectionFactory.csNotifications
Blobs
ExternalPayoutTransactionNotification.csInvoiceEventNotification.csJunkNotification.csNewVersionNotification.csPayoutNotification.cs
NotificationManager.csNotificationSender.csStores
ThemesSettings.csUserService.csWalletRepository.csWallets
Storage
TagHelpers
UserManagerExtensions.csViews
Shared
Bitcoin
BitcoinLikeMethodCheckout-v2.cshtmlBitcoinLikeMethodCheckoutNoScript.cshtmlViewBitcoinLikePaymentData.cshtml
Confirm.cshtmlConfirmModal.cshtmlCrowdfund
Forms
LNURL
LayoutHead.cshtmlLayoutHeadStoreBranding.cshtmlLayoutPartials
Lightning
NFC
PayButton
PointOfSale
NavExtension.cshtml
PosData.cshtmlPostRedirect.cshtmlPublic
Cart.cshtmlLight.cshtmlMinimalLight.cshtmlPrint.cshtmlStatic.cshtmlVueLight.cshtml_Layout.cshtml_LayoutPos.cshtml
UpdatePointOfSale.cshtmlShopify
ShowQR.cshtmlTemplateEditor.cshtml_BTCPaySupporters.cshtml_Footer.cshtml_Form.cshtml_FormWrap.cshtml_Layout.cshtml_LayoutSignedOut.cshtml_LayoutSimple.cshtml_StatusMessage.cshtml_StoreFooterLogo.cshtml_StoreHeader.cshtml_ValidationScriptsPartial.cshtmlUIAccount
CheatPermissions.cshtmlLockout.cshtmlLogin.cshtmlLoginWith2fa.cshtmlLoginWithFido2.cshtmlLoginWithLNURLAuth.cshtml
UIApps
UICustodianAccounts
UIForms
UIHome
UIInvoice
Checkout-Body.cshtmlCheckout-Cheating.cshtmlCheckout.cshtmlCheckoutNoScript.cshtmlCheckoutV2.cshtmlInvoice.cshtmlInvoiceReceipt.cshtmlInvoiceStatusChangePartial.cshtmlListInvoices.cshtmlListInvoicesPaymentsPartial.cshtmlPosData.cshtml
UILNURL
UIManage
UIPaymentRequest
UIPayoutProcessors
UIPublicLightningNodeInfo
UIPullPayment
UIServer
UIShopify
UIStorePullPayments
UIStores
CheckoutAppearance.cshtmlDashboard.cshtmlGeneralSettings.cshtml
ImportWallet
ImportWalletOptions.cshtmlLightningSettings.cshtmlListTokens.cshtmlPlugins.cshtmlRates.cshtmlStoreNavPages.csStoreUsers.cshtmlWalletSettings.cshtml_GenerateWalletForm.cshtml_Nav.cshtmlUIUserStores
UIWallets
wwwroot
cart
checkout-v2
img
js
light-pos
locales
am-ET.jsonar.jsonaz.jsonbg-BG.jsonbs-BA.jsonca-ES.json
checkout
am-ET.jsonar.jsonaz.jsonbg-BG.jsonbs-BA.jsonca-ES.jsoncs-CZ.jsonda-DK.jsonde-DE.jsonel-GR.jsonen.jsones-ES.jsonfa.jsonfi-FI.jsonfr-FR.jsonhe.jsonhi.jsonhr-HR.jsonhu-HU.jsonhy.jsonid.jsonis-IS.jsonit-IT.jsonja-JP.jsonka.jsonkk-KZ.jsonko.jsonlv.jsonnl-NL.jsonno.jsonnp-NP.jsonpl.jsonpt-BR.jsonpt-PT.jsonro.jsonru-RU.jsonsk-SK.jsonsl-SI.jsonsr.jsonsv.jsonth-TH.jsontr.jsonuk-UA.jsonvi-VN.jsonzh-SG.jsonzh-SP.jsonzh-TW.jsonzu.json
cs-CZ.jsonda-DK.jsonde-DE.jsonel-GR.jsonen.jsones-ES.jsonfa.jsonfi-FI.jsonfr-FR.jsonhe.jsonhi.jsonhr-HR.jsonhu-HU.jsonhy.jsonid.jsonis-IS.jsonit-IT.jsonja-JP.jsonka.jsonkk-KZ.jsonko.jsonlv.jsonnl-NL.jsonno.jsonnp-NP.jsonpl.jsonpt-BR.jsonpt-PT.jsonro.jsonru-RU.jsonsk-SK.jsonsl-SI.jsonsr.jsonsv.jsonth-TH.jsontr.jsonuk-UA.jsonvi-VN.jsonzh-SG.jsonzh-SP.jsonzh-TW.jsonzu.jsonmain
manifest.jsonmodal
swagger/v1
swagger.template.api-keys.jsonswagger.template.apps.jsonswagger.template.custodians.jsonswagger.template.invoices.jsonswagger.template.jsonswagger.template.lightning.common.jsonswagger.template.lightning.internal.jsonswagger.template.lightning.store.jsonswagger.template.notifications.jsonswagger.template.payout-processors.jsonswagger.template.pull-payments.jsonswagger.template.stores-lightning-addresses.jsonswagger.template.stores-payment-methods.lnurl.jsonswagger.template.stores-rates-config.jsonswagger.template.stores-rates.jsonswagger.template.stores-users.jsonswagger.template.stores.jsonswagger.template.users.json
vendor
babel-polyfill
dom-confetti
jquery-easing
tom-select
Build
Changelog.mdLICENSEPlugins
BTCPayServer.Plugins.Custodians.FakeCustodian
BTCPayServer.Plugins.Test
BTCPayServer.Plugins.Test.csproj
Controllers
Data
Migrations
Resources/img
Services
TestExtension.csTestPluginMigrationRunner.csViews
docs
publish-docker.ps1run.ps1run.sh@ -11,10 +11,14 @@ insert_final_newline = true
|
||||
indent_style = space
|
||||
indent_size = 4
|
||||
charset = utf-8
|
||||
space_before_self_closing = true
|
||||
|
||||
[*.json]
|
||||
indent_size = 2
|
||||
|
||||
[swagger*.json]
|
||||
indent_size = 4
|
||||
|
||||
# C# files
|
||||
[*.cs]
|
||||
# New line preferences
|
||||
@ -67,7 +71,7 @@ dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
|
||||
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
|
||||
|
||||
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
|
||||
|
||||
# Code style defaults
|
||||
dotnet_sort_system_directives_first = true
|
||||
|
12
.github/ISSUE_TEMPLATE/config.yml
vendored
12
.github/ISSUE_TEMPLATE/config.yml
vendored
@ -1,8 +1,14 @@
|
||||
blank_issues_enabled: true
|
||||
contact_links:
|
||||
- name: 🚀 Discussions
|
||||
url: https://github.com/btcpayserver/btcpayserver/discussions
|
||||
about: Technical discussions, questions and feature requests
|
||||
- name: 💡 Request a feature
|
||||
url: https://github.com/btcpayserver/btcpayserver/discussions/categories/ideas-feature-requests
|
||||
about: Submit a feature request or vote on ideas posted by others. Features with most upvotes become roadmap candidates
|
||||
- name: 🧑💻 Ask a technical question
|
||||
url: https://github.com/btcpayserver/btcpayserver/discussions/new?category=technical-support
|
||||
about: If you're experiencing a technical problem post it to our community support forum
|
||||
- name: 🔌 Report a problem with a plugin
|
||||
url: https://github.com/btcpayserver/btcpayserver/discussions/new?category=plugins-integrations
|
||||
about: Experiencing a problem with a third-party plugin? Post it here and we will tag their developers to assist
|
||||
- name: 📝 Official Documentation
|
||||
url: https://docs.btcpayserver.org
|
||||
about: Check our documentation for answers to common questions
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@ -298,3 +298,4 @@ Packed Plugins
|
||||
Plugins/packed
|
||||
|
||||
BTCPayServer/wwwroot/swagger/v1/openapi.json
|
||||
BTCPayServer/appsettings.dev.json
|
@ -14,8 +14,8 @@
|
||||
<option name="PROJECT_KIND" value="DotNetCore" />
|
||||
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
|
||||
<method v="2">
|
||||
<option name="Build" default="false" projectName="BTCPayServer.Plugins.Test" projectPath="C:\Git\btcpayserver\BTCPayServer.Plugins.Test\BTCPayServer.Plugins.Test.csproj" />
|
||||
<option name="Build" default="false" projectName="BTCPayServer.Plugins.Test" projectPath="C:\Git\btcpayserver\Plugins\BTCPayServer.Plugins.Test\BTCPayServer.Plugins.Test.csproj" />
|
||||
<option name="Build" />
|
||||
</method>
|
||||
</configuration>
|
||||
</component>
|
||||
</component>
|
||||
|
@ -1,3 +1,5 @@
|
||||
using System.IO;
|
||||
|
||||
namespace BTCPayServer.Configuration
|
||||
{
|
||||
public class DataDirectories
|
||||
@ -7,5 +9,12 @@ namespace BTCPayServer.Configuration
|
||||
public string TempStorageDir { get; set; }
|
||||
public string StorageDir { get; set; }
|
||||
public string TempDir { get; set; }
|
||||
|
||||
public string ToDatadirFullPath(string path)
|
||||
{
|
||||
if (Path.IsPathRooted(path))
|
||||
return path;
|
||||
return Path.Combine(DataDir, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
|
@ -19,6 +19,8 @@ namespace BTCPayServer.Abstractions.Contracts
|
||||
public class NotificationViewModel
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Identifier { get; set; }
|
||||
public string Type { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
public string Body { get; set; }
|
||||
public string ActionLink { get; set; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
#nullable enable
|
||||
#nullable enable
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
public interface IScopeProvider
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Contracts;
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using NBitcoin;
|
||||
|
||||
|
@ -9,7 +9,7 @@ public class AssetQuoteResult
|
||||
|
||||
public AssetQuoteResult() { }
|
||||
|
||||
public AssetQuoteResult(string fromAsset, string toAsset,decimal bid, decimal ask)
|
||||
public AssetQuoteResult(string fromAsset, string toAsset, decimal bid, decimal ask)
|
||||
{
|
||||
FromAsset = fromAsset;
|
||||
ToAsset = toAsset;
|
||||
|
@ -2,10 +2,11 @@ namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class AssetBalancesUnavailableException : CustodianApiException
|
||||
{
|
||||
|
||||
public AssetBalancesUnavailableException(System.Exception e) : base(500, "asset-balances-unavailable", $"Cannot fetch the asset balances: {e.Message}", e)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public AssetBalancesUnavailableException(string errorMsg) : base(500, "asset-balances-unavailable", $"Cannot fetch the asset balances: {errorMsg}")
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
using System;
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
public class CustodianApiException: Exception {
|
||||
public class CustodianApiException : Exception
|
||||
{
|
||||
public int HttpStatus { get; }
|
||||
public string Code { get; }
|
||||
|
||||
@ -9,7 +10,8 @@ public class CustodianApiException: Exception {
|
||||
HttpStatus = httpStatus;
|
||||
Code = code;
|
||||
}
|
||||
public CustodianApiException( int httpStatus, string code, string message) : this(httpStatus, code, message, null)
|
||||
|
||||
public CustodianApiException(int httpStatus, string code, string message) : this(httpStatus, code, message, null)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class CustodianFeatureNotImplementedException: CustodianApiException
|
||||
public class CustodianFeatureNotImplementedException : CustodianApiException
|
||||
{
|
||||
public CustodianFeatureNotImplementedException(string message) : base(400, "not-implemented", message)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,8 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class InsufficientFundsException : CustodianApiException
|
||||
{
|
||||
{
|
||||
public InsufficientFundsException(string message) : base(400, "insufficient-funds", message)
|
||||
{
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ public class TradeNotFoundException : CustodianApiException
|
||||
{
|
||||
private string tradeId { get; }
|
||||
|
||||
public TradeNotFoundException(string tradeId) : base(404,"trade-not-found","Could not find trade ID " + tradeId)
|
||||
public TradeNotFoundException(string tradeId) : base(404, "trade-not-found", "Could not find trade ID " + tradeId)
|
||||
{
|
||||
this.tradeId = tradeId;
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public class WrongTradingPairException: CustodianApiException
|
||||
public class WrongTradingPairException : CustodianApiException
|
||||
{
|
||||
public const int HttpCode = 404;
|
||||
public WrongTradingPairException(string fromAsset, string toAsset) : base(HttpCode, "wrong-trading-pair", $"Cannot find a trading pair for converting {fromAsset} into {toAsset}.")
|
||||
|
@ -0,0 +1,28 @@
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.JsonConverters;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians.Client;
|
||||
|
||||
public class SimulateWithdrawalResult
|
||||
{
|
||||
public string PaymentMethod { get; }
|
||||
public string Asset { get; }
|
||||
public decimal MinQty { get; }
|
||||
public decimal MaxQty { get; }
|
||||
|
||||
public List<LedgerEntryData> LedgerEntries { get; }
|
||||
|
||||
// Fee can be NULL if unknown.
|
||||
public decimal? Fee { get; }
|
||||
|
||||
public SimulateWithdrawalResult(string paymentMethod, string asset, List<LedgerEntryData> ledgerEntries,
|
||||
decimal minQty, decimal maxQty)
|
||||
{
|
||||
PaymentMethod = paymentMethod;
|
||||
Asset = asset;
|
||||
LedgerEntries = ledgerEntries;
|
||||
MinQty = minQty;
|
||||
MaxQty = maxQty;
|
||||
}
|
||||
}
|
@ -9,18 +9,16 @@ namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
public interface ICanTrade
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* A list of tradable asset pairs, or NULL if the custodian cannot trade/convert assets. if thr asset pair contains fiat, fiat is always put last. If both assets are a cyrptocode or both are fiat, the pair is written alphabetically. Always in uppercase. Example: ["BTC/EUR","BTC/USD", "EUR/USD", "BTC/ETH",...]
|
||||
*/
|
||||
public List<AssetPairData> GetTradableAssetPairs();
|
||||
|
||||
|
||||
/**
|
||||
* Execute a market order right now.
|
||||
*/
|
||||
public Task<MarketTradeResult> TradeMarketAsync(string fromAsset, string toAsset, decimal qty, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
|
||||
/**
|
||||
* Get the details about a previous market trade.
|
||||
*/
|
||||
|
@ -5,9 +5,14 @@ using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Custodians;
|
||||
|
||||
/// <summary>
|
||||
/// Interface for custodians that can move funds to the store wallet.
|
||||
/// </summary>
|
||||
public interface ICanWithdraw
|
||||
{
|
||||
public Task<WithdrawResult> WithdrawAsync(string paymentMethod, decimal amount, JObject config, CancellationToken cancellationToken);
|
||||
public Task<WithdrawResult> WithdrawToStoreWalletAsync(string paymentMethod, decimal amount, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public Task<SimulateWithdrawalResult> SimulateWithdrawalAsync(string paymentMethod, decimal qty, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public Task<WithdrawResult> GetWithdrawalInfoAsync(string paymentMethod, string withdrawalId, JObject config, CancellationToken cancellationToken);
|
||||
|
||||
|
@ -12,7 +12,7 @@ public interface ICustodian
|
||||
* Get the unique code that identifies this custodian.
|
||||
*/
|
||||
string Code { get; }
|
||||
|
||||
|
||||
string Name { get; }
|
||||
|
||||
/**
|
||||
@ -20,7 +20,6 @@ public interface ICustodian
|
||||
*/
|
||||
Task<Dictionary<string, decimal>> GetAssetBalancesAsync(JObject config, CancellationToken cancellationToken);
|
||||
|
||||
public Task<Form.Form> GetConfigForm(JObject config, string locale,
|
||||
CancellationToken cancellationToken = default);
|
||||
public Task<Form.Form> GetConfigForm(CancellationToken cancellationToken = default);
|
||||
|
||||
}
|
||||
|
@ -7,6 +7,10 @@ namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class GreenfieldExtensions
|
||||
{
|
||||
public static IActionResult UserNotFound(this ControllerBase ctrl)
|
||||
{
|
||||
return ctrl.CreateAPIError(404, "user-not-found", "The user was not found");
|
||||
}
|
||||
public static IActionResult CreateValidationError(this ControllerBase controller, ModelStateDictionary modelState)
|
||||
{
|
||||
return controller.UnprocessableEntity(modelState.ToGreenfieldValidationError());
|
||||
@ -30,12 +34,12 @@ public static class GreenfieldExtensions
|
||||
{
|
||||
return controller.BadRequest(new GreenfieldAPIError(errorCode, errorMessage));
|
||||
}
|
||||
|
||||
|
||||
public static IActionResult CreateAPIError(this ControllerBase controller, int httpCode, string errorCode, string errorMessage)
|
||||
{
|
||||
return controller.StatusCode(httpCode, new GreenfieldAPIError(errorCode, errorMessage));
|
||||
}
|
||||
|
||||
|
||||
public static IActionResult CreateAPIPermissionError(this ControllerBase controller, string missingPermission, string message = null)
|
||||
{
|
||||
return controller.StatusCode(403, new GreenfieldPermissionAPIError(missingPermission, message));
|
||||
|
@ -11,7 +11,7 @@ public static class HttpRequestExtensions
|
||||
return false;
|
||||
return request.Host.Host.EndsWith(".onion", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
|
||||
public static string GetAbsoluteRoot(this HttpRequest request)
|
||||
{
|
||||
return string.Concat(
|
||||
|
@ -6,7 +6,6 @@ namespace BTCPayServer.Abstractions.Extensions;
|
||||
|
||||
public static class StringExtensions
|
||||
{
|
||||
|
||||
public static bool IsValidFileName(this string fileName)
|
||||
{
|
||||
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c)
|
||||
@ -41,5 +40,4 @@ public static class StringExtensions
|
||||
return str.Substring(0, str.Length - 1);
|
||||
return str;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -50,7 +50,7 @@ namespace BTCPayServer.Abstractions.Extensions
|
||||
{
|
||||
return IsActiveCategory(viewData, category.ToString(), id);
|
||||
}
|
||||
|
||||
|
||||
public static string IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
|
||||
{
|
||||
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY))
|
||||
@ -77,7 +77,7 @@ namespace BTCPayServer.Abstractions.Extensions
|
||||
? ActivePageClass
|
||||
: null;
|
||||
}
|
||||
|
||||
|
||||
public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
|
||||
{
|
||||
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
|
||||
@ -126,7 +126,7 @@ namespace BTCPayServer.Abstractions.Extensions
|
||||
{
|
||||
return $"{(int)timeSpan.TotalMinutes} minute{Plural((int)timeSpan.TotalMinutes)}";
|
||||
}
|
||||
return timeSpan.Days < 1
|
||||
return timeSpan.Days < 1
|
||||
? $"{(int)timeSpan.TotalHours} hour{Plural((int)timeSpan.TotalHours)}"
|
||||
: $"{(int)timeSpan.TotalDays} day{Plural((int)timeSpan.TotalDays)}";
|
||||
}
|
||||
|
@ -17,16 +17,16 @@ public class AlertMessage
|
||||
Danger,
|
||||
Info
|
||||
}
|
||||
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public AlertMessageType Type;
|
||||
|
||||
|
||||
// The translated message to be shown to the user
|
||||
public string Message;
|
||||
|
||||
public AlertMessage()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
public AlertMessage(AlertMessageType type, string message)
|
||||
|
@ -12,12 +12,12 @@ public class Field
|
||||
{
|
||||
public static Field Create(string label, string name, string value, bool required, string helpText, string type = "text")
|
||||
{
|
||||
return new Field()
|
||||
return new Field
|
||||
{
|
||||
Label = label,
|
||||
Name = name,
|
||||
Value = value,
|
||||
OriginalValue = value,
|
||||
OriginalValue = value,
|
||||
Required = required,
|
||||
HelpText = helpText,
|
||||
Type = type
|
||||
@ -26,14 +26,14 @@ public class Field
|
||||
// The name of the HTML5 node. Should be used as the key for the posted data.
|
||||
public string Name;
|
||||
|
||||
public bool Hidden;
|
||||
public bool Constant;
|
||||
|
||||
// HTML5 compatible type string like "text", "textarea", "email", "password", etc. Each type is a class and may contain more fields (i.e. "select" would have options).
|
||||
// HTML5 compatible type string like "text", "textarea", "email", "password", etc.
|
||||
public string Type;
|
||||
|
||||
public static Field CreateFieldset()
|
||||
{
|
||||
return new Field() { Type = "fieldset" };
|
||||
return new Field { Type = "fieldset" };
|
||||
}
|
||||
|
||||
// The value field is what is currently in the DB or what the user entered, but possibly not saved yet due to validation errors.
|
||||
@ -52,10 +52,10 @@ public class Field
|
||||
public string HelpText;
|
||||
|
||||
[JsonExtensionData] public IDictionary<string, JToken> AdditionalData { get; set; }
|
||||
public List<Field> Fields { get; set; } = new();
|
||||
public List<Field> Fields { get; set; } = new ();
|
||||
|
||||
// The field is considered "valid" if there are no validation errors
|
||||
public List<string> ValidationErrors = new List<string>();
|
||||
public List<string> ValidationErrors = new ();
|
||||
|
||||
public virtual bool IsValid()
|
||||
{
|
||||
|
@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.AspNetCore.Mvc.ModelBinding;
|
||||
using Microsoft.Extensions.Primitives;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Npgsql.Internal.TypeHandlers.GeometricHandlers;
|
||||
|
||||
namespace BTCPayServer.Abstractions.Form;
|
||||
|
||||
@ -20,137 +22,138 @@ public class Form
|
||||
return JObject.FromObject(this, CamelCaseSerializerSettings.Serializer).ToString(Newtonsoft.Json.Formatting.Indented);
|
||||
}
|
||||
#nullable restore
|
||||
|
||||
// Messages to be shown at the top of the form indicating user feedback like "Saved successfully" or "Please change X because of Y." or a warning, etc...
|
||||
public List<AlertMessage> TopMessages { get; set; } = new();
|
||||
|
||||
|
||||
// Groups of fields in the form
|
||||
public List<Field> Fields { get; set; } = new();
|
||||
|
||||
|
||||
// Are all the fields valid in the form?
|
||||
public bool IsValid()
|
||||
{
|
||||
return Fields.Select(f => f.IsValid()).All(o => o);
|
||||
}
|
||||
|
||||
public Field GetFieldByName(string name)
|
||||
public Field GetFieldByFullName(string fullName)
|
||||
{
|
||||
return GetFieldByName(name, Fields, null);
|
||||
}
|
||||
|
||||
private static Field GetFieldByName(string name, List<Field> fields, string prefix)
|
||||
{
|
||||
prefix ??= string.Empty;
|
||||
foreach (var field in fields)
|
||||
foreach (var f in GetAllFields())
|
||||
{
|
||||
var currentPrefix = prefix;
|
||||
if (!string.IsNullOrEmpty(field.Name))
|
||||
{
|
||||
|
||||
currentPrefix = $"{prefix}{field.Name}";
|
||||
if (currentPrefix.Equals(name, StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
return field;
|
||||
}
|
||||
|
||||
currentPrefix += "_";
|
||||
}
|
||||
|
||||
var subFieldResult = GetFieldByName(name, field.Fields, currentPrefix);
|
||||
if (subFieldResult is not null)
|
||||
{
|
||||
return subFieldResult;
|
||||
}
|
||||
|
||||
if (f.FullName == fullName)
|
||||
return f.Field;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public List<string> GetAllNames()
|
||||
public IEnumerable<(string FullName, List<string> Path, Field Field)> GetAllFields()
|
||||
{
|
||||
return GetAllNames(Fields);
|
||||
}
|
||||
|
||||
private static List<string> GetAllNames(List<Field> fields)
|
||||
{
|
||||
var names = new List<string>();
|
||||
|
||||
foreach (var field in fields)
|
||||
HashSet<string> nameReturned = new();
|
||||
foreach (var f in GetAllFieldsCore(new List<string>(), Fields))
|
||||
{
|
||||
string prefix = string.Empty;
|
||||
if (!string.IsNullOrEmpty(field.Name))
|
||||
{
|
||||
names.Add(field.Name);
|
||||
prefix = $"{field.Name}_";
|
||||
}
|
||||
|
||||
if (field.Fields.Any())
|
||||
{
|
||||
names.AddRange(GetAllNames(field.Fields).Select(s => $"{prefix}{s}" ));
|
||||
}
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
public void ApplyValuesFromOtherForm(Form form)
|
||||
{
|
||||
foreach (var fieldset in Fields)
|
||||
{
|
||||
foreach (var field in fieldset.Fields)
|
||||
{
|
||||
field.Value = form
|
||||
.GetFieldByName(
|
||||
$"{(string.IsNullOrEmpty(fieldset.Name) ? string.Empty : fieldset.Name + "_")}{field.Name}")
|
||||
?.Value;
|
||||
}
|
||||
var fullName = string.Join('_', f.Path.Where(s => !string.IsNullOrEmpty(s)));
|
||||
if (!nameReturned.Add(fullName))
|
||||
continue;
|
||||
yield return (fullName, f.Path, f.Field);
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyValuesFromForm(IFormCollection form)
|
||||
|
||||
public bool ValidateFieldNames(out List<string> errors)
|
||||
{
|
||||
var names = GetAllNames();
|
||||
foreach (var name in names)
|
||||
errors = new List<string>();
|
||||
HashSet<string> nameReturned = new();
|
||||
foreach (var f in GetAllFieldsCore(new List<string>(), Fields))
|
||||
{
|
||||
var field = GetFieldByName(name);
|
||||
if (field is null || !form.TryGetValue(name, out var val))
|
||||
var fullName = string.Join('_', f.Path.Where(s => !string.IsNullOrEmpty(s)));
|
||||
if (!nameReturned.Add(fullName))
|
||||
{
|
||||
errors.Add($"Form contains duplicate field names '{fullName}'");
|
||||
continue;
|
||||
}
|
||||
|
||||
field.Value = val;
|
||||
}
|
||||
return errors.Count == 0;
|
||||
}
|
||||
|
||||
public Dictionary<string, object> GetValues()
|
||||
IEnumerable<(List<string> Path, Field Field)> GetAllFieldsCore(List<string> path, List<Field> fields)
|
||||
{
|
||||
return GetValues(Fields);
|
||||
}
|
||||
|
||||
private static Dictionary<string, object> GetValues(List<Field> fields)
|
||||
{
|
||||
var result = new Dictionary<string, object>();
|
||||
foreach (Field field in fields)
|
||||
foreach (var field in fields)
|
||||
{
|
||||
var name = field.Name ?? string.Empty;
|
||||
if (field.Fields.Any())
|
||||
List<string> thisPath = new(path.Count + 1);
|
||||
thisPath.AddRange(path);
|
||||
if (!string.IsNullOrEmpty(field.Name))
|
||||
{
|
||||
var values = GetValues(fields);
|
||||
values.Remove(string.Empty, out var keylessValue);
|
||||
|
||||
result.TryAdd(name, values);
|
||||
thisPath.Add(field.Name);
|
||||
yield return (thisPath, field);
|
||||
}
|
||||
|
||||
if (keylessValue is not Dictionary<string, object> dict) continue;
|
||||
foreach (KeyValuePair<string,object> keyValuePair in dict)
|
||||
foreach (var child in field.Fields)
|
||||
{
|
||||
if (field.Constant)
|
||||
child.Constant = true;
|
||||
foreach (var descendant in GetAllFieldsCore(thisPath, field.Fields))
|
||||
{
|
||||
result.TryAdd(keyValuePair.Key, keyValuePair.Value);
|
||||
yield return descendant;
|
||||
}
|
||||
}
|
||||
else
|
||||
}
|
||||
}
|
||||
|
||||
public void ApplyValuesFromForm(IEnumerable<KeyValuePair<string, StringValues>> form)
|
||||
{
|
||||
var values = form.GroupBy(f => f.Key, f => f.Value).ToDictionary(g => g.Key, g => g.First());
|
||||
foreach (var f in GetAllFields())
|
||||
{
|
||||
if (f.Field.Constant || !values.TryGetValue(f.FullName, out var val))
|
||||
continue;
|
||||
|
||||
f.Field.Value = val;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetValues(JObject values)
|
||||
{
|
||||
var fields = GetAllFields().ToDictionary(k => k.FullName, k => k.Field);
|
||||
SetValues(fields, new List<string>(), values);
|
||||
}
|
||||
|
||||
private void SetValues(Dictionary<string, Field> fields, List<string> path, JObject values)
|
||||
{
|
||||
foreach (var prop in values.Properties())
|
||||
{
|
||||
List<string> propPath = new List<string>(path.Count + 1);
|
||||
propPath.AddRange(path);
|
||||
propPath.Add(prop.Name);
|
||||
if (prop.Value.Type == JTokenType.Object)
|
||||
{
|
||||
result.TryAdd(name, field.Value);
|
||||
SetValues(fields, propPath, (JObject)prop.Value);
|
||||
}
|
||||
else if (prop.Value.Type == JTokenType.String)
|
||||
{
|
||||
var fullName = string.Join('_', propPath.Where(s => !string.IsNullOrEmpty(s)));
|
||||
if (fields.TryGetValue(fullName, out var f) && !f.Constant)
|
||||
f.Value = prop.Value.Value<string>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
public JObject GetValues()
|
||||
{
|
||||
var r = new JObject();
|
||||
foreach (var f in GetAllFields())
|
||||
{
|
||||
var node = r;
|
||||
for (int i = 0; i < f.Path.Count - 1; i++)
|
||||
{
|
||||
var p = f.Path[i];
|
||||
var child = node[p] as JObject;
|
||||
if (child is null)
|
||||
{
|
||||
child = new JObject();
|
||||
node[p] = child;
|
||||
}
|
||||
node = child;
|
||||
}
|
||||
node[f.Field.Name] = f.Field.Value;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
}
|
||||
|
@ -8,18 +8,52 @@ namespace BTCPayServer.Abstractions.Models
|
||||
{
|
||||
public abstract class BaseBTCPayServerPlugin : IBTCPayServerPlugin
|
||||
{
|
||||
public abstract string Identifier { get; }
|
||||
public abstract string Name { get; }
|
||||
public virtual string Identifier
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetType().GetTypeInfo().Assembly.GetName().Name;
|
||||
}
|
||||
}
|
||||
public virtual string Name
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetType().GetTypeInfo().Assembly
|
||||
.GetCustomAttribute<AssemblyProductAttribute>()?
|
||||
.Product ?? "???";
|
||||
}
|
||||
}
|
||||
|
||||
public virtual Version Version
|
||||
{
|
||||
get
|
||||
{
|
||||
return Assembly.GetAssembly(GetType())?.GetName().Version ?? new Version(1, 0, 0, 0);
|
||||
return GetVersion(GetType().GetTypeInfo().Assembly
|
||||
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
|
||||
.InformationalVersion) ??
|
||||
Assembly.GetAssembly(GetType())?.GetName()?.Version ??
|
||||
new Version(1, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
public abstract string Description { get; }
|
||||
private static Version GetVersion(string informationalVersion)
|
||||
{
|
||||
if (informationalVersion is null)
|
||||
return null;
|
||||
Version.TryParse(informationalVersion, out var r);
|
||||
return r;
|
||||
}
|
||||
|
||||
public virtual string Description
|
||||
{
|
||||
get
|
||||
{
|
||||
return GetType().GetTypeInfo().Assembly
|
||||
.GetCustomAttribute<AssemblyDescriptionAttribute>()?
|
||||
.Description ?? string.Empty;
|
||||
}
|
||||
}
|
||||
public bool SystemPlugin { get; set; }
|
||||
public virtual IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } = Array.Empty<IBTCPayServerPlugin.PluginDependency>();
|
||||
|
||||
|
@ -8,7 +8,7 @@ public class AuthorizationFilterHandle
|
||||
public AuthorizationHandlerContext Context { get; }
|
||||
public PolicyRequirement Requirement { get; }
|
||||
public HttpContext HttpContext { get; }
|
||||
public bool Success { get; private set; }
|
||||
public bool Success { get; private set; }
|
||||
|
||||
public AuthorizationFilterHandle(
|
||||
AuthorizationHandlerContext context,
|
||||
|
@ -114,6 +114,11 @@ namespace BTCPayServer.Security
|
||||
_Policies.Add(policy);
|
||||
}
|
||||
|
||||
public void UnsafeEval()
|
||||
{
|
||||
Add("script-src", "'unsafe-eval'");
|
||||
}
|
||||
|
||||
public IEnumerable<ConsentSecurityPolicy> Rules => _Policies;
|
||||
public bool HasRules => _Policies.Count != 0;
|
||||
|
||||
|
@ -23,11 +23,20 @@ public class SVGUse : UrlResolutionTagHelper2
|
||||
{
|
||||
_fileVersionProvider = fileVersionProvider;
|
||||
}
|
||||
|
||||
public override void Process(TagHelperContext context, TagHelperOutput output)
|
||||
{
|
||||
var attr = output.Attributes["href"].Value.ToString();
|
||||
attr = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, attr);
|
||||
var symbolIndex = attr!.IndexOf("#", StringComparison.InvariantCulture);
|
||||
var start = attr.IndexOf("~", StringComparison.InvariantCulture) + 1;
|
||||
var length = (symbolIndex != -1 ? symbolIndex : attr.Length) - start;
|
||||
var filePath = attr.Substring(start, length);
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
var versioned = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, filePath);
|
||||
attr = attr.Replace(filePath, versioned);
|
||||
}
|
||||
output.Attributes.SetAttribute("href", attr);
|
||||
base.Process(context, output);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,8 +28,8 @@
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.17" />
|
||||
<PackageReference Include="NBitcoin" Version="7.0.20" />
|
||||
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.21" />
|
||||
<PackageReference Include="NBitcoin" Version="7.0.24" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
@ -1,4 +1,5 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Net.Http;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
@ -22,6 +23,15 @@ namespace BTCPayServer.Client
|
||||
return await HandleResponse<ApiKeyData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<ApiKeyData> CreateAPIKey(string userId, CreateApiKeyRequest request, CancellationToken token = default)
|
||||
{
|
||||
if (request == null)
|
||||
throw new ArgumentNullException(nameof(request));
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{userId}/api-keys",
|
||||
bodyPayload: request, method: HttpMethod.Post), token);
|
||||
return await HandleResponse<ApiKeyData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task RevokeCurrentAPIKeyInfo(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/api-keys/current", null, HttpMethod.Delete), token);
|
||||
@ -35,5 +45,14 @@ namespace BTCPayServer.Client
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/api-keys/{apikey}", null, HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
public virtual async Task RevokeAPIKey(string userId, string apikey, CancellationToken token = default)
|
||||
{
|
||||
if (apikey == null)
|
||||
throw new ArgumentNullException(nameof(apikey));
|
||||
if (userId is null)
|
||||
throw new ArgumentNullException(nameof(userId));
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{userId}/api-keys/{apikey}", null, HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,7 @@ namespace BTCPayServer.Client
|
||||
method: HttpMethod.Post), token);
|
||||
return await HandleResponse<PointOfSaleAppData>(response);
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<CrowdfundAppData> CreateCrowdfundApp(string storeId,
|
||||
CreateCrowdfundAppRequest request, CancellationToken token = default)
|
||||
{
|
||||
@ -51,6 +51,44 @@ namespace BTCPayServer.Client
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<AppDataBase>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<AppDataBase[]> GetAllApps(string storeId, CancellationToken token = default)
|
||||
{
|
||||
if (storeId == null)
|
||||
throw new ArgumentNullException(nameof(storeId));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/apps",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<AppDataBase[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<AppDataBase[]> GetAllApps(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/apps",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<AppDataBase[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<PointOfSaleAppData> GetPosApp(string appId, CancellationToken token = default)
|
||||
{
|
||||
if (appId == null)
|
||||
throw new ArgumentNullException(nameof(appId));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/apps/pos/{appId}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<PointOfSaleAppData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<CrowdfundAppData> GetCrowdfundApp(string appId, CancellationToken token = default)
|
||||
{
|
||||
if (appId == null)
|
||||
throw new ArgumentNullException(nameof(appId));
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/apps/crowdfund/{appId}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<CrowdfundAppData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task DeleteApp(string appId, CancellationToken token = default)
|
||||
{
|
||||
|
@ -50,7 +50,7 @@ namespace BTCPayServer.Client
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<DepositAddressData> GetDepositAddress(string storeId, string accountId, string paymentMethod, CancellationToken token = default)
|
||||
public virtual async Task<DepositAddressData> GetCustodianAccountDepositAddress(string storeId, string accountId, string paymentMethod, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/addresses/{paymentMethod}"), token);
|
||||
return await HandleResponse<DepositAddressData>(response);
|
||||
@ -58,7 +58,6 @@ namespace BTCPayServer.Client
|
||||
|
||||
public virtual async Task<MarketTradeResponseData> MarketTradeCustodianAccountAsset(string storeId, string accountId, TradeRequestData request, CancellationToken token = default)
|
||||
{
|
||||
|
||||
//var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/users", null, request, HttpMethod.Post), token);
|
||||
//return await HandleResponse<ApplicationUserData>(response);
|
||||
var internalRequest = CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/market", null,
|
||||
@ -67,13 +66,13 @@ namespace BTCPayServer.Client
|
||||
return await HandleResponse<MarketTradeResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<MarketTradeResponseData> GetTradeInfo(string storeId, string accountId, string tradeId, CancellationToken token = default)
|
||||
public virtual async Task<MarketTradeResponseData> GetCustodianAccountTradeInfo(string storeId, string accountId, string tradeId, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/{tradeId}", method: HttpMethod.Get), token);
|
||||
return await HandleResponse<MarketTradeResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<TradeQuoteResponseData> GetTradeQuote(string storeId, string accountId, string fromAsset, string toAsset, CancellationToken token = default)
|
||||
public virtual async Task<TradeQuoteResponseData> GetCustodianAccountTradeQuote(string storeId, string accountId, string fromAsset, string toAsset, CancellationToken token = default)
|
||||
{
|
||||
var queryPayload = new Dictionary<string, object>();
|
||||
queryPayload.Add("fromAsset", fromAsset);
|
||||
@ -82,13 +81,19 @@ namespace BTCPayServer.Client
|
||||
return await HandleResponse<TradeQuoteResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<WithdrawalResponseData> CreateWithdrawal(string storeId, string accountId, WithdrawRequestData request, CancellationToken token = default)
|
||||
public virtual async Task<WithdrawalResponseData> CreateCustodianAccountWithdrawal(string storeId, string accountId, WithdrawRequestData request, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals", bodyPayload: request, method: HttpMethod.Post), token);
|
||||
return await HandleResponse<WithdrawalResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<WithdrawalSimulationResponseData> SimulateCustodianAccountWithdrawal(string storeId, string accountId, WithdrawRequestData request, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals/simulation", bodyPayload: request, method: HttpMethod.Post), token);
|
||||
return await HandleResponse<WithdrawalSimulationResponseData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<WithdrawalResponseData> GetWithdrawalInfo(string storeId, string accountId, string paymentMethod, string withdrawalId, CancellationToken token = default)
|
||||
public virtual async Task<WithdrawalResponseData> GetCustodianAccountWithdrawalInfo(string storeId, string accountId, string paymentMethod, string withdrawalId, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals/{paymentMethod}/{withdrawalId}", method: HttpMethod.Get), token);
|
||||
return await HandleResponse<WithdrawalResponseData>(response);
|
||||
|
@ -17,7 +17,7 @@ namespace BTCPayServer.Client
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningNodeInformationData>(response);
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<LightningNodeBalanceData> GetLightningNodeBalance(string cryptoCode,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
@ -95,7 +95,7 @@ namespace BTCPayServer.Client
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningInvoiceData>(response);
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<LightningInvoiceData[]> GetLightningInvoices(string cryptoCode,
|
||||
bool? pendingOnly = null, long? offsetIndex = null, CancellationToken token = default)
|
||||
{
|
||||
@ -113,6 +113,24 @@ namespace BTCPayServer.Client
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/invoices", queryPayload), token);
|
||||
return await HandleResponse<LightningInvoiceData[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningPaymentData[]> GetLightningPayments(string cryptoCode,
|
||||
bool? includePending = null, long? offsetIndex = null, CancellationToken token = default)
|
||||
{
|
||||
var queryPayload = new Dictionary<string, object>();
|
||||
if (includePending is bool v)
|
||||
{
|
||||
queryPayload.Add("includePending", v.ToString());
|
||||
}
|
||||
if (offsetIndex is > 0)
|
||||
{
|
||||
queryPayload.Add("offsetIndex", offsetIndex);
|
||||
}
|
||||
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/payments", queryPayload), token);
|
||||
return await HandleResponse<LightningPaymentData[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string cryptoCode, CreateLightningInvoiceRequest request,
|
||||
CancellationToken token = default)
|
||||
|
@ -17,7 +17,7 @@ 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)
|
||||
{
|
||||
@ -97,7 +97,7 @@ namespace BTCPayServer.Client
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningInvoiceData>(response);
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<LightningInvoiceData[]> GetLightningInvoices(string storeId, string cryptoCode,
|
||||
bool? pendingOnly = null, long? offsetIndex = null, CancellationToken token = default)
|
||||
{
|
||||
@ -115,6 +115,24 @@ namespace BTCPayServer.Client
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/invoices", queryPayload), token);
|
||||
return await HandleResponse<LightningInvoiceData[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningPaymentData[]> GetLightningPayments(string storeId, string cryptoCode,
|
||||
bool? includePending = null, long? offsetIndex = null, CancellationToken token = default)
|
||||
{
|
||||
var queryPayload = new Dictionary<string, object>();
|
||||
if (includePending is bool v)
|
||||
{
|
||||
queryPayload.Add("includePending", v.ToString());
|
||||
}
|
||||
if (offsetIndex is > 0)
|
||||
{
|
||||
queryPayload.Add("offsetIndex", offsetIndex);
|
||||
}
|
||||
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/payments", queryPayload), token);
|
||||
return await HandleResponse<LightningPaymentData[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string storeId, string cryptoCode,
|
||||
CreateLightningInvoiceRequest request, CancellationToken token = default)
|
||||
|
48
BTCPayServer.Client/BTCPayServerClient.LightningAddresses.cs
Normal file
48
BTCPayServer.Client/BTCPayServerClient.LightningAddresses.cs
Normal file
@ -0,0 +1,48 @@
|
||||
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<LightningAddressData[]> GetStoreLightningAddresses(string storeId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningAddressData[]>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningAddressData> GetStoreLightningAddress(string storeId, string username,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses/{username}",
|
||||
method: HttpMethod.Get), token);
|
||||
return await HandleResponse<LightningAddressData>(response);
|
||||
}
|
||||
|
||||
public virtual async Task RemoveStoreLightningAddress(string storeId, string username,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses/{username}",
|
||||
method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<LightningAddressData> AddOrUpdateStoreLightningAddress(string storeId,
|
||||
string username, LightningAddressData data,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses/{username}",
|
||||
method: HttpMethod.Post, bodyPayload: data), token);
|
||||
|
||||
return await HandleResponse<LightningAddressData>(response);
|
||||
}
|
||||
}
|
||||
}
|
@ -39,7 +39,7 @@ namespace BTCPayServer.Client
|
||||
parameters.Add("includeNeighbourData", v);
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", parameters, method:HttpMethod.Get), token);
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", parameters, method: HttpMethod.Get), token);
|
||||
return await HandleResponse<OnChainWalletObjectData[]>(response);
|
||||
}
|
||||
public virtual async Task RemoveOnChainWalletObject(string storeId, string cryptoCode, OnChainWalletObjectId objectId,
|
||||
@ -47,7 +47,7 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}", method:HttpMethod.Delete), token);
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}", method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
public virtual async Task<OnChainWalletObjectData> AddOrUpdateOnChainWalletObject(string storeId, string cryptoCode, AddOnChainWalletObjectRequest request,
|
||||
@ -55,7 +55,7 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", method:HttpMethod.Post, bodyPayload: request), token);
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", method: HttpMethod.Post, bodyPayload: request), token);
|
||||
return await HandleResponse<OnChainWalletObjectData>(response);
|
||||
}
|
||||
public virtual async Task AddOrUpdateOnChainWalletLink(string storeId, string cryptoCode,
|
||||
@ -65,7 +65,7 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links", method:HttpMethod.Post, bodyPayload: request), token);
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links", method: HttpMethod.Post, bodyPayload: request), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
public virtual async Task RemoveOnChainWalletLinks(string storeId, string cryptoCode,
|
||||
@ -75,7 +75,7 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
var response =
|
||||
await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links/{link.Type}/{link.Id}", method:HttpMethod.Delete), token);
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links/{link.Type}/{link.Id}", method: HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
}
|
||||
|
@ -63,7 +63,8 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
query.Add(nameof(statusFilter), statusFilter);
|
||||
}
|
||||
if (labelFilter != null) {
|
||||
if (labelFilter != null)
|
||||
{
|
||||
query.Add(nameof(labelFilter), labelFilter);
|
||||
}
|
||||
var response =
|
||||
|
@ -52,17 +52,17 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}/payouts", bodyPayload: payoutRequest, method: HttpMethod.Post), cancellationToken);
|
||||
return await HandleResponse<PayoutData>(response);
|
||||
}
|
||||
}
|
||||
public virtual async Task<PayoutData> GetPullPaymentPayout(string pullPaymentId, string payoutId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}/payouts/{payoutId}", method: HttpMethod.Get), cancellationToken);
|
||||
return await HandleResponse<PayoutData>(response);
|
||||
}
|
||||
}
|
||||
public virtual async Task<PayoutData> GetStorePayout(string storeId, string payoutId, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payouts/{payoutId}", method: HttpMethod.Get), cancellationToken);
|
||||
return await HandleResponse<PayoutData>(response);
|
||||
}
|
||||
}
|
||||
public virtual async Task<PayoutData> CreatePayout(string storeId, CreatePayoutThroughStoreRequest payoutRequest, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payouts", bodyPayload: payoutRequest, method: HttpMethod.Post), cancellationToken);
|
||||
@ -97,5 +97,15 @@ namespace BTCPayServer.Client
|
||||
method: HttpMethod.Post, bodyPayload: request), cancellationToken);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
public virtual async Task<PullPaymentLNURL> GetPullPaymentLNURL(string pullPaymentId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest(
|
||||
$"/api/v1/pull-payments/{pullPaymentId}/lnurl",
|
||||
method: HttpMethod.Get), cancellationToken);
|
||||
return await HandleResponse<PullPaymentLNURL>(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
public partial class BTCPayServerClient
|
||||
{
|
||||
public virtual async Task<IEnumerable<PayoutProcessorData>> GetPayoutProcessors(string storeId,
|
||||
public virtual async Task<IEnumerable<PayoutProcessorData>> GetPayoutProcessors(string storeId,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors"), token);
|
||||
@ -20,28 +20,28 @@ namespace BTCPayServer.Client
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/{processor}/{paymentMethod}", null, HttpMethod.Delete), token);
|
||||
await HandleResponse(response);
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<IEnumerable<LightningAutomatedPayoutSettings>> GetStoreLightningAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory{(paymentMethod is null? string.Empty: $"/{paymentMethod}")}"), token);
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory{(paymentMethod is null ? string.Empty : $"/{paymentMethod}")}"), token);
|
||||
return await HandleResponse<IEnumerable<LightningAutomatedPayoutSettings>>(response);
|
||||
}
|
||||
public virtual async Task<LightningAutomatedPayoutSettings> UpdateStoreLightningAutomatedPayoutProcessors(string storeId, string paymentMethod,LightningAutomatedPayoutSettings request, CancellationToken token = default)
|
||||
public virtual async Task<LightningAutomatedPayoutSettings> UpdateStoreLightningAutomatedPayoutProcessors(string storeId, string paymentMethod, LightningAutomatedPayoutSettings request, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory/{paymentMethod}",null, request, HttpMethod.Put ), token);
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory/{paymentMethod}", null, request, HttpMethod.Put), token);
|
||||
return await HandleResponse<LightningAutomatedPayoutSettings>(response);
|
||||
}
|
||||
public virtual async Task<OnChainAutomatedPayoutSettings> UpdateStoreOnChainAutomatedPayoutProcessors(string storeId, string paymentMethod,OnChainAutomatedPayoutSettings request, CancellationToken token = default)
|
||||
public virtual async Task<OnChainAutomatedPayoutSettings> UpdateStoreOnChainAutomatedPayoutProcessors(string storeId, string paymentMethod, OnChainAutomatedPayoutSettings request, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory/{paymentMethod}",null, request, HttpMethod.Put ), token);
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory/{paymentMethod}", null, request, HttpMethod.Put), token);
|
||||
return await HandleResponse<OnChainAutomatedPayoutSettings>(response);
|
||||
}
|
||||
|
||||
|
||||
public virtual async Task<IEnumerable<OnChainAutomatedPayoutSettings>> GetStoreOnChainAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory{(paymentMethod is null? string.Empty: $"/{paymentMethod}")}"), token);
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory{(paymentMethod is null ? string.Empty : $"/{paymentMethod}")}"), token);
|
||||
return await HandleResponse<IEnumerable<OnChainAutomatedPayoutSettings>>(response);
|
||||
}
|
||||
}
|
||||
|
@ -37,17 +37,28 @@ namespace BTCPayServer.Client
|
||||
return await HandleResponse<StoreRateConfiguration>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<List<StoreRatePreviewResult>> PreviewUpdateStoreRateConfiguration(string storeId,
|
||||
public virtual async Task<List<StoreRateResult>> PreviewUpdateStoreRateConfiguration(string storeId,
|
||||
StoreRateConfiguration request,
|
||||
string[] currencyPair,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/rates/configuration/preview", bodyPayload: request,
|
||||
queryPayload: new Dictionary<string, object>() {{"currencyPair", currencyPair}},
|
||||
queryPayload: new Dictionary<string, object>() { { "currencyPair", currencyPair } },
|
||||
method: HttpMethod.Post),
|
||||
token);
|
||||
return await HandleResponse<List<StoreRatePreviewResult>>(response);
|
||||
return await HandleResponse<List<StoreRateResult>>(response);
|
||||
}
|
||||
|
||||
public virtual async Task<List<StoreRateResult>> GetStoreRates(string storeId, string[] currencyPair,
|
||||
CancellationToken token = default)
|
||||
{
|
||||
using var response = await _httpClient.SendAsync(
|
||||
CreateHttpRequest($"api/v1/stores/{storeId}/rates",
|
||||
queryPayload: new Dictionary<string, object>() { { "currencyPair", currencyPair } },
|
||||
method: HttpMethod.Get),
|
||||
token);
|
||||
return await HandleResponse<List<StoreRateResult>>(response);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -36,12 +36,12 @@ namespace BTCPayServer.Client
|
||||
public virtual async Task<bool> LockUser(string idOrEmail, bool locked, CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{idOrEmail}/lock", null,
|
||||
new LockUserRequest {Locked = locked}, HttpMethod.Post), token);
|
||||
new LockUserRequest { Locked = locked }, HttpMethod.Post), token);
|
||||
await HandleResponse(response);
|
||||
return response.IsSuccessStatusCode;
|
||||
}
|
||||
|
||||
public virtual async Task<ApplicationUserData[]> GetUsers( CancellationToken token = default)
|
||||
public virtual async Task<ApplicationUserData[]> GetUsers(CancellationToken token = default)
|
||||
{
|
||||
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/", null, HttpMethod.Get), token);
|
||||
return await HandleResponse<ApplicationUserData[]>(response);
|
||||
|
@ -0,0 +1,29 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Lightning;
|
||||
using NBitcoin.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client.JsonConverters
|
||||
{
|
||||
public class TradeQuantityJsonConverter : JsonConverter<TradeQuantity>
|
||||
{
|
||||
public override TradeQuantity ReadJson(JsonReader reader, Type objectType, TradeQuantity existingValue, bool hasExistingValue, JsonSerializer serializer)
|
||||
{
|
||||
if (reader.TokenType == JsonToken.Null)
|
||||
return null;
|
||||
if (reader.TokenType != JsonToken.String)
|
||||
throw new JsonObjectException("Invalid TradeQuantity, expected string. Expected: \"1.50\" or \"50%\"", reader);
|
||||
if (TradeQuantity.TryParse((string)reader.Value, out var q))
|
||||
return q;
|
||||
throw new JsonObjectException("Invalid format for TradeQuantity. Expected: \"1.50\" or \"50%\"", reader);
|
||||
}
|
||||
|
||||
public override void WriteJson(JsonWriter writer, TradeQuantity value, JsonSerializer serializer)
|
||||
{
|
||||
if (value is not null)
|
||||
writer.WriteValue(value.ToString());
|
||||
}
|
||||
}
|
||||
}
|
@ -8,7 +8,7 @@ public class AssetPairData
|
||||
public AssetPairData()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
public AssetPairData(string assetBought, string assetSold, decimal minimumTradeQty)
|
||||
{
|
||||
AssetBought = assetBought;
|
||||
@ -25,7 +25,7 @@ public class AssetPairData
|
||||
[JsonProperty]
|
||||
public decimal MinimumTradeQty { set; get; }
|
||||
|
||||
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return AssetBought + "/" + AssetSold;
|
||||
|
@ -11,14 +11,14 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
public CreateLightningInvoiceRequest(LightMoney amount, string description, TimeSpan expiry)
|
||||
{
|
||||
Amount = amount;
|
||||
Description = description;
|
||||
Expiry = expiry;
|
||||
}
|
||||
|
||||
|
||||
[JsonConverter(typeof(JsonConverters.LightMoneyJsonConverter))]
|
||||
public LightMoney Amount { get; set; }
|
||||
public string Description { get; set; }
|
||||
|
@ -5,11 +5,11 @@ namespace BTCPayServer.Client.Models
|
||||
public abstract class CustodianAccountBaseData
|
||||
{
|
||||
public string CustodianCode { get; set; }
|
||||
|
||||
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
public string StoreId { get; set; }
|
||||
|
||||
|
||||
public JObject Config { get; set; }
|
||||
}
|
||||
|
||||
|
@ -2,13 +2,13 @@ using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class CustodianAccountResponse: CustodianAccountData
|
||||
public class CustodianAccountResponse : CustodianAccountData
|
||||
{
|
||||
public IDictionary<string, decimal> AssetBalances { get; set; }
|
||||
|
||||
public CustodianAccountResponse()
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -9,5 +9,5 @@ public class CustodianData
|
||||
public Dictionary<string, AssetPairData> TradableAssetPairs { get; set; }
|
||||
public string[] WithdrawablePaymentMethods { get; set; }
|
||||
public string[] DepositablePaymentMethods { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
@ -6,10 +6,10 @@ public class DepositAddressData
|
||||
// * Example: P2PKH, P2SH, P2WPKH, P2TR, BOLT11, ...
|
||||
// */
|
||||
// public string Type { get; set; }
|
||||
|
||||
|
||||
/**
|
||||
* Format depends hugely on the type.
|
||||
*/
|
||||
public string Address { get; set; }
|
||||
|
||||
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
using BTCPayServer.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Converters;
|
||||
|
||||
@ -6,6 +7,7 @@ namespace BTCPayServer.Client.Models;
|
||||
public class LedgerEntryData
|
||||
{
|
||||
public string Asset { get; }
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal Qty { get; }
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
|
10
BTCPayServer.Client/Models/LightningAddressData.cs
Normal file
10
BTCPayServer.Client/Models/LightningAddressData.cs
Normal file
@ -0,0 +1,10 @@
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class LightningAddressData
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string CurrencyCode { get; set; }
|
||||
public decimal? Min { get; set; }
|
||||
public decimal? Max { get; set; }
|
||||
|
||||
}
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using BTCPayServer.Client.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@ -7,7 +7,7 @@ namespace BTCPayServer.Client.Models;
|
||||
public class LightningAutomatedPayoutSettings
|
||||
{
|
||||
public string PaymentMethod { get; set; }
|
||||
|
||||
|
||||
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
||||
public TimeSpan IntervalSeconds { get; set; }
|
||||
}
|
||||
|
@ -16,9 +16,15 @@ namespace BTCPayServer.Client.Models
|
||||
|
||||
[JsonProperty("BOLT11")]
|
||||
public string BOLT11 { get; set; }
|
||||
|
||||
public string PaymentHash { get; set; }
|
||||
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public string Preimage { get; set; }
|
||||
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset? PaidAt { get; set; }
|
||||
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset ExpiresAt { get; set; }
|
||||
|
||||
|
@ -9,10 +9,10 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
[JsonProperty("onchain")]
|
||||
public OnchainBalanceData OnchainBalance { get; set; }
|
||||
|
||||
|
||||
[JsonProperty("offchain")]
|
||||
public OffchainBalanceData OffchainBalance { get; set; }
|
||||
|
||||
|
||||
public LightningNodeBalanceData()
|
||||
{
|
||||
}
|
||||
@ -31,7 +31,7 @@ namespace BTCPayServer.Client.Models
|
||||
|
||||
[JsonConverter(typeof(JsonConverters.MoneyJsonConverter))]
|
||||
public Money Unconfirmed { get; set; }
|
||||
|
||||
|
||||
[JsonConverter(typeof(JsonConverters.MoneyJsonConverter))]
|
||||
public Money Reserved { get; set; }
|
||||
}
|
||||
@ -40,13 +40,13 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
[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; }
|
||||
}
|
||||
|
@ -17,12 +17,12 @@ namespace BTCPayServer.Client.Models
|
||||
|
||||
[JsonProperty("BOLT11")]
|
||||
public string BOLT11 { get; set; }
|
||||
|
||||
|
||||
public string Preimage { get; set; }
|
||||
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset? CreatedAt { get; set; }
|
||||
|
||||
|
||||
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
||||
public LightMoney TotalAmount { get; set; }
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
namespace BTCPayServer.Client;
|
||||
namespace BTCPayServer.Client;
|
||||
|
||||
public class LockUserRequest
|
||||
{
|
||||
|
@ -16,7 +16,7 @@ public class MarketTradeResponseData
|
||||
public string TradeId { get; }
|
||||
|
||||
public string AccountId { get; }
|
||||
|
||||
|
||||
public string CustodianCode { get; }
|
||||
|
||||
public MarketTradeResponseData(string fromAsset, string toAsset, List<LedgerEntryData> ledgerEntries, string tradeId, string accountId, string custodianCode)
|
||||
|
@ -6,6 +6,8 @@ namespace BTCPayServer.Client.Models
|
||||
public class NotificationData
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Identifier { get; set; }
|
||||
public string Type { get; set; }
|
||||
public string Body { get; set; }
|
||||
public bool Seen { get; set; }
|
||||
public Uri Link { get; set; }
|
||||
|
@ -1,4 +1,4 @@
|
||||
using System;
|
||||
using System;
|
||||
using BTCPayServer.Client.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
@ -7,9 +7,9 @@ namespace BTCPayServer.Client.Models;
|
||||
public class OnChainAutomatedPayoutSettings
|
||||
{
|
||||
public string PaymentMethod { get; set; }
|
||||
|
||||
|
||||
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
||||
public TimeSpan IntervalSeconds { get; set; }
|
||||
|
||||
public int? FeeBlockTarget { get; set; }
|
||||
public int? FeeBlockTarget { get; set; }
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
[JsonConverter(typeof(NodeUriJsonConverter))]
|
||||
[JsonProperty("nodeURI")]
|
||||
public NodeInfo NodeURI { get; set; }
|
||||
public BTCPayServer.Lightning.NodeInfo NodeURI { get; set; }
|
||||
[JsonConverter(typeof(MoneyJsonConverter))]
|
||||
public Money ChannelAmount { get; set; }
|
||||
|
||||
|
@ -11,13 +11,13 @@ namespace BTCPayServer.Client.Models
|
||||
{
|
||||
[JsonProperty("BOLT11")]
|
||||
public string BOLT11 { get; set; }
|
||||
|
||||
|
||||
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
|
||||
public float? MaxFeePercent { get; set; }
|
||||
|
||||
|
||||
[JsonConverter(typeof(MoneyJsonConverter))]
|
||||
public Money MaxFeeFlat { get; set; }
|
||||
|
||||
|
||||
[JsonConverter(typeof(LightMoneyJsonConverter))]
|
||||
public LightMoney Amount { get; set; }
|
||||
|
||||
|
13
BTCPayServer.Client/Models/PaymentMethodCriteriaData.cs
Normal file
13
BTCPayServer.Client/Models/PaymentMethodCriteriaData.cs
Normal file
@ -0,0 +1,13 @@
|
||||
using BTCPayServer.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class PaymentMethodCriteriaData
|
||||
{
|
||||
public string PaymentMethod { get; set; }
|
||||
public string CurrencyCode { get; set; }
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal Amount { get; set; }
|
||||
public bool Above { get; set; }
|
||||
}
|
@ -12,14 +12,56 @@ namespace BTCPayServer.Client.Models
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset Created { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class PointOfSaleAppData : AppDataBase
|
||||
{
|
||||
// We can add POS specific things here later
|
||||
public string Title { get; set; }
|
||||
public string DefaultView { get; set; }
|
||||
public bool ShowCustomAmount { get; set; }
|
||||
public bool ShowDiscount { get; set; }
|
||||
public bool EnableTips { get; set; }
|
||||
public string Currency { get; set; }
|
||||
public object Items { get; set; }
|
||||
public string FixedAmountPayButtonText { get; set; }
|
||||
public string CustomAmountPayButtonText { get; set; }
|
||||
public string TipText { get; set; }
|
||||
public string CustomCSSLink { get; set; }
|
||||
public string NotificationUrl { get; set; }
|
||||
public string RedirectUrl { get; set; }
|
||||
public string Description { get; set; }
|
||||
public string EmbeddedCSS { get; set; }
|
||||
public bool? RedirectAutomatically { get; set; }
|
||||
public bool? RequiresRefundEmail { get; set; }
|
||||
}
|
||||
|
||||
public class CrowdfundAppData : AppDataBase
|
||||
{
|
||||
// We can add Crowdfund specific things here later
|
||||
public string Title { get; set; }
|
||||
public bool Enabled { get; set; }
|
||||
public bool EnforceTargetAmount { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset? StartDate { get; set; }
|
||||
public string TargetCurrency { get; set; }
|
||||
public string Description { get; set; }
|
||||
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
|
||||
public DateTimeOffset? EndDate { get; set; }
|
||||
public decimal? TargetAmount { get; set; }
|
||||
public string CustomCSSLink { get; set; }
|
||||
public string MainImageUrl { get; set; }
|
||||
public string EmbeddedCSS { get; set; }
|
||||
public string NotificationUrl { get; set; }
|
||||
public string Tagline { get; set; }
|
||||
public object Perks { get; set; }
|
||||
public bool DisqusEnabled { get; set; }
|
||||
public string DisqusShortname { get; set; }
|
||||
public bool SoundsEnabled { get; set; }
|
||||
public bool AnimationsEnabled { get; set; }
|
||||
public int ResetEveryAmount { get; set; }
|
||||
public string ResetEvery { get; set; }
|
||||
public bool DisplayPerksValue { get; set; }
|
||||
public bool DisplayPerksRanking { get; set; }
|
||||
public bool SortPerksByPopularity { get; set; }
|
||||
public string[] Sounds { get; set; }
|
||||
public string[] AnimationColors { get; set; }
|
||||
}
|
||||
}
|
||||
|
8
BTCPayServer.Client/Models/PullPaymentLNURL.cs
Normal file
8
BTCPayServer.Client/Models/PullPaymentLNURL.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace BTCPayServer.Client.Models
|
||||
{
|
||||
public class PullPaymentLNURL
|
||||
{
|
||||
public string LNURLBech32 { get; set; }
|
||||
public string LNURLUri { get; set; }
|
||||
}
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
namespace BTCPayServer.Client.Models;
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class RateSource
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -20,6 +20,10 @@ namespace BTCPayServer.Client.Models
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public TimeSpan InvoiceExpiration { get; set; } = TimeSpan.FromMinutes(15);
|
||||
|
||||
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public TimeSpan DisplayExpirationTimer { get; set; } = TimeSpan.FromMinutes(5);
|
||||
|
||||
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public TimeSpan MonitoringExpiration { get; set; } = TimeSpan.FromMinutes(60);
|
||||
@ -59,8 +63,11 @@ namespace BTCPayServer.Client.Models
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public NetworkFeeMode NetworkFeeMode { get; set; } = NetworkFeeMode.Never;
|
||||
|
||||
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
|
||||
public List<PaymentMethodCriteriaData> PaymentMethodCriteria { get; set; }
|
||||
|
||||
public bool PayJoinEnabled { get; set; }
|
||||
|
||||
|
||||
public InvoiceData.ReceiptOptions Receipt { get; set; }
|
||||
|
||||
|
||||
|
@ -7,7 +7,7 @@ namespace BTCPayServer.Client.Models
|
||||
/// </summary>
|
||||
public string Id { get; set; }
|
||||
}
|
||||
|
||||
|
||||
public class StoreUserData
|
||||
{
|
||||
/// <summary>
|
||||
|
@ -1,10 +0,0 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class StoreRatePreviewResult
|
||||
{
|
||||
public string CurrencyPair { get; set; }
|
||||
public decimal? Rate { get; set; }
|
||||
public List<string> Errors { get; set; }
|
||||
}
|
@ -1,7 +1,13 @@
|
||||
namespace BTCPayServer.Client.Models;
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class StoreRateResult
|
||||
{
|
||||
public string CurrencyPair { get; set; }
|
||||
public decimal Rate { get; set; }
|
||||
}
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal? Rate { get; set; }
|
||||
public List<string> Errors { get; set; }
|
||||
}
|
||||
|
@ -1,8 +1,13 @@
|
||||
using BTCPayServer.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class TradeQuoteResponseData
|
||||
{
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal Bid { get; }
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal Ask { get; }
|
||||
public string ToAsset { get; }
|
||||
public string FromAsset { get; }
|
||||
|
@ -1,13 +1,85 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Globalization;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using System.Net.Http.Headers;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class WithdrawRequestData
|
||||
{
|
||||
public string PaymentMethod { set; get; }
|
||||
public decimal Qty { set; get; }
|
||||
[JsonConverter(typeof(JsonConverters.TradeQuantityJsonConverter))]
|
||||
public TradeQuantity Qty { set; get; }
|
||||
|
||||
public WithdrawRequestData(string paymentMethod, decimal qty)
|
||||
public WithdrawRequestData()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public WithdrawRequestData(string paymentMethod, TradeQuantity qty)
|
||||
{
|
||||
PaymentMethod = paymentMethod;
|
||||
Qty = qty;
|
||||
}
|
||||
}
|
||||
|
||||
#nullable enable
|
||||
public record TradeQuantity
|
||||
{
|
||||
public TradeQuantity(decimal value, ValueType type)
|
||||
{
|
||||
Type = type;
|
||||
Value = value;
|
||||
}
|
||||
|
||||
public enum ValueType
|
||||
{
|
||||
Exact,
|
||||
Percent
|
||||
}
|
||||
|
||||
public ValueType Type { get; }
|
||||
public decimal Value { get; set; }
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Type == ValueType.Exact)
|
||||
return Value.ToString(CultureInfo.InvariantCulture);
|
||||
else
|
||||
return Value.ToString(CultureInfo.InvariantCulture) + "%";
|
||||
}
|
||||
public static TradeQuantity Parse(string str)
|
||||
{
|
||||
if (!TryParse(str, out var r))
|
||||
throw new FormatException("Invalid TradeQuantity");
|
||||
return r;
|
||||
}
|
||||
public static bool TryParse(string str, [MaybeNullWhen(false)] out TradeQuantity quantity)
|
||||
{
|
||||
if (str is null)
|
||||
throw new ArgumentNullException(nameof(str));
|
||||
quantity = null;
|
||||
str = str.Trim();
|
||||
str = str.Replace(" ", "");
|
||||
if (str.Length == 0)
|
||||
return false;
|
||||
if (str[^1] == '%')
|
||||
{
|
||||
if (!decimal.TryParse(str[..^1], NumberStyles.Any, CultureInfo.InvariantCulture, out var r))
|
||||
return false;
|
||||
if (r < 0.0m)
|
||||
return false;
|
||||
quantity = new TradeQuantity(r, TradeQuantity.ValueType.Percent);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!decimal.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out var r))
|
||||
return false;
|
||||
if (r < 0.0m)
|
||||
return false;
|
||||
quantity = new TradeQuantity(r, TradeQuantity.ValueType.Exact);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
22
BTCPayServer.Client/Models/WithdrawalBaseResponseData.cs
Normal file
22
BTCPayServer.Client/Models/WithdrawalBaseResponseData.cs
Normal file
@ -0,0 +1,22 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public abstract class WithdrawalBaseResponseData
|
||||
{
|
||||
public string Asset { get; }
|
||||
public string PaymentMethod { get; }
|
||||
public List<LedgerEntryData> LedgerEntries { get; }
|
||||
public string AccountId { get; }
|
||||
public string CustodianCode { get; }
|
||||
|
||||
public WithdrawalBaseResponseData(string paymentMethod, string asset, List<LedgerEntryData> ledgerEntries, string accountId,
|
||||
string custodianCode)
|
||||
{
|
||||
PaymentMethod = paymentMethod;
|
||||
Asset = asset;
|
||||
LedgerEntries = ledgerEntries;
|
||||
AccountId = accountId;
|
||||
CustodianCode = custodianCode;
|
||||
}
|
||||
}
|
@ -5,18 +5,13 @@ using Newtonsoft.Json.Converters;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class WithdrawalResponseData
|
||||
public class WithdrawalResponseData : WithdrawalBaseResponseData
|
||||
{
|
||||
public string Asset { get; }
|
||||
public string PaymentMethod { get; }
|
||||
public List<LedgerEntryData> LedgerEntries { get; }
|
||||
public string WithdrawalId { get; }
|
||||
public string AccountId { get; }
|
||||
public string CustodianCode { get; }
|
||||
|
||||
|
||||
[JsonConverter(typeof(StringEnumConverter))]
|
||||
public WithdrawalStatus Status { get; }
|
||||
|
||||
public string WithdrawalId { get; }
|
||||
public DateTimeOffset CreatedTime { get; }
|
||||
|
||||
public string TransactionId { get; }
|
||||
@ -24,14 +19,10 @@ public class WithdrawalResponseData
|
||||
public string TargetAddress { get; }
|
||||
|
||||
public WithdrawalResponseData(string paymentMethod, string asset, List<LedgerEntryData> ledgerEntries, string withdrawalId, string accountId,
|
||||
string custodianCode, WithdrawalStatus status, DateTimeOffset createdTime, string targetAddress, string transactionId)
|
||||
string custodianCode, WithdrawalStatus status, DateTimeOffset createdTime, string targetAddress, string transactionId) : base(paymentMethod, asset, ledgerEntries, accountId,
|
||||
custodianCode)
|
||||
{
|
||||
PaymentMethod = paymentMethod;
|
||||
Asset = asset;
|
||||
LedgerEntries = ledgerEntries;
|
||||
WithdrawalId = withdrawalId;
|
||||
AccountId = accountId;
|
||||
CustodianCode = custodianCode;
|
||||
TargetAddress = targetAddress;
|
||||
TransactionId = transactionId;
|
||||
Status = status;
|
||||
|
@ -0,0 +1,21 @@
|
||||
using System.Collections.Generic;
|
||||
using BTCPayServer.JsonConverters;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace BTCPayServer.Client.Models;
|
||||
|
||||
public class WithdrawalSimulationResponseData : WithdrawalBaseResponseData
|
||||
{
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal? MinQty { get; set; }
|
||||
[JsonConverter(typeof(NumericStringJsonConverter))]
|
||||
public decimal? MaxQty { get; set; }
|
||||
|
||||
public WithdrawalSimulationResponseData(string paymentMethod, string asset, string accountId,
|
||||
string custodianCode, List<LedgerEntryData> ledgerEntries, decimal? minQty, decimal? maxQty) : base(paymentMethod,
|
||||
asset, ledgerEntries, accountId, custodianCode)
|
||||
{
|
||||
MinQty = minQty;
|
||||
MaxQty = maxQty;
|
||||
}
|
||||
}
|
@ -6,7 +6,9 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
public class Policies
|
||||
{
|
||||
public const string CanViewLightningInvoiceInternalNode = "btcpay.server.canviewlightninginvoiceinternalnode";
|
||||
public const string CanCreateLightningInvoiceInternalNode = "btcpay.server.cancreatelightninginvoiceinternalnode";
|
||||
public const string CanViewLightningInvoiceInStore = "btcpay.store.canviewlightninginvoice";
|
||||
public const string CanCreateLightningInvoiceInStore = "btcpay.store.cancreatelightninginvoice";
|
||||
public const string CanUseInternalLightningNode = "btcpay.server.canuseinternallightningnode";
|
||||
public const string CanUseLightningNodeInStore = "btcpay.store.canuselightningnode";
|
||||
@ -26,8 +28,11 @@ namespace BTCPayServer.Client
|
||||
public const string CanViewNotificationsForUser = "btcpay.user.canviewnotificationsforuser";
|
||||
public const string CanViewUsers = "btcpay.server.canviewusers";
|
||||
public const string CanCreateUser = "btcpay.server.cancreateuser";
|
||||
public const string CanManageUsers = "btcpay.server.canmanageusers";
|
||||
public const string CanDeleteUser = "btcpay.user.candeleteuser";
|
||||
public const string CanManagePullPayments = "btcpay.store.canmanagepullpayments";
|
||||
public const string CanCreatePullPayments = "btcpay.store.cancreatepullpayments";
|
||||
public const string CanCreateNonApprovedPullPayments = "btcpay.store.cancreatenonapprovedpullpayments";
|
||||
public const string CanViewCustodianAccounts = "btcpay.store.canviewcustodianaccounts";
|
||||
public const string CanManageCustodianAccounts = "btcpay.store.canmanagecustodianaccounts";
|
||||
public const string CanDepositToCustodianAccounts = "btcpay.store.candeposittocustodianaccount";
|
||||
@ -56,15 +61,20 @@ namespace BTCPayServer.Client
|
||||
yield return CanViewNotificationsForUser;
|
||||
yield return Unrestricted;
|
||||
yield return CanUseInternalLightningNode;
|
||||
yield return CanViewLightningInvoiceInternalNode;
|
||||
yield return CanCreateLightningInvoiceInternalNode;
|
||||
yield return CanUseLightningNodeInStore;
|
||||
yield return CanViewLightningInvoiceInStore;
|
||||
yield return CanCreateLightningInvoiceInStore;
|
||||
yield return CanManagePullPayments;
|
||||
yield return CanCreatePullPayments;
|
||||
yield return CanCreateNonApprovedPullPayments;
|
||||
yield return CanViewCustodianAccounts;
|
||||
yield return CanManageCustodianAccounts;
|
||||
yield return CanDepositToCustodianAccounts;
|
||||
yield return CanWithdrawFromCustodianAccounts;
|
||||
yield return CanTradeCustodianAccount;
|
||||
yield return CanManageUsers;
|
||||
}
|
||||
}
|
||||
public static bool IsValidPolicy(string policy)
|
||||
@ -88,9 +98,45 @@ namespace BTCPayServer.Client
|
||||
{
|
||||
return policy.StartsWith("btcpay.plugin", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
public static bool IsUserPolicy(string policy)
|
||||
{
|
||||
return policy.StartsWith("btcpay.user", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
}
|
||||
|
||||
public class PermissionSet
|
||||
{
|
||||
public PermissionSet() : this(Array.Empty<Permission>())
|
||||
{
|
||||
|
||||
}
|
||||
public PermissionSet(Permission[] permissions)
|
||||
{
|
||||
Permissions = permissions;
|
||||
}
|
||||
|
||||
public Permission[] Permissions { get; }
|
||||
|
||||
public bool Contains(Permission requestedPermission)
|
||||
{
|
||||
return Permissions.Any(p => p.Contains(requestedPermission));
|
||||
}
|
||||
public bool Contains(string permission, string store)
|
||||
{
|
||||
if (permission is null)
|
||||
throw new ArgumentNullException(nameof(permission));
|
||||
if (store is null)
|
||||
throw new ArgumentNullException(nameof(store));
|
||||
return Contains(Permission.Create(permission, store));
|
||||
}
|
||||
}
|
||||
public class Permission
|
||||
{
|
||||
static Permission()
|
||||
{
|
||||
Init();
|
||||
}
|
||||
|
||||
public static Permission Create(string policy, string scope = null)
|
||||
{
|
||||
if (TryCreatePermission(policy, scope, out var r))
|
||||
@ -106,7 +152,7 @@ namespace BTCPayServer.Client
|
||||
policy = policy.Trim().ToLowerInvariant();
|
||||
if (!Policies.IsValidPolicy(policy))
|
||||
return false;
|
||||
if (scope != null && !Policies.IsStorePolicy(policy))
|
||||
if (!string.IsNullOrEmpty(scope) && !Policies.IsStorePolicy(policy))
|
||||
return false;
|
||||
permission = new Permission(policy, scope);
|
||||
return true;
|
||||
@ -159,7 +205,7 @@ namespace BTCPayServer.Client
|
||||
}
|
||||
if (!Policies.IsStorePolicy(subpermission.Policy))
|
||||
return true;
|
||||
return Scope == null || subpermission.Scope == this.Scope;
|
||||
return Scope == null || subpermission.Scope == Scope;
|
||||
}
|
||||
|
||||
public static IEnumerable<Permission> ToPermissions(string[] permissions)
|
||||
@ -175,35 +221,61 @@ namespace BTCPayServer.Client
|
||||
|
||||
private bool ContainsPolicy(string subpolicy)
|
||||
{
|
||||
if (this.Policy == Policies.Unrestricted)
|
||||
return ContainsPolicy(Policy, subpolicy);
|
||||
}
|
||||
|
||||
private static bool ContainsPolicy(string policy, string subpolicy)
|
||||
{
|
||||
if (policy == Policies.Unrestricted)
|
||||
return true;
|
||||
if (this.Policy == subpolicy)
|
||||
if (policy == subpolicy)
|
||||
return true;
|
||||
switch (subpolicy)
|
||||
if (!PolicyMap.TryGetValue(policy, out var subPolicies))
|
||||
return false;
|
||||
return subPolicies.Contains(subpolicy) || subPolicies.Any(s => ContainsPolicy(s, subpolicy));
|
||||
}
|
||||
|
||||
private static Dictionary<string, HashSet<string>> PolicyMap = new();
|
||||
|
||||
private static void Init()
|
||||
{
|
||||
PolicyHasChild(Policies.CanModifyStoreSettings,
|
||||
Policies.CanManageCustodianAccounts,
|
||||
Policies.CanManagePullPayments,
|
||||
Policies.CanModifyInvoices,
|
||||
Policies.CanViewStoreSettings,
|
||||
Policies.CanModifyStoreWebhooks,
|
||||
Policies.CanModifyPaymentRequests,
|
||||
Policies.CanUseLightningNodeInStore);
|
||||
|
||||
PolicyHasChild(Policies.CanManageUsers, Policies.CanCreateUser);
|
||||
PolicyHasChild(Policies.CanManagePullPayments, Policies.CanCreatePullPayments);
|
||||
PolicyHasChild(Policies.CanCreatePullPayments, Policies.CanCreateNonApprovedPullPayments);
|
||||
PolicyHasChild(Policies.CanModifyPaymentRequests, Policies.CanViewPaymentRequests);
|
||||
PolicyHasChild(Policies.CanModifyProfile, Policies.CanViewProfile);
|
||||
PolicyHasChild(Policies.CanUseLightningNodeInStore, Policies.CanViewLightningInvoiceInStore, Policies.CanCreateLightningInvoiceInStore);
|
||||
PolicyHasChild(Policies.CanManageNotificationsForUser, Policies.CanViewNotificationsForUser);
|
||||
PolicyHasChild(Policies.CanModifyServerSettings,
|
||||
Policies.CanUseInternalLightningNode,
|
||||
Policies.CanManageUsers);
|
||||
PolicyHasChild(Policies.CanUseInternalLightningNode, Policies.CanCreateLightningInvoiceInternalNode, Policies.CanViewLightningInvoiceInternalNode);
|
||||
PolicyHasChild(Policies.CanManageCustodianAccounts, Policies.CanViewCustodianAccounts);
|
||||
PolicyHasChild(Policies.CanModifyInvoices, Policies.CanViewInvoices, Policies.CanCreateInvoice, Policies.CanCreateLightningInvoiceInStore);
|
||||
PolicyHasChild(Policies.CanViewStoreSettings, Policies.CanViewInvoices, Policies.CanViewPaymentRequests);
|
||||
}
|
||||
|
||||
private static void PolicyHasChild(string policy, params string[] subPolicies)
|
||||
{
|
||||
if (PolicyMap.TryGetValue(policy, out var existingSubPolicies))
|
||||
{
|
||||
case Policies.CanViewInvoices when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanViewInvoices when this.Policy == Policies.CanModifyInvoices:
|
||||
case Policies.CanModifyStoreWebhooks when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanViewInvoices when this.Policy == Policies.CanViewStoreSettings:
|
||||
case Policies.CanViewStoreSettings when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanCreateInvoice when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanModifyInvoices when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanViewProfile when this.Policy == Policies.CanModifyProfile:
|
||||
case Policies.CanModifyPaymentRequests when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanManagePullPayments when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanViewStoreSettings:
|
||||
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanModifyPaymentRequests:
|
||||
case Policies.CanCreateLightningInvoiceInternalNode when this.Policy == Policies.CanUseInternalLightningNode:
|
||||
case Policies.CanCreateLightningInvoiceInStore when this.Policy == Policies.CanUseLightningNodeInStore:
|
||||
case Policies.CanViewNotificationsForUser when this.Policy == Policies.CanManageNotificationsForUser:
|
||||
case Policies.CanUseInternalLightningNode when this.Policy == Policies.CanModifyServerSettings:
|
||||
case Policies.CanViewCustodianAccounts when this.Policy == Policies.CanManageCustodianAccounts:
|
||||
case Policies.CanViewCustodianAccounts when this.Policy == Policies.CanModifyStoreSettings:
|
||||
case Policies.CanManageCustodianAccounts when this.Policy == Policies.CanModifyStoreSettings:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
foreach (string subPolicy in subPolicies)
|
||||
{
|
||||
existingSubPolicies.Add(subPolicy);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
PolicyMap.Add(policy, subPolicies.ToHashSet());
|
||||
}
|
||||
}
|
||||
|
||||
@ -212,23 +284,17 @@ namespace BTCPayServer.Client
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
if (Scope != null)
|
||||
{
|
||||
return $"{Policy}:{Scope}";
|
||||
}
|
||||
return Policy;
|
||||
return Scope != null ? $"{Policy}:{Scope}" : Policy;
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
Permission item = obj as Permission;
|
||||
if (item == null)
|
||||
return false;
|
||||
return ToString().Equals(item.ToString());
|
||||
return item != null && ToString().Equals(item.ToString());
|
||||
}
|
||||
public static bool operator ==(Permission a, Permission b)
|
||||
{
|
||||
if (System.Object.ReferenceEquals(a, b))
|
||||
if (ReferenceEquals(a, b))
|
||||
return true;
|
||||
if (((object)a == null) || ((object)b == null))
|
||||
return false;
|
||||
|
@ -4,8 +4,8 @@
|
||||
|
||||
<ItemGroup>
|
||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||
<PackageReference Include="NBXplorer.Client" Version="4.2.2" />
|
||||
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.18" />
|
||||
<PackageReference Include="NBXplorer.Client" Version="4.2.3" />
|
||||
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="2.0.1" />
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(Altcoins)' != 'true'">
|
||||
<Compile Remove="Altcoins\**\*.cs"></Compile>
|
||||
|
@ -23,7 +23,7 @@ namespace BTCPayServer
|
||||
internal Task ProcessTask;
|
||||
public async Task Process(CancellationToken cancellationToken)
|
||||
{
|
||||
retry:
|
||||
retry:
|
||||
while (Chan.Reader.TryRead(out var item))
|
||||
{
|
||||
await item(cancellationToken);
|
||||
@ -52,7 +52,7 @@ namespace BTCPayServer
|
||||
{
|
||||
lock (_Queues)
|
||||
{
|
||||
retry:
|
||||
retry:
|
||||
if (stopped)
|
||||
return;
|
||||
Cleanup();
|
||||
|
@ -1,6 +1,6 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using BTCPayServer.Data.Data;
|
||||
using System.Threading.Tasks;
|
||||
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Design;
|
||||
@ -30,7 +30,12 @@ namespace BTCPayServer.Data
|
||||
{
|
||||
_designTime = designTime;
|
||||
}
|
||||
|
||||
#nullable enable
|
||||
public async Task<string?> GetMigrationState()
|
||||
{
|
||||
return (await Settings.FromSqlRaw("SELECT \"Id\", \"Value\" FROM \"Settings\" WHERE \"Id\"='MigrationData'").AsNoTracking().FirstOrDefaultAsync())?.Value;
|
||||
}
|
||||
#nullable restore
|
||||
public DbSet<AddressInvoiceData> AddressInvoices { get; set; }
|
||||
public DbSet<APIKeyData> ApiKeys { get; set; }
|
||||
public DbSet<AppData> Apps { get; set; }
|
||||
@ -67,8 +72,9 @@ namespace BTCPayServer.Data
|
||||
public DbSet<WalletTransactionData> WalletTransactions { get; set; }
|
||||
public DbSet<WebhookDeliveryData> WebhookDeliveries { get; set; }
|
||||
public DbSet<WebhookData> Webhooks { get; set; }
|
||||
public DbSet<LightningAddressData> LightningAddresses{ get; set; }
|
||||
public DbSet<LightningAddressData> LightningAddresses { get; set; }
|
||||
public DbSet<PayoutProcessorData> PayoutProcessors { get; set; }
|
||||
public DbSet<FormData> Forms { get; set; }
|
||||
|
||||
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
|
||||
{
|
||||
@ -83,23 +89,23 @@ namespace BTCPayServer.Data
|
||||
|
||||
// some of the data models don't have OnModelCreating for now, commenting them
|
||||
|
||||
ApplicationUser.OnModelCreating(builder);
|
||||
ApplicationUser.OnModelCreating(builder, Database);
|
||||
AddressInvoiceData.OnModelCreating(builder);
|
||||
APIKeyData.OnModelCreating(builder);
|
||||
APIKeyData.OnModelCreating(builder, Database);
|
||||
AppData.OnModelCreating(builder);
|
||||
CustodianAccountData.OnModelCreating(builder);
|
||||
CustodianAccountData.OnModelCreating(builder, Database);
|
||||
//StoredFile.OnModelCreating(builder);
|
||||
InvoiceEventData.OnModelCreating(builder);
|
||||
InvoiceSearchData.OnModelCreating(builder);
|
||||
InvoiceWebhookDeliveryData.OnModelCreating(builder);
|
||||
InvoiceData.OnModelCreating(builder);
|
||||
NotificationData.OnModelCreating(builder);
|
||||
InvoiceData.OnModelCreating(builder, Database);
|
||||
NotificationData.OnModelCreating(builder, Database);
|
||||
//OffchainTransactionData.OnModelCreating(builder);
|
||||
BTCPayServer.Data.PairedSINData.OnModelCreating(builder);
|
||||
PairingCodeData.OnModelCreating(builder);
|
||||
//PayjoinLock.OnModelCreating(builder);
|
||||
PaymentRequestData.OnModelCreating(builder);
|
||||
PaymentData.OnModelCreating(builder);
|
||||
PaymentRequestData.OnModelCreating(builder, Database);
|
||||
PaymentData.OnModelCreating(builder, Database);
|
||||
PayoutData.OnModelCreating(builder);
|
||||
PendingInvoiceData.OnModelCreating(builder);
|
||||
//PlannedTransaction.OnModelCreating(builder);
|
||||
@ -110,7 +116,7 @@ namespace BTCPayServer.Data
|
||||
StoreWebhookData.OnModelCreating(builder);
|
||||
StoreData.OnModelCreating(builder, Database);
|
||||
U2FDevice.OnModelCreating(builder);
|
||||
Fido2Credential.OnModelCreating(builder);
|
||||
Fido2Credential.OnModelCreating(builder, Database);
|
||||
BTCPayServer.Data.UserStore.OnModelCreating(builder);
|
||||
//WalletData.OnModelCreating(builder);
|
||||
WalletObjectData.OnModelCreating(builder, Database);
|
||||
@ -118,13 +124,14 @@ namespace BTCPayServer.Data
|
||||
#pragma warning disable CS0612 // Type or member is obsolete
|
||||
WalletTransactionData.OnModelCreating(builder);
|
||||
#pragma warning restore CS0612 // Type or member is obsolete
|
||||
WebhookDeliveryData.OnModelCreating(builder);
|
||||
LightningAddressData.OnModelCreating(builder);
|
||||
PayoutProcessorData.OnModelCreating(builder);
|
||||
//WebhookData.OnModelCreating(builder);
|
||||
WebhookDeliveryData.OnModelCreating(builder, Database);
|
||||
LightningAddressData.OnModelCreating(builder, Database);
|
||||
PayoutProcessorData.OnModelCreating(builder, Database);
|
||||
WebhookData.OnModelCreating(builder, Database);
|
||||
FormData.OnModelCreating(builder, Database);
|
||||
|
||||
|
||||
if (Database.IsSqlite() && !_designTime)
|
||||
if (Database.IsSqlite() && !_designTime)
|
||||
{
|
||||
// SQLite does not have proper support for DateTimeOffset via Entity Framework Core, see the limitations
|
||||
// here: https://docs.microsoft.com/en-us/ef/core/providers/sqlite/limitations#query-limitations
|
||||
|
@ -1,9 +1,11 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class APIKeyData
|
||||
public class APIKeyData : IHasBlob<APIKeyBlob>
|
||||
{
|
||||
[MaxLength(50)]
|
||||
public string Id { get; set; }
|
||||
@ -16,13 +18,15 @@ namespace BTCPayServer.Data
|
||||
|
||||
public APIKeyType Type { get; set; } = APIKeyType.Legacy;
|
||||
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
public StoreData StoreData { get; set; }
|
||||
public ApplicationUser User { get; set; }
|
||||
public string Label { get; set; }
|
||||
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<APIKeyData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
@ -36,6 +40,13 @@ namespace BTCPayServer.Data
|
||||
|
||||
builder.Entity<APIKeyData>()
|
||||
.HasIndex(o => o.StoreId);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<APIKeyData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,11 +2,13 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Identity;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
// Add profile data for application users by adding properties to the ApplicationUser class
|
||||
public class ApplicationUser : IdentityUser
|
||||
public class ApplicationUser : IdentityUser, IHasBlob<UserBlob>
|
||||
{
|
||||
public bool RequiresEmailConfirmation { get; set; }
|
||||
public List<StoredFile> StoredFiles { get; set; }
|
||||
@ -20,15 +22,28 @@ namespace BTCPayServer.Data
|
||||
public List<UserStore> UserStores { get; set; }
|
||||
public List<Fido2Credential> Fido2Credentials { get; set; }
|
||||
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
|
||||
public List<IdentityUserRole<string>> UserRoles { get; set; }
|
||||
|
||||
public static void OnModelCreating(ModelBuilder builder)
|
||||
public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<ApplicationUser>()
|
||||
.HasMany<IdentityUserRole<string>>(user => user.UserRoles)
|
||||
.WithOne().HasForeignKey(role => role.UserId);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<ApplicationUser>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public class UserBlob
|
||||
{
|
||||
public bool ShowInvoiceStatusChangeHint { get; set; }
|
||||
}
|
||||
}
|
||||
|
@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace BTCPayServer.Data;
|
||||
|
||||
public class CustodianAccountData
|
||||
public class CustodianAccountData : IHasBlob<JObject>
|
||||
{
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
@ -14,29 +16,39 @@ public class CustodianAccountData
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
public string StoreId { get; set; }
|
||||
|
||||
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
public string CustodianCode { get; set; }
|
||||
|
||||
|
||||
[Required]
|
||||
[MaxLength(50)]
|
||||
public string Name { get; set; }
|
||||
|
||||
|
||||
[JsonIgnore]
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public string Blob2 { get; set; }
|
||||
|
||||
[JsonIgnore]
|
||||
public StoreData StoreData { get; set; }
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<CustodianAccountData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
.WithMany(i => i.CustodianAccounts)
|
||||
.HasForeignKey(i => i.StoreId).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
builder.Entity<APIKeyData>()
|
||||
|
||||
builder.Entity<CustodianAccountData>()
|
||||
.HasIndex(o => o.StoreId);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<CustodianAccountData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2,10 +2,11 @@ using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class Fido2Credential
|
||||
public class Fido2Credential : IHasBlobUntyped
|
||||
{
|
||||
public string Name { get; set; }
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
@ -14,6 +15,7 @@ namespace BTCPayServer.Data
|
||||
public string ApplicationUserId { get; set; }
|
||||
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
public CredentialType Type { get; set; }
|
||||
public enum CredentialType
|
||||
{
|
||||
@ -22,12 +24,18 @@ namespace BTCPayServer.Data
|
||||
[Display(Name = "Lightning node (LNURL Auth)")]
|
||||
LNURLAuth
|
||||
}
|
||||
public static void OnModelCreating(ModelBuilder builder)
|
||||
public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<Fido2Credential>()
|
||||
.HasOne(o => o.ApplicationUser)
|
||||
.WithMany(i => i.Fido2Credentials)
|
||||
.HasForeignKey(i => i.ApplicationUserId).OnDelete(DeleteBehavior.Cascade);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<Fido2Credential>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
|
||||
public ApplicationUser ApplicationUser { get; set; }
|
||||
|
@ -2,11 +2,30 @@ using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data.Data;
|
||||
namespace BTCPayServer.Data;
|
||||
|
||||
public class FormData
|
||||
{
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public string Id { get; set; }
|
||||
public string Name { get; set; }
|
||||
public string StoreId { get; set; }
|
||||
public StoreData Store { get; set; }
|
||||
public string Config { get; set; }
|
||||
public bool Public { get; set; }
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<FormData>()
|
||||
.HasOne(o => o.Store)
|
||||
.WithMany(o => o.Forms).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<FormData>().HasIndex(o => o.StoreId);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<FormData>()
|
||||
.Property(o => o.Config)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
28
BTCPayServer.Data/Data/IHasBlob.cs
Normal file
28
BTCPayServer.Data/Data/IHasBlob.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public interface IHasBlob<T>
|
||||
{
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
byte[] Blob { get; set; }
|
||||
string Blob2 { get; set; }
|
||||
}
|
||||
public interface IHasBlob
|
||||
{
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
byte[] Blob { get; set; }
|
||||
string Blob2 { get; set; }
|
||||
public Type Type { get; set; }
|
||||
}
|
||||
public interface IHasBlobUntyped
|
||||
{
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
byte[] Blob { get; set; }
|
||||
string Blob2 { get; set; }
|
||||
}
|
||||
}
|
@ -2,10 +2,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class InvoiceData
|
||||
public class InvoiceData : IHasBlobUntyped
|
||||
{
|
||||
public string Id { get; set; }
|
||||
|
||||
@ -16,7 +17,9 @@ namespace BTCPayServer.Data
|
||||
public List<PaymentData> Payments { get; set; }
|
||||
public List<InvoiceEventData> Events { get; set; }
|
||||
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
public string ItemCode { get; set; }
|
||||
public string OrderId { get; set; }
|
||||
public string Status { get; set; }
|
||||
@ -32,7 +35,7 @@ namespace BTCPayServer.Data
|
||||
public RefundData CurrentRefund { get; set; }
|
||||
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<InvoiceData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
@ -42,6 +45,13 @@ namespace BTCPayServer.Data
|
||||
builder.Entity<InvoiceData>()
|
||||
.HasOne(o => o.CurrentRefund);
|
||||
builder.Entity<InvoiceData>().HasIndex(o => o.Created);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<InvoiceData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,17 +1,21 @@
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data;
|
||||
|
||||
public class LightningAddressData
|
||||
public class LightningAddressData : IHasBlob<LightningAddressDataBlob>
|
||||
{
|
||||
public string Username { get; set; }
|
||||
public string StoreDataId { get; set; }
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
|
||||
public StoreData Store { get; set; }
|
||||
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<LightningAddressData>()
|
||||
.HasOne(o => o.Store)
|
||||
@ -20,6 +24,12 @@ public class LightningAddressData
|
||||
.IsRequired()
|
||||
.OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<LightningAddressData>().HasKey(o => o.Username);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<LightningAddressData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,10 +1,12 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Storage;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class NotificationData
|
||||
public class NotificationData : IHasBlobUntyped
|
||||
{
|
||||
[MaxLength(36)]
|
||||
public string Id { get; set; }
|
||||
@ -17,15 +19,23 @@ namespace BTCPayServer.Data
|
||||
[Required]
|
||||
public string NotificationType { get; set; }
|
||||
public bool Seen { get; set; }
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<NotificationData>()
|
||||
.HasOne(o => o.ApplicationUser)
|
||||
.WithMany(n => n.Notifications)
|
||||
.HasForeignKey(k => k.ApplicationUserId).OnDelete(DeleteBehavior.Cascade);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<NotificationData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,24 +1,34 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class PaymentData
|
||||
public class PaymentData : IHasBlobUntyped
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public string InvoiceDataId { get; set; }
|
||||
public InvoiceData InvoiceData { get; set; }
|
||||
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
public string Type { get; set; }
|
||||
public bool Accounted { get; set; }
|
||||
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<PaymentData>()
|
||||
.HasOne(o => o.InvoiceData)
|
||||
.WithMany(i => i.Payments).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<PaymentData>()
|
||||
.HasIndex(o => o.InvoiceDataId);
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PaymentData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,10 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class PaymentRequestData
|
||||
public class PaymentRequestData : IHasBlobUntyped
|
||||
{
|
||||
public string Id { get; set; }
|
||||
public DateTimeOffset Created { get; set; }
|
||||
@ -14,10 +15,12 @@ namespace BTCPayServer.Data
|
||||
|
||||
public Client.Models.PaymentRequestData.PaymentRequestStatus Status { get; set; }
|
||||
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.HasOne(o => o.StoreData)
|
||||
@ -28,6 +31,13 @@ namespace BTCPayServer.Data
|
||||
.HasDefaultValue(new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero));
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.HasIndex(o => o.Status);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PaymentRequestData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,9 +1,15 @@
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data.Data;
|
||||
namespace BTCPayServer.Data;
|
||||
|
||||
public class PayoutProcessorData
|
||||
public class AutomatedPayoutBlob
|
||||
{
|
||||
public TimeSpan Interval { get; set; } = TimeSpan.FromHours(1);
|
||||
}
|
||||
public class PayoutProcessorData : IHasBlobUntyped
|
||||
{
|
||||
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
|
||||
public string Id { get; set; }
|
||||
@ -11,15 +17,23 @@ public class PayoutProcessorData
|
||||
public StoreData Store { get; set; }
|
||||
public string PaymentMethod { get; set; }
|
||||
public string Processor { get; set; }
|
||||
|
||||
public byte[] Blob { get; set; }
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
{
|
||||
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<PayoutProcessorData>()
|
||||
.HasOne(o => o.Store)
|
||||
.WithMany(data => data.PayoutProcessors).OnDelete(DeleteBehavior.Cascade);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<PayoutProcessorData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
|
@ -1,11 +1,13 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations.Schema;
|
||||
using System.Text;
|
||||
using BTCPayServer.Client;
|
||||
using BTCPayServer.Client.Models;
|
||||
using BTCPayServer.Data.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using PayoutProcessorData = BTCPayServer.Data.Data.PayoutProcessorData;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using PayoutProcessorData = BTCPayServer.Data.PayoutProcessorData;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
@ -25,7 +27,6 @@ namespace BTCPayServer.Data
|
||||
[Obsolete("Use GetDerivationStrategies instead")]
|
||||
public string DerivationStrategy { get; set; }
|
||||
|
||||
[Obsolete("Use GetDerivationStrategies instead")]
|
||||
public string DerivationStrategies { get; set; }
|
||||
|
||||
public string StoreName { get; set; }
|
||||
@ -50,6 +51,7 @@ namespace BTCPayServer.Data
|
||||
public IEnumerable<PayoutData> Payouts { get; set; }
|
||||
public IEnumerable<CustodianAccountData> CustodianAccounts { get; set; }
|
||||
public IEnumerable<StoreSettingData> Settings { get; set; }
|
||||
public IEnumerable<FormData> Forms { get; set; }
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
@ -58,6 +60,20 @@ namespace BTCPayServer.Data
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.StoreBlob)
|
||||
.HasColumnType("JSONB");
|
||||
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.DerivationStrategies)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
else if (databaseFacade.IsMySql())
|
||||
{
|
||||
builder.Entity<StoreData>()
|
||||
.Property(o => o.StoreBlob)
|
||||
.HasConversion(new ValueConverter<string, byte[]>
|
||||
(
|
||||
convertToProviderExpression: (str) => Encoding.UTF8.GetBytes(str),
|
||||
convertFromProviderExpression: (bytes) => Encoding.UTF8.GetString(bytes)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ public class StoreSettingData
|
||||
public string Value { get; set; }
|
||||
|
||||
public StoreData Store { get; set; }
|
||||
|
||||
|
||||
public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<StoreSettingData>().HasKey(data => new { data.StoreId, data.Name });
|
||||
|
@ -2,5 +2,5 @@ namespace BTCPayServer.Data;
|
||||
|
||||
public class TradeResultData
|
||||
{
|
||||
|
||||
|
||||
}
|
||||
|
@ -12,6 +12,13 @@ namespace BTCPayServer.Data
|
||||
{
|
||||
public class Types
|
||||
{
|
||||
public static readonly HashSet<string> AllTypes;
|
||||
static Types()
|
||||
{
|
||||
AllTypes = typeof(Types).GetFields()
|
||||
.Where(f => f.FieldType == typeof(string))
|
||||
.Select(f => (string)f.GetValue(null)).ToHashSet(StringComparer.OrdinalIgnoreCase);
|
||||
}
|
||||
public const string Label = "label";
|
||||
public const string Tx = "tx";
|
||||
public const string Payjoin = "payjoin";
|
||||
|
@ -1,15 +1,29 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class WebhookData
|
||||
public class WebhookData : IHasBlobUntyped
|
||||
{
|
||||
[Key]
|
||||
[MaxLength(25)]
|
||||
public string Id { get; set; }
|
||||
[Required]
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
public List<WebhookDeliveryData> Deliveries { get; set; }
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<WebhookData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,10 +1,11 @@
|
||||
using System;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
|
||||
namespace BTCPayServer.Data
|
||||
{
|
||||
public class WebhookDeliveryData
|
||||
public class WebhookDeliveryData : IHasBlobUntyped
|
||||
{
|
||||
[Key]
|
||||
[MaxLength(25)]
|
||||
@ -16,17 +17,24 @@ namespace BTCPayServer.Data
|
||||
|
||||
[Required]
|
||||
public DateTimeOffset Timestamp { get; set; }
|
||||
|
||||
[Required]
|
||||
[Obsolete("Use Blob2 instead")]
|
||||
public byte[] Blob { get; set; }
|
||||
public string Blob2 { get; set; }
|
||||
|
||||
|
||||
internal static void OnModelCreating(ModelBuilder builder)
|
||||
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
|
||||
{
|
||||
builder.Entity<WebhookDeliveryData>()
|
||||
.HasOne(o => o.Webhook)
|
||||
.WithMany(a => a.Deliveries).OnDelete(DeleteBehavior.Cascade);
|
||||
builder.Entity<WebhookDeliveryData>().HasIndex(o => o.WebhookId);
|
||||
|
||||
if (databaseFacade.IsNpgsql())
|
||||
{
|
||||
builder.Entity<WebhookDeliveryData>()
|
||||
.Property(o => o.Blob2)
|
||||
.HasColumnType("JSONB");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,8 +1,8 @@
|
||||
using System;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using System;
|
||||
using BTCPayServer.Data;
|
||||
using Microsoft.EntityFrameworkCore;
|
||||
using Microsoft.EntityFrameworkCore.Infrastructure;
|
||||
using Microsoft.EntityFrameworkCore.Migrations;
|
||||
using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
|
||||
using Npgsql.EntityFrameworkCore.PostgreSQL.Metadata;
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user