Compare commits

...

543 Commits

Author SHA1 Message Date
4bffe117a9 Do not show cheatmode in release, fix warnigns 2023-07-25 10:50:34 +09:00
05b01a13c8 Fix NRE error in PoS report 2023-07-24 23:20:17 +09:00
08e21c1a5d Fix report view 2023-07-24 23:13:11 +09:00
4d5245605d bump 2023-07-24 22:59:18 +09:00
453548d614 Checkout v2: Play sound when invoice is paid ()
* Checkout v2: Play sound when invoice is paid

Closes .

* Refactoring: Use low-level audio API to play the sound

Allows to play the sound regardless of browser permissions.

* Add audio file detection

* Use model state for file upload errors

* Add default sound and customizing option

* Fix mp3 detection

* Add sounds

* Update defaults

* Add nfcread and error sounds

* Improve label wording

* Replace sound

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-07-24 22:57:24 +09:00
95a0614ae1 Support accepting 0 amount bolt 11 invoices for payouts ()
* Support accepting 0 amount bolt 11 invoices for payouts

* add test

* handle validation better

* fix case when we just want pp to provide amt

* Update BTCPayServer/HostedServices/PullPaymentHostedService.cs

* Update BTCPayServer/HostedServices/PullPaymentHostedService.cs

* Update BTCPayServer/Data/Payouts/LightningLike/UILightningLikePayoutController.cs

* Update UILightningLikePayoutController.cs

* fix null

* fix payments of payouts on cln

* add comment

* bump lightning lib

---------

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-07-24 20:40:26 +09:00
36ea17a6b7 Introduce Payout metadata for api and plugins ()
* Introduce Payout metadata for api and plugins

* fix controller

* fix metadata requirement

* save an object

* pr changes
2023-07-24 18:37:18 +09:00
dc986959fd Add reporting feature ()
* Add reporting feature

* Remove nodatime

* Add summaries

* work...

* Add chart title

* Fix error

* Allow to set hour in the field

* UI updates

* Fix fake data

* ViewDefinitions can be dynamic

* Add items sold

* Sticky table headers

* Update JS and remove jQuery usages

* JS click fix

* Handle tag all invoices for app

* fix dup row in items report

* Can cancel invoice request

* Add tests

* Fake data for items sold

* Rename Items to Products, improve navigation F5

* Use bordered table for summaries

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-07-24 09:24:32 +09:00
845e2881fa POS Cart redesign ()
* Move POS assets

* WIP

* Refactor into common Vue mixin

* Offcanvas updates

* Unifications across POS views

* POSData view fix

* Number and test fixes

* Update cart width

* Fix test

* More view unification

* Hide cart when emptied

* Validate cart

* Header improvement

* Increase remove icon size

* Animate add to cart action

* Offcanvas for mobile, sidebar for desktop

* ui+pos: updates icon size + badge + label

* Remove cart table headers

* Use same size for Cart and Shop headlines

* Update search placeholder

* Bump horizontal  input padding

* Increase sidebar width

* Bump badge font size

* Fix manipulating the quantity of line items

* Fix cart icon

* Update cart display

* updates empty button

* Rounded search input

* Remove cart button on desktop

* Fix dark accent color

* More accent fixes

* Fix plus/minus alignment

* Update BTCPayServer/Views/Shared/PointOfSale/Public/Cart.cshtml

* Apply suggestions from code review

---------

Co-authored-by: dstrukt <gfxdsign@gmail.com>
2023-07-22 21:15:41 +09:00
2e4be9310c Design system updates () 2023-07-21 09:27:37 +02:00
a2faa6fd59 Minor fixes () 2023-07-21 09:05:50 +02:00
0a78846e8d Stop using bitpay's CreateInvoice for non bitpay API usage () 2023-07-21 09:08:32 +09:00
4063a5aaee Quality of life improvements to payout processors ()
* Quality of life improvements to payout processors

* Allows more fleixble intervals for payout processing from 10-60 mins to 1min-24hours(requested by users)
* Cancel ln payotus that expired (bolt11)
* Allow cancelling of ln payotus that have failed to be paid after x attempts
* Allow conifguring a threshold for when to process on-chain payouts (reduces fees)

# Conflicts:
#	BTCPayServer.Tests/SeleniumTests.cs

* Simplify the code

* switch to concurrent dictionary

* Allow ProcessNewPayoutsInstantly

* refactor plugin hook service to have events available and change processor hooks to actions with better args

* add procesor extended tests

* Update BTCPayServer.Tests/GreenfieldAPITests.cs

* fix concurrency issue

* Update BTCPayServer/PayoutProcessors/BaseAutomatedPayoutProcessor.cs

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-07-20 22:05:14 +09:00
b1c81b696f Generate unique order IDs for PoS and Crowdfund sales ()
* Generate unique order IDs for PoS and Crowdfund sales

Part of .

* Refactorings

* Updates

* Updates

* Refactoring

* Remove search by AdditionalSearchTerm

* Implement appid

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-07-20 16:03:39 +09:00
0017f236a7 Improve create first store view ()
* Improve create first store view

Closes .

* Fix tests
2023-07-19 22:21:16 +09:00
19d5e64063 Form invoice amount adjusters ()
* Fix constant fields being editable on UI

* fix redirect to checkout if invoice is settled (redirect to receipt instead)

* enhance: make mirror field type able to map values

* Introduce invoice amount adjustment fields for form

* Integrate invoice amount adjustment fields for form on pos

* Support mirror in editor

* Indicate when special field names are used

* polsih mirror view and name suggestions for fields

* clarify

* hide hidden field from ui

* Minor adjustmentts

* Improve mirror field editing

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-07-19 18:54:51 +09:00
22435a2bf5 Refactor logic for calculating due amount of invoices ()
* Refactor logic for calculating due amount of invoices

* Remove Money type from the accounting

* Fix tests

* Fix a corner case

* fix bug

* Rename PaymentCurrency to Currency

* Fix bug

* Rename PaymentCurrency -> Currency

* Payment objects should have access to the InvoiceEntity

* Set Currency USD in tests

* Simplify some code

* Remove useless code

* Simplify code, kukks comment
2023-07-19 18:47:32 +09:00
a7def63137 fix pos item topups lnurl ()
fixes 
2023-07-17 13:08:41 +02:00
3703a170e7 try fix migration for pos yml 2023-07-13 14:59:18 +02:00
73fbfbd7cb Add support for Monero RPC authentication ()
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2023-07-13 12:24:08 +02:00
acae3b8753 Refactoring 2023-07-13 12:17:41 +02:00
a618f901fc Support NFC on modal 2023-07-13 12:17:41 +02:00
6d4918f0ab Update ViewPullPayment.cshtml 2023-07-13 12:17:01 +02:00
7f2c4d2e7a add extension point for pull payment view 2023-07-13 12:17:01 +02:00
fd6d361e1a CheckoutV2: When WebSocket disconnects, we should continue polling via XHR ()
* When WebSocket disconnects, we should continue polling via XHR

* Update BTCPayServer/wwwroot/checkout-v2/checkout.js

Co-authored-by: d11n <mail@dennisreimann.de>

---------

Co-authored-by: d11n <mail@dennisreimann.de>
2023-07-11 21:56:13 +02:00
b5f0924651 Serialize PosAppCartItem.value as decimal instead of string 2023-07-11 15:49:16 +09:00
1600dd4759 POS: Backwards-compatible price parsing ()
* POS: Backwards-compatible price parsing

Fixes  and a regression introduced in bbff9710bf2f4a66bd6f4cd9e8ee55618d0ca5e0: The price in posData needs to be parsed in a backwards-compatible manner, as the old format of price as an object exists in the invoice metadata.

* Test corner cases

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-07-11 15:32:01 +09:00
c777746b69 Custom Forms: Allow HTML in labels and help text ()
* Custom Forms: Allow HTML in labels and help text

Fixes .

* Vue: Sanitize labels and helper text input

* Form editor: Fix blur on input for select option values

---------

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-07-11 13:02:02 +09:00
9f5466a41f Make sure CheckJsContent run as part of CI, and ignore end of line differences 2023-07-11 09:41:28 +09:00
4d1e4801bf Dark theme color fix 2023-07-10 11:33:39 +02:00
5e469ff9c0 Improve rates ()
* Removes Chaincoin shitcoin which is so dead even its website is gone
* Add ExchangeRateHost and FreeCurrencyRates as new rate providers
* Add recommended rate providers for UGX and RSD
* Fix BTX rate by switching to graviex
* Fix BTC rate by switching to exmo
* Fix LCAD rate script
2023-07-10 17:31:48 +09:00
2f3eedea5b Invoice lists: Show icons for payment methods () 2023-07-08 17:33:13 +02:00
5c5d6dc1e2 Bumping LND to 0.16.4-beta 2023-07-08 08:22:42 -05:00
fbe31ce64f Support LNURL in pay button ()
* Support LNURL in pay button

* UI updates

* Cleanups

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-07-06 10:12:31 +02:00
0b082138c8 Payment Requests: List view improvements ()
* List invoice checkbox variant

* Remove custom css

* Improve payment requests list view

* Improve Payment Requests List View

* List invoice checkbox variant

* Remove custom css

* Improve payment requests list view

* Improve Payment Requests List View

* Update payment request (name link leads to view not edit)

* Refactoring

---------

Co-authored-by: d11n <mail@dennisreimann.de>
2023-07-06 10:02:23 +02:00
966e598f10 Apps: Add direct file upload in item editor () 2023-07-06 11:01:36 +09:00
e998340387 POS: Account for custom amount in cart view ()
* Add failing test

* Account for custom amount

* Test fix
2023-07-05 17:23:15 +09:00
f6b27cc5f9 Compare domains in lowercase
Domains are case-insensitive, so this comparision should be too.

I encountered this issue with a Citadel user who accidentially named their domain an uppercase name (Pay.example.com), but browsers automatically converted it to pay.example.com
2023-07-03 08:49:16 +02:00
f3dbf1e139 Allow browser to access LND config () 2023-06-30 15:08:23 +09:00
627d84fc91 Update to Bootstrap v5.3 ()
Based on 
2023-06-30 09:21:27 +09:00
8cde8c01df Add category feature to the PoS with Cart ()
* Add grouping feature to the PoS with Cart

* Improve UI

* Rename groups to categories

* Make it easier to select categories of the items

* Refactor TemplateEditor, use TomSelect for categories

* Prevent Vue code insertion

* Prevent empty categories

* Add label ids

* Add test case

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-06-30 09:13:15 +09:00
983b8c1f54 Fix changelog 2023-06-27 21:32:05 +09:00
d666d8ea1a Changelog 1.10.3 ()
* Changelog 1.10.3

* Apply suggestions from code review

Co-authored-by: d11n <mail@dennisreimann.de>

* Apply suggestions from code review

* Update changelog

---------

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
Co-authored-by: d11n <mail@dennisreimann.de>
2023-06-27 21:23:56 +09:00
3ed81c3a78 Greenfield: Fix missing default currency in stores API
Docs mention it should be present, but it wasn't. Fixes .
2023-06-27 12:52:24 +02:00
4afec2e2b6 Fix: Using lnaddresses on Nostr should not result in lots of invoice being created 2023-06-27 12:50:24 +02:00
db83d238d5 Crowdfund: Fix JS errors in empty state ()
An empty crfowdfund with the default perk had JS errors.
2023-06-27 09:42:18 +09:00
fdcf7b3b7a Bumping LND to 0.16.3-beta () 2023-06-27 09:06:31 +09:00
53aafcf86b Fix: The current preimage of a invoice's lightning payment method should be available via API () 2023-06-23 19:12:11 +09:00
aec84f6d67 Dashboard: Limit "Top Items" to five ()
Feedback we got at BTCPrague: Do not show more than five items in the top list, because otherwise the list can get very long if there's a POS with many items.
2023-06-23 11:31:05 +02:00
01e9f82d24 Policies: Update wording to fit API keys and Roles ()
* Policies: Update wording to fit API keys and Roles

Closes .

* API keys: Improve spacing
2023-06-22 10:37:30 +02:00
2eff45e65c Ajaxify the wallet transaction list to avoid timeout (Fix ) ()
* Ajaxify the wallet transaction list to avoid timeout (Fix )

* Add cancellation to request to wallet transactions

* Fix tests

* Improve empty state

* Cleanups

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-06-22 16:09:53 +09:00
13203c3e2b Receipt improvements ()
* Remove Order ID link

* Add separate print version for receipt

* Fix POS number handling and add keypad test

Fixes .

* Add formatting function

* Remove OrderUrl for POS, bring back order link for receipt

* Update BTCPayServer/Plugins/PointOfSale/Controllers/UIPointOfSaleController.cs
2023-06-22 15:57:29 +09:00
82c5e0e43d Dashboard: Make invoice badges consistent with those on invoices list ()
Closes .
2023-06-22 15:47:12 +09:00
a1575f404b Invoices: Fix search box shrinking too small ()
Fixes .
2023-06-21 09:52:42 +02:00
e1509506dc Upgrade Bootstrap-Vue and fix tooltip positioning
Fixes .
2023-06-21 08:31:13 +02:00
0c1d0d7b05 Fix: formResponse and formId missing from API's GetPaymentRequest route 2023-06-21 12:47:21 +09:00
ad70856af0 Fix: LN payments failed to be detected on litd () 2023-06-21 12:15:46 +09:00
8615f120ce Fix tests 2023-06-20 22:37:05 +09:00
0d0477d661 Lightning: Relax GetInfo constraint for LNDhub connections ()
* Lightning: Relax GetInfo constraint for LNDhub connections

The LNDhub-compatible implementation by LNbits does not support the `GetInfo` call for all their funding sources — see lnbits/lnbits#1182. By catching that exception in combination with the `LndHubLightningClient`, we give people the ability to still use their LNbits-based LNDhub as a Lightning node.

Fixes .

* Update approach to handling unsupported GetInfo calls
2023-06-20 17:28:16 +09:00
b31dc30878 Make file management UI more useful ()
* Make file management UI more useful

* Simplify markup

* Move file info to top

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-06-20 08:58:28 +02:00
6e392f4cfb After changing PoS items in UpdatePoS ident the JSON template 2023-06-19 14:44:12 +09:00
cc3bdc331e Fix build 2023-06-16 23:19:47 +09:00
76faf77a1c Fix keypad view broken by previous commit 2023-06-16 23:18:47 +09:00
d8c0e5bf3a Add extension point to template editor () 2023-06-16 23:05:49 +09:00
28c4c320cc Checkout v2: Add return link in processing state ()
* Checkout v2: Add return link in processing state

* Update copy text position
2023-06-16 23:05:08 +09:00
e81403ec3f Fix: Applying a discount in PoS with cart wasn't working () 2023-06-16 23:02:14 +09:00
f11424f73a Pull Payment: Support LNURL Withdraw with SATS denomination ()
* Pull Payment: Support LNURL Withdraw with SATS denomination

* Refactor and add tests
2023-06-16 10:56:17 +09:00
fa8b977016 Remove id from create webhook endpoint; fix consistency. () 2023-06-16 10:53:41 +09:00
d181846339 Refund: Fix overpaid option ()
Closes .
2023-06-16 10:52:52 +09:00
1956919886 Do not crash when an invoice have an amount that is too big () 2023-06-16 10:47:58 +09:00
0f66498965 NFC: Do not start scanning if unsupported
Fixes .
2023-06-14 09:14:09 +02:00
918cd152b1 Fix: Incorrect rounding in the receipt of PoS invoice (fix ) () 2023-06-13 20:34:21 +02:00
d3222df396 Fix build warnings ()
Fixes these two:

```
/source/BTCPayServer/Hosting/MigrationStartupTask.cs(643,49): warning CS0168: The variable 'items' is declared but never used [/source/BTCPayServer/BTCPayServer.csproj]
/source/BTCPayServer/Hosting/MigrationStartupTask.cs(644,24): warning CS0168: The variable 'newTemplate' is declared but never used [/source/BTCPayServer/BTCPayServer.csproj]
```
2023-06-13 20:46:44 +09:00
a84ffd8c7e Crowdfund: Fix null pointer exception for topup type (missing price) ()
Items with type topup have a price = null and hence not even the property set (ignored in JSON). This needs to be handled in the temlate, otherwise this exception occurs:

```
An unhandled exception was thrown by the application.
System.InvalidOperationException: Nullable object must have a value.
   at AspNetCoreGeneratedDocument.Views_Shared_Crowdfund_Public_ContributeForm.<>c__DisplayClass24_0.<<ExecuteAsync>b__0>d.MoveNext()
```
2023-06-13 20:46:27 +09:00
6d0f9120b8 prep for 1.10.2 2023-06-07 18:02:51 +02:00
aafb4a7f2a Fix stale invoice api for settle invoice
fixes 
2023-06-07 17:57:03 +02:00
ae432ff237 Fix: Crash on migation of old instances (Fix ) 2023-06-07 10:20:39 +02:00
cdc318c71a Pay Button: Fix circular reference when serializing JSON
When apps were set, the `GetAllApps` included the store data, which led to a circular reference when serializing the JSON. That data isn't necessary here, so we can just drop it before rendering.

Fixes .
2023-06-05 12:35:06 +02:00
94d1cec8a9 Hide Sensitive Info: Fix script location
The script snippet needs to be located outside of the theme if-conditions, otherwise it only works if no custom theme is applied.
2023-06-05 12:34:54 +02:00
c0bc19ea59 Update Changelog 2023-06-02 18:21:57 +09:00
6f07714cd9 Language update 2023-06-02 18:18:10 +09:00
a9d2cac23c bump 1.10.1 2023-06-02 18:15:56 +09:00
693b46126b Bump Bitcoin core to 25.0 () 2023-06-02 16:41:35 +09:00
bbff9710bf fix cart + form combination bug fixes 2023-06-02 09:34:55 +02:00
358e122775 Fix tests 2023-06-01 22:17:42 +09:00
3818468932 Pluginify on chain wallet setup ()
* Pluginify on chain wallet setup

This PR fixes a few logical points in the wallet setup flow to allow more extensive plugin flexibility; It also fixes an issue when building plugins that requires an Altcoin config profile. Here is an example showcasing the Liquid+ plugin using this to enforce that it is a hot wallet (a requirement it has) and that import to RPC is always set, and a new option that is used to configure the wallet further https://i.imgur.com/pDPQ73v.gif

* Update BTCPayServer/Controllers/UIStoresController.Onchain.cs

* update nbx
2023-06-01 21:18:28 +09:00
3d2554fbe1 Make role name show uneditable when not creating 2023-05-31 15:49:34 +02:00
4309603317 Hide topup items from cart 2023-05-31 15:49:34 +02:00
f733c9ea77 Form Builder: Improve wording
Element -> Field. Something bas and I came across while reviewing the blog post.
2023-05-31 14:57:11 +02:00
775ee01171 fix store role deletion fixes 2023-05-31 13:42:38 +02:00
33ec790137 Changelog 2023-05-31 11:50:10 +09:00
0c575c888c Remove payment requirement for marking expired invoices ()
* Remove payment requirement for marking expired invoices

Allows to manually mark expired invoices, regardless of registered payments. See  for context, in which BTCPay Server sometimes did not register payments that were received to a LNbank wallet (this got fixed in )

* Refactor conditions for better readability
2023-05-31 11:49:01 +09:00
24f7e51e3a Small adjustements 2023-05-31 11:27:03 +09:00
0a0cf97c55 Do not cleanup unreachable stores () 2023-05-31 11:22:37 +09:00
16b988d097 UI: Only display applicable refund options
Fixes .
2023-05-30 12:51:51 +02:00
5edc0ff6ef UI: Fix visual bug with Hide Sensitive Info
Fixes 
2023-05-30 11:20:58 +02:00
375b96e508 UI: Center-align recovery phrase
Fixes .
2023-05-30 11:19:16 +02:00
1e72b12074 UI: Store selector link distinguishes between owner and user
The `IsOwner` property went missing with , so everyone landed on the invoices list when switching stores. This brings back the original behaviour of linking to the Dashboard, if the user has the permission to access it.

Fixes .
2023-05-30 11:18:34 +02:00
4a6d52f78e Fix crowdfund perk support fixes 2023-05-30 10:34:48 +02:00
35dd580e74 Fix cart view and provide better naming for default items fixes 2023-05-30 10:05:31 +02:00
79836ef1de make free invoices from pos redirect to receipt and make receipt reload fast on such case 2023-05-30 10:04:23 +02:00
8cb06f9c6c fix user store reole setting fixes 2023-05-30 09:37:14 +02:00
215a36e7a9 Fix: Some multi path payment on LND wouldn't be detected 2023-05-30 12:26:30 +09:00
247f6b86a5 Changelog 1.10.0 () 2023-05-29 16:24:27 +09:00
a9d42f1e6a Add What's New in v1.10.0 ()
* Add What's New in v1.10.0

* Update BTCPayServer/Views/UIStores/Dashboard.cshtml

Co-authored-by: B <102448109+Bas02@users.noreply.github.com>

---------

Co-authored-by: B <102448109+Bas02@users.noreply.github.com>
2023-05-29 16:08:46 +09:00
4e03c2523a Prune webhook data from database 2023-05-29 09:02:47 +02:00
418b476725 Bug fix on StoreRoleId parsing 2023-05-27 12:51:48 +09:00
783e4ccb35 Store Custom Roles () 2023-05-26 23:49:32 +09:00
6b7fb55658 Fix: Payment not marked as settled even if the payment is successful with LNBank
Fix https://github.com/dennisreimann/btcpayserver-plugin-lnbank/issues/33
2023-05-25 21:09:13 +09:00
3d5361cd11 [Bug] If a altcoins is disabled from BTCPay and payout processor is used, it would crash at restart ()
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2023-05-25 12:42:23 +02:00
2c4349c630 Test concurrent payment of lightning invoices 2023-05-25 18:41:17 +09:00
3589417b58 Form Editor: Minor wording adjustments () 2023-05-25 08:51:03 +02:00
55203e0b64 Dashboard: Fix SATS denomination display ()
When the default currency of the store is SATS, the display was broken.
2023-05-25 10:08:00 +09:00
a918288e3b Fix codeql config to not scan vendor js, add it to solution 2023-05-23 10:38:59 +09:00
e183138d2c Remove vendor js from codeql scan 2023-05-23 10:07:08 +09:00
d3e42862ed Create codeql.yml ()
Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-05-23 09:23:24 +09:00
8860eec254 Switch Apps to json not YML () 2023-05-23 09:18:57 +09:00
97e7e60cea Add minrelayfee to payjoin request
fixes 
2023-05-22 14:56:08 +02:00
44aaf7acbb Form editor ()
Co-authored-by: dstrukt <gfxdsign@gmail.com>
2023-05-22 13:30:28 +02:00
9b721fae27 Better handle postgres requests for wallet objects () 2023-05-20 23:26:16 +09:00
c3f412e3bb Bump tests to Bitcoin Core 24.1 () 2023-05-20 21:38:39 +09:00
ee738a29f0 Stop spamming logs with event aggregator logging 2023-05-19 15:24:20 +09:00
6c6544bf9b Improve invoice filtering UI ()
* Improve invoice filtering UI

Closes .

* UI updates

* Add app filter

* Add indicator for active filters

* updates text

* Improve selected filter display

* Apply suggestions from code review

---------

Co-authored-by: dstrukt <gfxdsign@gmail.com>
2023-05-19 10:42:09 +09:00
3d57b944ca Fix a bunch of minor bugs () 2023-05-19 08:41:21 +09:00
acf003b1b4 Do not generate new address when a new payment is detected ()
* Do not generate new address when a new payment is detected

* Update BTCPayServer.Tests/UnitTest1.cs

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>

---------

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2023-05-18 16:53:01 +09:00
52e108d32f Minor design system updates ()
- Update Manage Plugins icon
- Add ESC to supporters sprite
- Update body-text-active variable
2023-05-17 10:19:26 +02:00
7b96f96025 bump clightning ()
* bump clightning

* Remove Lightning Charge from our tests
2023-05-16 09:17:21 +09:00
8db5e7e043 Plugins: Allow payout processors to signal they cannot be removed through common UI 2023-05-15 09:49:13 +02:00
25fb5c1293 Checkout v2: Improve expired paid partial state ()
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2023-05-11 10:38:40 +02:00
37f0498def adds payouts settings button ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-05-11 10:37:28 +02:00
02110f93d7 Hide sensitive info () 2023-05-11 10:35:51 +02:00
195dfc2c47 Refund updates () 2023-05-11 10:33:33 +02:00
541b6cf9eb Improve create first store case () 2023-05-10 11:18:29 +02:00
2c26b77afc Forms: Add multiline input () 2023-05-10 11:14:19 +02:00
99bcec5597 bump nbx 2023-05-09 22:06:23 +09:00
781190a65d Bump to 1.9.3 ()
* Bump to 1.9.3

* Apply suggestions from code review

* Update Changelog.md

* Update Changelog.md

* Update Changelog.md

* Update Changelog.md

Co-authored-by: d11n <mail@dennisreimann.de>

* Update Changelog.md

Co-authored-by: d11n <mail@dennisreimann.de>

* Update Changelog.md

Co-authored-by: d11n <mail@dennisreimann.de>

---------

Co-authored-by: d11n <mail@dennisreimann.de>
2023-05-08 21:30:43 +09:00
3763480280 NFC: Handle HTTP-related exceptions () 2023-05-08 12:11:42 +02:00
6fad5ebedb Do not crash checkout when attempting lnurl checkout through non secure page ()
Co-authored-by: d11n <mail@dennisreimann.de>
2023-05-08 12:09:48 +02:00
0690194aa1 Fix posdata with primitive array ()
Co-authored-by: d11n <mail@dennisreimann.de>
2023-05-08 11:02:13 +02:00
03b94e2be3 Minor refactoring about DefaultPaymentMethod 2023-05-08 09:14:58 +09:00
18e34b3cbe Checkout v2: Improve truncation of displayed addresses () 2023-05-05 10:00:55 +02:00
a0bb3ace61 LN Settings: Show only node host name () 2023-05-05 09:59:33 +02:00
920ad67633 Rates: Fix advanced rules example formatting
Fixes .
2023-05-05 09:58:42 +02:00
8b8f72129c Crowdfund: Fix redirect URL fallback
As the request for invoice creation is issued via web socket, the display URL ends up being the hob connection URL. This replaces it with the actual app URL and fixes .
2023-05-05 09:57:44 +02:00
b9b11e722c Greenfield: Apply store default payment method on invoice creation
Fixes .
2023-05-05 09:56:23 +02:00
eddd458744 Fix missing shopify link
fixes 
2023-05-05 09:51:45 +02:00
439ea20a89 Resolving weird Firefox form autocomplete behavior on our POS () 2023-05-04 18:49:35 +02:00
cec223c8e7 Fix missing closing div () 2023-05-03 10:55:20 +02:00
25cb188d00 Bumping LND to 0.16.2-beta 2023-04-29 09:10:07 -05:00
31007a8d96 Merge pull request from dennisreimann/esc
Supporters: Add ESC
2023-04-27 18:30:09 +02:00
a4fa8db69b Supporters: Add ESC 2023-04-27 18:28:29 +02:00
6193835ea1 Make LightningListener nullable, fix some NRE 2023-04-27 13:37:32 +09:00
0c78e9e4ac Bumping LND to 0.16.1-beta () 2023-04-27 13:17:57 +09:00
58c409e7fa Fix tests 2023-04-27 13:00:25 +09:00
9577eed524 Validate input in greenfield for payout processors () 2023-04-27 10:59:19 +09:00
76f32cd064 Fix payment request overriding user provided email 2023-04-26 14:06:42 +02:00
92d9c17095 Fix payment request merge conflict marker in UI 2023-04-26 14:06:23 +02:00
b0396df33f Update changelog 2023-04-26 18:27:06 +09:00
c17572c76f Clip configuration values for payout processors 2023-04-26 18:24:46 +09:00
5c91e072a6 Prevent payout processors from stalling restart 2023-04-26 18:09:56 +09:00
4991d0f965 Update Changelog and bump version 2023-04-26 17:57:25 +09:00
45b74e1ce5 Fix cart receipt + fix pos email form forwarding ()
* Show correct array regardless of size

fixes 

* Email provided to pos form was not forwarded to form

fixes 

* Make invoice receipt url redirect to the invoice redirect url if receipt is not enabled

When setting up a default email rule upon invoice settlement, you would link to the receipt page naturally. However, if using the payment requests, receipts are disabled as the payment request itself is the receipt.  This commit makes the receipt url redirect to the invoice redirect url if available, and in the case of payment requests, it would mean the receipt url is the payment request url. fixes 

* Set the email address in the form when configured in the payment request

* fix pay request email copy

* fix payouts nav link

fixes 

* Update BTCPayServer/Views/UIPaymentRequest/EditPaymentRequest.cshtml

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>

---------

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-04-26 16:45:35 +09:00
ccb4b9a9ba Merge pull request from dennisreimann/receipt-print
Receipt: Optimize print view
2023-04-26 15:41:41 +09:00
dd635071d6 Merge pull request from dennisreimann/fix-4889
POS: Fix choiceKey case
2023-04-26 15:16:54 +09:00
fe1448dfae Merge pull request from NicolasDorier/qiponbtq
Remove LNURLStandardInvoiceEnabled
2023-04-26 15:15:20 +09:00
56855bc54d Fix typo in PayJoinEndpointController.cs () 2023-04-25 22:29:06 +02:00
b51fa8df5a Fix indent 2023-04-25 21:03:12 +09:00
3aa979cb11 Test updates 2023-04-25 13:07:01 +02:00
c95f75bc6c Remove disable BOLT11 option 2023-04-25 12:21:27 +02:00
b13a636f89 Fix syntax error 2023-04-25 12:11:08 +02:00
8de55cef31 Unify checkout v1 behaviour with v2 2023-04-25 11:36:45 +02:00
cb781f42e3 POS: Fix choiceKey case
I came across this while debugging . This does not actually fix it, but it fixes an inconsistence in the casing of the parameter name.

However, I think the original issue is a caching problem in the browser. I was able to reproduce it on first load, after reloading the page once more it works as intended. The weird thing is: even though the values are correct on first load (verified via debugger), the `choiceKey` for the first item is set incorrectly to an integer value.
2023-04-25 09:16:09 +02:00
b59292dc24 Receipt: Optimize print view
Fixes 
2023-04-25 07:30:15 +02:00
03b793d7e2 Fix tests 2023-04-25 10:28:36 +09:00
bee18d1cfb Can set LazyPaymentMethod at the invoice creation level 2023-04-25 08:38:42 +09:00
d8698181f4 Remove LNURLStandardInvoiceEnabled 2023-04-24 23:52:40 +09:00
47f5d97eaf Prevent an NRE in LNURL ()
* Prevent an NRE in LNURL

In addition to f05a7f9f14e0a2f906c79951a15311085774db85. Fixes .

* Revert "Prevent an NRE in LNURL"

This reverts commit 0b241d61ab45b79297211e04da0e05c2cb10dada.

* Fix NRE

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-04-24 21:50:31 +09:00
cb3c5e56fd Fix: Poll of Lightning Invoice status might fail on LND if LNURL is used () 2023-04-24 18:15:39 +09:00
39b76c08de Fix: Form in Payment Requests was not setting its values to the invoices metadata () 2023-04-24 18:04:46 +09:00
c3c8cc21ff Security Page Refactor ()
* Update SECURITY.md

* typo

* project vs product

* Suggestion Update - Docker Deployment

Co-authored-by: d11n <mail@dennisreimann.de>

* Suggestion - Email highlight

Co-authored-by: d11n <mail@dennisreimann.de>

---------

Co-authored-by: d11n <mail@dennisreimann.de>
2023-04-24 15:04:56 +09:00
6dba1b6d8b Nullable on LanguageService 2023-04-20 09:44:24 +09:00
381fe70a79 Add UserAgent to IPN and webhook HTTP requests (Fix ) 2023-04-19 21:13:31 +09:00
feb927c2e4 Add missing param, fix response code. () 2023-04-19 13:07:36 +09:00
e77bd4c188 Swagger: FIx typos in pull payments docs ()
Fixes .
2023-04-19 13:06:51 +09:00
43436fc49e Remove BTCPayServer.Plugins.Test ()
Remove the plugin, which is superseded with the plugin template and move the PluginPacker to the root of th solution (which matches its location in the file system).
2023-04-17 11:38:03 +09:00
d738f797ec bump 2023-04-17 11:11:00 +09:00
b5de97f785 Update changelog 2023-04-17 10:54:00 +09:00
b0c1b0895d Fix crash if auto detect language on checkout page, and the language couldn't be detected (Fix ) () 2023-04-17 10:53:45 +09:00
8e60932f81 Migrate reference to AppType in server settings (Fix ) 2023-04-17 10:34:41 +09:00
7d14cd74f2 LightningLikePaymentData: Null-check preimage ()
Fixes .
2023-04-17 00:08:40 +02:00
717f1610f5 Update changelog 2023-04-13 16:28:30 +09:00
f1abe6497f Fix wrong data mapping to store data instead of store user data. () 2023-04-13 16:27:40 +09:00
046129a57d Bumping LND to 0.16.0-beta () 2023-04-13 14:48:47 +09:00
90d300a490 Remove superflous category in API doc 2023-04-13 08:41:46 +09:00
a2d506c0db Checkout v2: Confetti for processing payments ()
Let's not spoil the fun for those paying on-chain.
2023-04-13 08:40:21 +09:00
58748a24da What's New entry for v1.9 ()
Copy is just a proposal from my side. Link check expected to fail, because the blog post isn't up yet.
2023-04-12 20:40:20 +09:00
639e8a4a1d Add links to invoice metadata in the docs () 2023-04-12 16:30:34 +09:00
48ebaf5c5a Do not put payRequest in the metadata () 2023-04-12 16:30:22 +09:00
1aaccb1e6b Do not show empty JObject in AddtionalData of views 2023-04-11 13:21:02 +09:00
f05a7f9f14 Prevent an NRE in LNURL 2023-04-11 13:08:14 +09:00
98ddb348b0 Update changelog 2023-04-10 20:21:13 +09:00
a4aa85ebab Fix: If connection to Lightning node was interrupted, payments would be missed () 2023-04-10 19:35:01 +09:00
516efe56f4 Refactor: Dot not make LNURLPaymentMethodDetails depends on BTCPayInvoiceId ()
* Refactor: Dot not make LNURLPaymentMethodDetails depends on BTCPayInvoiceId

* Abstract PaymentProof

* fix bug

* Make the selenium container resolves the btcpay host name
2023-04-10 16:38:49 +09:00
a4d72d5bbc Fix tests 2023-04-10 15:06:59 +09:00
24b8ec16f1 Fix tests 2023-04-10 13:37:09 +09:00
ac25fef555 Remove warning 2023-04-10 12:01:11 +09:00
8302f082a2 Do not render the TruncateCenter if text null or empty 2023-04-10 11:17:29 +09:00
7546ef7a8e Dotnet reformat 2023-04-10 11:07:03 +09:00
f598c70a4f Add comment TODO for improving automatic translations efficiency. 2023-04-10 11:03:36 +09:00
422da21de5 Update Changelog 2023-04-07 17:52:48 +09:00
f530fb3241 Update changelog 2023-04-07 17:50:57 +09:00
5d39bb7466 Allow LN Address to customize invoice metadata, and various bug fixes on LNUrl ()
* Allow LN Address to customize invoice metadata

solves https://github.com/OpenSats/website/issues/8

* Refactor GetLNUrl

* Fix lightningAddresssettings.Max being ignored

* Fix: The payRequest generated by the callback wasn't the same as the original

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-04-07 17:48:58 +09:00
041cba72b6 Made Fake Custodian config field non-required () 2023-04-07 15:59:44 +09:00
892b3e273f Improve Labeling further ()
* If loading addresses into the send wallet page using bip21 or address,  (or clicking on "Send selected payouts"  from the payotus page), existing labels will be pre-populated.
*  Add the payout label to the address when the payoutis created instead of to the transaction when it is paid.
*  Add the label attachments when adding labels from an address to the transaction.
2023-04-07 15:58:41 +09:00
91faf5756d With core lightning, getting payment by paymenthash wouldn't return the successful payment if the first one failed. 2023-04-07 15:54:56 +09:00
e239390ebf Allow any bolt11 invoice for pullpayments/payouts ()
closes 

If users want to deal with expired payout destinations, then they should be able to conifugre it that way. Some wallets simply do not allow customizing the bolt11 expiry and the defaults are much less than a day. I think we should merge  if we introduce this as an automated payotu processor for lightning running every few minutes would work together with this and solve it.
2023-04-06 15:54:19 +09:00
b24764d679 bump 2023-04-05 23:38:39 +09:00
4d5a568fd7 Changelog 1.9 () 2023-04-05 23:37:01 +09:00
5ab55e71e0 Add cart items to receipt () 2023-04-05 15:42:23 +02:00
929d63ecf8 Fixed nav menu active states + Better Fake Custodian () 2023-04-05 15:11:46 +02:00
0ef7f3715f remove obsolete reference 2023-04-05 15:09:42 +02:00
2298f3901a Update langs () 2023-04-05 13:32:24 +09:00
3005f1937a Replace GetUriByAction by GetPathByAction 2023-04-05 10:58:56 +09:00
f48eec2e93 Fix: Redirecting to local absolute URL in wizard windows should work 2023-04-05 10:55:35 +09:00
754d304e54 Fix tx link in Recent Transactions 2023-04-05 08:53:34 +09:00
9b8d08a668 Make Checkout V2 the default ()
* Make Checkout V2 the default

* Fix align
2023-04-05 08:35:50 +09:00
1b672a1ace Allow multi-step settings in custodian ()
* Allow multi-step settings in custodian

* Fix CustodianAccount.Name not saved

* Reuse TradeQuantity for SimulateTrade

* TradeQuantityJsonConverter accepts numerics

* Fix build
2023-04-04 14:48:29 +09:00
60d6e98c67 Form System Flexibility improvements ()
* Introduce very flexible form input system

* Refactorings after rebase

* Test fix

* Update BTCPayServer/Forms/FormDataService.cs

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-04-04 11:01:34 +09:00
11f05285a1 Invoice Details: Improve payments list and print view ()
Closes .

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-04-04 10:59:14 +09:00
2bd1842da1 Improve pagination ()
Based on the design repo updates by @benalleng in btcpayserver/btcpayserver-design#61. Closes .
2023-04-04 10:54:04 +09:00
57544068e9 Store rule emails in HTML + Test rule emails ()
* Store rule emails in HTML + Test rule emails

* Store rule emails in HTML + Test rule emails

* Update BTCPayServer/Controllers/UIStoresController.Email.cs

Thanks !

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>

* change in StoreEmails() to work properly with add commande

* CanSetupEmailServer() : Remove Bosy sendkeys that doesn't work with new HTML control

* Update test for new HTML control

* better command treatment

---------

Co-authored-by: nisaba <infos@nisaba.solutions>
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2023-04-04 10:52:42 +09:00
60cfea9f94 Add presets in the checkout appearance () 2023-04-04 10:45:40 +09:00
eece001376 Add labels for recent txs dashboard widget ()
* Add labels for recent txs dashboard widget

It is not with the rich data for now, but a good start.

* Turn labels into links

* Add rich info to dashboard labels

* Use truncate-center component for recent transactions

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-03-30 19:54:11 +02:00
98d8ef8e1a Checkout Appearance: Move language settings into the general section ()
The language settings work for both versions of the checkout, so let's make them available for both. Request by @petzsch.
2023-03-30 08:18:13 +02:00
0e43042217 Remove FakeCustodian as a separate project () 2023-03-30 12:38:30 +09:00
c8e6714207 Merge pull request from dennisreimann/unify-plugins-apps
Apps become plugins
2023-03-29 20:03:18 +02:00
824e779eb2 Hooks for Zaps () 2023-03-29 12:27:04 +02:00
83ea898780 Checkout: Update wording ()
We make it "Payment Received" instead of "Payment Sent", because in other places we are also talking from the merchant perspective.
2023-03-29 17:24:49 +09:00
5af3233fd6 Add link to forms doc 2023-03-28 22:02:58 +09:00
08ff2f3173 Checkout: Fix language select width in modal () 2023-03-28 13:12:47 +02:00
22657b66d7 NFC finetuning () 2023-03-28 12:36:32 +02:00
8b6c7a6061 Pull Payments: FIx column order in list ()
Date and name were swapped. Fixes .
2023-03-28 19:10:50 +09:00
1f197f6688 Merge pull request from dennisreimann/nfc 2023-03-28 09:19:58 +02:00
1055e61bb4 NFC improvements
Two changes which fix :

- Once permissions are granted we start scanning immediately, no need to ask for permissions or have the user click the button again
- We don't abort the scan, which gets rid of the cases in which the OS took over after the scan, because the user left the card on the device

Also adds feedback for the NFC states scanning and submitting.
2023-03-27 18:28:53 +02:00
7ad0aa82fc Apps become plugins
Unified navigation for apps that are now plugins. Part of .
2023-03-27 16:43:44 +02:00
d3f5576570 Remove store integrations list page ()
Co-authored-by: d11n <mail@dennisreimann.de>
2023-03-27 16:40:50 +02:00
45141d1391 Checkout v2: Payment processing state () 2023-03-27 12:12:11 +02:00
de9ac9fd43 Receipt: Add payment proof ()
* Receipt: Add payment proof

Closes .

* shice

* Add truncate-center component

* Improve view

* Hide button and link when printed

* Describe component

* Remove transaction ID from UI

* Remove modification to interface

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-03-27 14:07:12 +09:00
c53d5272d6 Wallet Transactions Export: Add BIP-329 support ()
* Wallet Transactions Export: Add BIP-329 support

* Adjust wording

* Export one line per label

* Join labels, fix type

* Rewrite the ProcessBip329 function to be more performant

* Add nullable on all TransactionsExport

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-03-27 13:59:33 +09:00
18c78192ec Reconstruct issue template ()
* reconstruct issue template

* provide a direct link for filing a tech question
2023-03-27 13:59:07 +09:00
632d67eef4 Fix casing in template example for forms 2023-03-27 12:54:12 +09:00
c23aa48688 Optimize invoice print view ()
Closes .
2023-03-26 20:44:05 +09:00
95f3e429b4 Wallet transactions: Add label manager ()
* Wallet transactions: Add label manager

* Update BTCPayServer/Views/UIWallets/WalletTransactions.cshtml

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>

* Add rich label info

* Fixes

* support labels in wallet send

* add labels to tx info page

* Remove noscript parts

* Allow click on transaction label info

* update psbt info labelstyling

* revert red pixel fix as it broke all

---------

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2023-03-26 20:42:38 +09:00
8635fcfe84 UI: Redesign Recovery Seed view ()
* Improve recovery seed backup page

* Fix errors from Selenium tests (Sequence contains no elements)

* Revert previous commit

* Improve recovery seed backup page

* Recovery phrase UI update

* recovery seed UI format

* Improve word order

* One column version

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-03-24 16:09:53 +01:00
d861537d9a Merge pull request from dennisreimann/gf-ln-array-fix
Greenfield: Fix Lightning transaction list return types
2023-03-23 18:59:36 +01:00
631ee99f60 Greenfield: Fix Lightning transaction list return types
The LocalBTCPayServerClient deserializes the results as arrays (`LightningPaymentData[]` and `LightningInvoiceData[]`) — if they are `IEnumerable` the `GetFromActionResult` does not return the data but null.
2023-03-23 17:42:10 +01:00
ffa1441ccd Delete code detecting whether the running version of nbx fixed a bug
The reason to delete this is that any version of NBX with this bug
wouldn't be able to run nowadays because of another bug which would
prevent NBXplorer from synching (Array size too big)
2023-03-23 13:45:40 +09:00
2f3e947027 Merge pull request from Kukks/lnurl-disable-if-no-node 2023-03-22 09:02:52 +01:00
a62aecfdfe Merge pull request from dennisreimann/fix-4794 2023-03-22 09:02:35 +01:00
5f829c68f2 Merge pull request from dennisreimann/fix-4790 2023-03-22 09:02:10 +01:00
0290d74aeb POS: Fix escaped HTML entities in item title
Properly escapes and the sanitized values. Fixes .
2023-03-21 15:31:54 +01:00
f6bc16007d Label tooltips: Use plain text instead of HTML
Fixes .
2023-03-21 15:21:24 +01:00
ad5752f09b Reuse LightningTimeout constant 2023-03-21 14:22:10 +01:00
55565f1718 Do not provide lnurl method if ln node is dead
fixes 
2023-03-21 13:48:25 +01:00
5f96d17b8c Update lang 2023-03-20 19:30:56 +09:00
fd22406e0a Fix PullTransifexTranslationsCore 2023-03-20 19:21:35 +09:00
64fe542c1e Update lang 2023-03-20 19:20:46 +09:00
fae1dc8dbb Adapt cookie auth to work with same API permission system ()
* Adapt cookie auth to work with same API permission system

* Handle unscoped store permission case

* Do not consider Unscoped as a valid policy

* Add tests

* Refactor permissions scopes

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-03-20 10:46:46 +09:00
6f2b673021 Custodian withdrawal support + Some refactoring and cleanup ()
* Renamed "WithdrawAsync" to "WithdrawToStoreWalletAsync"

* WIP

* WIP withdrawal + Refactored Form saving to JObject

* WIP

* Form to fix bad values during withdrawing appears correctly

* WIP

* Lots of cleanup and refactoring + Password field and toggle password view

* Cleanup + Finishing touches on withdrawals

* Added "Destination" dummy text as this is always the destination.

* Fixed broken test

* Added support for withdrawing using qty as a percentage if it ends with "%". Needs more testing.

* Fixed broken build

* Fixed broken build (2)

* Update BTCPayServer/wwwroot/swagger/v1/swagger.template.custodians.json

Co-authored-by: d11n <mail@dennisreimann.de>

* Update BTCPayServer/wwwroot/swagger/v1/swagger.template.custodians.json

Co-authored-by: d11n <mail@dennisreimann.de>

* Improved unit tests

* Fixed swagger bug

* Test improvements

Make string conversion of quantity explicitely.

* Fix build warnings

* Swagger: Add missing operationId

* Made change Dennis requested

* Removed unused file

* Removed incorrect comment

* Extra contructor

* Renamed client methods

* Cleanup config before saving

* Fixed broken controller

* Refactor custodian

* Fix build

* Make decimal fields strings to match the rest of Greenfield

* Improve parsing of % quantities

---------

Co-authored-by: d11n <mail@dennisreimann.de>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-03-20 10:45:32 +09:00
b26679ca14 Prevent people from starting with --sqlitefile or --mysql () 2023-03-20 10:40:48 +09:00
04ba1430ca Refactor plugin apps ()
* Refactor plugins

* Add missing names to view models

* Cleanups

* Replace SalesAppBaseType by two interfaces

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-03-20 10:39:26 +09:00
53f3758abc Replace text in copy buttons with icon ()
Closes .
2023-03-19 21:43:38 +01:00
c6742f5533 Language selector: Ensure correct font-size ()
* Language selector: Ensure correct font-size

Fixes the cut-off text on iOS, because somehow iOS uses a larger font-size by default.

* Fix select background color

Webkit-based browsers displayed transparent in a weird way.
2023-03-19 08:44:23 +01:00
cb44591a47 Derivation scheme parsing incorporates fingerprint and key path () 2023-03-17 14:35:30 +01:00
e02abb509f Allow plugins to do something before and after automatic payouts () 2023-03-17 13:50:37 +01:00
eff6be9643 Remove mention of LNUrl-Withdraw when paying by NFC () 2023-03-17 12:24:27 +01:00
348dbd7107 Support Form Select option ()
* Support Form Select option

* Add country select
2023-03-17 14:37:37 +09:00
f74ea14d8b Plugins can now build apps ()
* Plugins can now build apps

* fix tests

* fixup

* pluginize existing apps

* Test fixes part 1

* Test fixes part 2

* Fix Crowdfund namespace

* Syntax

* More namespace fixes

* Markup

* Test fix

* upstream fixes

* Add plugin icon

* Fix nullable build warnings

* allow pre popualting app creation

* Fixes after merge

* Make link methods async

* Use AppData as parameter for ConfigureLink

* GetApps by AppType

* Use ConfigureLink on dashboard

* Rename method

* Add properties to indicate stats support

* Property updates

* Test fixes

* Clean up imports

* Fixes after merge

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-03-17 11:56:32 +09:00
a671632fde Dashboard: Fix app stats tiles ()
* Dashboard: Fix app stats tiles

They broke with , because they contain script blocks that are loaded asynchronuosly and need to get run once the chart data is added to the page.

* Refactor PoS dashboard component

* Collocate the component JS files in separate files

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-03-16 15:51:24 +09:00
e344622c9e Form quick fixes () 2023-03-15 10:23:33 +01:00
06d7483ca3 Remove obsolete cli argument 'plugin-remote' () 2023-03-15 09:06:06 +01:00
7fe041fc2c Changelog 1.8.4 2023-03-15 10:45:49 +09:00
3f18e5476a Error when indexing invoices with some field that are too long (Fix ) 2023-03-15 09:31:38 +09:00
2a31613fe8 Fix invoice paid after expiration icon 2023-03-14 14:54:01 +01:00
ded0c8a3bc Update price display ()
* Update price display

As proposed by @dstrukt in .

* Update format

* Unify price display across the app

* Add DisplayFormatter

* Replace DisplayFormatCurrency method

* Use symbol currency format for invoice

* Unify currency formats on backend pages

* Revert recent changes

* Do not show exchange rate and fiat order amount for crypto denominations

* Fix test and add test cases
2023-03-13 10:12:58 +09:00
f3d9e07c5e Checkout v2: Celebrate payment with confetti ()
* Checkout v2: Celebrate payment with confetti

Have a colorful celebration for successful payments.

* Make it default and add test
2023-03-13 10:09:56 +09:00
eb3ba95114 Make CanUsePullPaymentsViaUI more robust ()
Fixes this nasty flaky test failure:

```
Failed CanUsePullPaymentsViaUI [17 s]
  Error Message:
   Assert.Equal() Failure
           ↓ (pos 1)
Expected: payout
Actual:   pull-payment
           ↑ (pos 1)
  Stack Trace:
     at BTCPayServer.Tests.ChromeTests.CanUsePullPaymentsViaUI() in /source/BTCPayServer.Tests/SeleniumTests.cs:line 1622
```

Because there are actually two labels, the previous selector was dependent on the correct ordern, because it always chose the first one …
2023-03-13 10:02:07 +09:00
7951dcada6 make sure we have cors for all of greenfield ()
fixes 
2023-03-10 15:20:11 +01:00
06951a39c6 fix API breaking changefor payout processors ()
fixes 
2023-03-10 17:57:33 +09:00
abe29f21f0 Checkout v2: Option to display amount in Sats in BIP21 case () 2023-03-09 21:36:11 +01:00
f57eab3008 Store branding: Add complementing text and accent colors () 2023-03-09 21:34:15 +01:00
6d4b2348ac Update changelog 2023-03-08 21:56:40 +09:00
397ca6ef0c Checkout v2: Minor UI updates ()
* Checkout v2: Minor copy change

* Allow copying of invoice ID and order ID on results page

* Add copy icons for payment details on results view

* Add missing powered by class to store footers
2023-03-08 21:39:03 +09:00
d6e5ee2851 UI: Decrease content padding top on small screens ()
If the viewport height is less than 800px, decrease the content padding top for breakpoints L and on.
2023-03-08 21:37:25 +09:00
98d62e826b Do not through missing-permission error when no store on /api/v1/stores (Close ) () 2023-03-08 21:36:51 +09:00
7b5ce8f70c CSP: Remove unsafe-eval when vue isn't used ()
* CSP: Remove unsafe-eval when vue isn't used

* Prevent XSS injection via VueJS
2023-03-08 17:57:36 +09:00
2010a9a458 bump 2023-03-07 10:29:18 +09:00
f787058c17 Fix: Impossible to create invoice after migration from Sqlite (Close ) 2023-03-07 10:27:04 +09:00
87ccae0d90 add missing docs of store payment method criteria 2023-03-05 14:40:18 +01:00
07d95c6ed7 bump clightning 2023-03-05 11:08:01 +09:00
514823f7d2 bump clightning 2023-03-04 21:39:49 +09:00
fb4feb24f3 Minor updates from design repo () 2023-03-04 09:36:30 +01:00
5caa0e0722 [Greenfield] Allow passing email instead of user id in API () 2023-03-03 21:24:27 +09:00
0406b420c8 Do not create if create API key is called on a non-existant user (Fix ) 2023-03-03 20:30:54 +09:00
9d72b9779e Update Changelog 2023-03-03 20:20:59 +09:00
fdc47e4a38 Avoid crash when some plugins are installed () 2023-03-03 20:18:09 +09:00
0566e964c0 Fix incorrect punctuation in translations 2023-03-03 17:32:46 +09:00
896fbf9a5c Lang update 2023-03-03 16:38:39 +09:00
126c8c101e Re-add language selector ()
Fixed version
2023-03-02 16:34:15 +09:00
3cb7cc01e4 Update db-migration.md 2023-03-02 13:20:47 +09:00
2b3d15bf45 Update Changelog.md 2023-03-01 23:50:35 +09:00
4049bdadcb Changelog v1.8 ()
* Changelog v1.8

* Update Changelog.md

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>

* Add fix

* Update changlelog

---------

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-03-01 23:41:43 +09:00
2042ba37d8 Update What's New ()
Links to https://blog.btcpayserver.org/btcpay-server-1-8-0/ which doesn't exist yet, that's why the linkcheck is expected to fail.
2023-03-01 23:41:27 +09:00
41a4ba62b0 Remove lang popup in checkout v2 2023-03-01 17:10:54 +09:00
21558d25b1 Do not show product information if there are no product information 2023-03-01 16:19:10 +09:00
06622bfbfd Translate Checkout v2 () 2023-03-01 15:49:21 +09:00
16fd2e3938 Greenfield: Show detailed Lightning routing error ()
The implementations have more detailed messages for LN routing errors, which e.g. allow me to detect self-payemnts in LNbank. We pass those from the LN lib, so if we have it, we should display it to provide a better insight on what's going on when a rout cannot be found.
2023-03-01 15:46:48 +09:00
040d7670ec Add currency code to payment request list ()
https://github.com/btcpayserver/btcpayserver/discussions/4619
2023-03-01 15:46:13 +09:00
23761eacc1 Unset X-Frame-Options header correctly ()
* Unset X-Frame-Options header correctly

According to the [spec](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options) there are onlye the `DENY` and `SAMEORIGIN` options, `ALLOW-FROM` being deprecated. Hence we have to actively unset the header, as we made `DENY` the default.

This also unsets the X-Frame-Options header for the public form pages, which fixes .

* Ignore anti forgery token in Forms

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-03-01 15:27:18 +09:00
5790bed766 Do not crash sqlite migration if the db is create but without tables 2023-03-01 15:04:32 +09:00
2f88da67e8 Fix build warnings and indentation () 2023-03-01 10:32:48 +09:00
21091cbf1a show all plugins regardless of version () 2023-02-28 12:16:33 +01:00
808949a884 Update langs 2023-02-26 21:07:23 +09:00
06334273dc Fix crashing on unserialize of old data 2023-02-26 11:18:54 +09:00
5399c04dff Fix crashing on unserialize of old data 2023-02-26 11:05:23 +09:00
cd051d4093 Update transaction label display ()
* Update transaction label display

* Fix test
2023-02-26 11:01:46 +09:00
0ca6e8ccfb bump 2023-02-26 00:20:55 +09:00
bd075919f3 Improve publish docker script 2023-02-26 00:19:59 +09:00
c229425534 Remove JSON in strings from JObjects () 2023-02-25 23:34:49 +09:00
e89b1826ce add invoicemetadata as a tab ()
* add invocie metadata as a tab

* Allow forms to add to posdata too in pos app

* Cleanup view

* Display additional information directly

* Update BTCPayServer/Views/Shared/PosData.cshtml

* Update BTCPayServer/Models/InvoicingModels/InvoiceDetailsModel.cs

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-02-25 22:38:28 +09:00
4ef19e19cc Checkout v2 fixes ()
* Prevent duplicate titles on invoice view

* Fix text display of escaped values

Fixes .

* Fix payment details re-rendering

Closes . Closes .

* Cleanup
2023-02-25 22:28:02 +09:00
ff58301729 do not require docker for plugin restart
we now have a more graceful restart mechanism specifically for plugins and most installs can handle this mechanism
2023-02-24 13:52:46 +01:00
4ae05272c3 Greenfield: Admins can create/delete API keys of any user ()
* Greenfield: Admins can create/delete API keys of any user

* Greenfield: Improve doc for scoped apikey (Close )

* Fix permissions hierarchy

* Update BTCPayServer.Client/Permissions.cs

* Fix tests

---------

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2023-02-24 16:19:03 +09:00
d14dafc871 Apply branding to custom forms () 2023-02-23 14:35:29 +01:00
022a077726 Use new transifex API on PullTransifexTranslations 2023-02-23 20:59:16 +09:00
d5bd86b07a POS: Align Keypad centered vertically () 2023-02-23 10:30:16 +01:00
66e1eee010 POS improvements () 2023-02-23 09:52:37 +01:00
ddb125f458 Fix: HTML injection in payment request/posData/receiptData (Close ) ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-02-22 16:35:34 +01:00
e6a157a101 Merge pull request from dennisreimann/noscript-fix 2023-02-22 14:01:13 +01:00
0a437fba6a Do not show Vue components when there is no JavaScript enabled
Small fix, came across this while testing the noscript checkout version.
2023-02-22 13:34:51 +01:00
39f2e80dc1 Merge pull request from dennisreimann/fix-4663 2023-02-22 12:30:16 +01:00
13f9eb0d18 Cleanups and unified wording 2023-02-22 11:20:50 +01:00
575b829799 Fix LNURL-Withdraw payments
Fixes comparisons of `long` and `LightMoney`, which did not work, because the `amount` provided was in sats and Lightmoney compares to millisats.

Closes .
2023-02-22 11:18:26 +01:00
02e50fadae Fix: Crash during migration on some SQLite instances (Close ) 2023-02-22 17:07:27 +09:00
a02f191034 Fix: Crash during migration on some SQLite instances (Close ) 2023-02-22 16:55:19 +09:00
d73d0f178f Checkout: Allow NFC/LNURL-W whenever LNURL is available ()
* Checkout: Allow NFC/LNURL-W whenever LNURL is available

With what we have in master right now, we display NFC only for top-up invoices. With these changes, we display NFC in all cases, where LNURL is available.

Note that this hides LNURL from the list of selectable payment methods, it's only available to use the NFC — and explicitely selectable only for the edge case of top-up invoice + non-unified QR (as before).

Rationale: Now that we got NFC tightly integrated, it doesn't make sense to support the NFC experience only for top-up invoices. With this we bring back LNURL for regular invoices as well, but don't make it selectable and use it only for the NFC functionality.

* Fix LNURL condition

* Improve and test NFC/LNURL display condition

Restores what was fixed in .

* Fix and test Lightning-only case

* Add cache busting for locales
2023-02-22 15:53:14 +09:00
d542a61f5a Fix missing walletchanged event and add storeremoved event () 2023-02-22 13:13:58 +09:00
e0486aaa24 Label Manager component ()
* Label Manager component

closes 

* UI updates

* Test fix

* add test

* fix warnings

* fix select update bug

* add test

* fix test

* Increase payment box max-width

* add labels from address to tx on detection

* Exclude well known label from the dropdown

* Add test on transaction label attachement, tighten UpdateLabels method to only update address labels

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-02-22 11:47:02 +09:00
02bf76fb3c Merge pull request from Kukks/gf/pmcriteria 2023-02-21 16:03:29 +01:00
8a3ece4a70 add test 2023-02-21 15:31:11 +01:00
c553dc02a9 Greenfield: Expose Payment method criteria 2023-02-21 15:23:51 +01:00
ff71caa47e Upgrade Lightning lib ()
To include the fix from 
2023-02-21 16:00:10 +09:00
2bd8227e20 Start using JSONB column instead of app side compressed data () 2023-02-21 15:06:34 +09:00
5c61de3ae9 Different icons for notifications ()
* Different icons for notifications

Closes .

* Fix version appendix for SVG use attributes

* Fix SVGUse TagHelper

* Update icons
2023-02-21 11:06:27 +09:00
cff46f2d59 UI: Remove highlight for valid fields () 2023-02-20 19:23:09 +01:00
bbbaacc350 Generic Forms ()
* Custom Forms

* Update BTCPayServer.Data/Migrations/20230125085242_AddForms.cs

* Cleanups

* Explain public form

* Add store branding

* Add form name to POS form

* add tests

* fix migration

* Minor cleanups

* Code improvements

* Add form validation

Closes .

* Adapt form validation for Bootstrap 5

* update logic for forms

* pr changes

* Minor code cleanup

* Remove unused parameters

* Refactor Form data handling to avoid O(n3) issues

* Rename Hidden to Constant

* Pre-populate FormView from the query string params

* Fix test

---------

Co-authored-by: d11n <mail@dennisreimann.de>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-02-20 19:35:54 +09:00
60f84d5e30 Display "Pay by LNURL" only when appropriate ()
Closes .
2023-02-20 08:49:10 +09:00
5218aa3c43 Fix missing style tag around embedded CSS () 2023-02-18 20:38:02 +09:00
4b2ea0c0c3 Fix: Should not crash with command line arg --help 2023-02-16 18:32:26 +09:00
9b865ef849 Fix build and run scripts () 2023-02-16 18:31:33 +09:00
9344113ae4 Version bump 2023-02-16 17:46:27 +09:00
4448ac9d2a Changelog 1.7.12 () 2023-02-16 17:45:51 +09:00
9aff143d40 UI: Fix standalone confirmation modal 2023-02-15 16:17:22 +01:00
fc14f418cb Fix: Setting the password of a new created user via API shouldn't be required (Close ) () 2023-02-15 17:11:39 +09:00
b99253ff47 Revert "Fix: Setting the password of a new created user via API shouldn't be required (Close ) ()" ()
This reverts commit 9cb844cbbbd4118442d85e6d7a3031f3e1e6ed5b.
2023-02-15 16:32:36 +09:00
9cb844cbbb Fix: Setting the password of a new created user via API shouldn't be required (Close ) () 2023-02-15 16:32:03 +09:00
285aedef2f Fix: If user get locked out, unlocking or deleting user fails (Fix ) ()
This is due to the fact our UserService is a singleton, and it had a
reference on UserManager which is scoped.

UserManager is caching user entities at the scope level.
UserService then had a view completely unsynchronized with the database.
2023-02-15 16:00:52 +09:00
5121d64022 Fix: Migrating from SQLite was crashing in some conditions (Close ) 2023-02-15 15:59:45 +09:00
8b80910d70 Fix: Unable to Edit amount when cloning paid Payment Request (Close ) 2023-02-15 15:33:26 +09:00
a5ff655eed Fix: If user get locked out, unlocking or deleting user fails
This is due to the fact our UserService is a singleton, and it had a
reference on UserManager which is scoped.

UserManager is caching user entities at the scope level.
UserService then had a view completely unsynchronized with the database.
2023-02-15 14:28:34 +09:00
cc9c63c33e Add list count to user preferences cookie ()
I think it's fair to assume that the user wants to set this as a preference and it fixes .
2023-02-15 11:04:17 +09:00
87eef72289 fix typo in vaultbridge.ui.js ()
targetting -> targeting
2023-02-14 19:20:03 +01:00
8e8ba3d052 Webhook: Add missing model validation ()
Fixes .
2023-02-14 22:37:35 +09:00
fea27b900c Harden file type inputs () 2023-02-14 17:03:12 +09:00
7ad91a76cd Checkout v2: FIx automatic redirect after paid () 2023-02-14 08:56:00 +09:00
a62b674722 bump 2023-02-13 23:40:32 +09:00
350f35b08d Add code comment 2023-02-13 23:39:55 +09:00
f405321abc Changelog 1.7.11 () 2023-02-13 23:35:33 +09:00
0d077f6ce5 Fix lnurl for pull paymentdescription + fix authorize redirect form issue ()
fixes 
fixes 
2023-02-13 23:34:43 +09:00
dffa6accb0 Fix XSS: Stenghten CSP rules on static file uploads () 2023-02-13 23:04:15 +09:00
b5abcd5ae5 Merge pull request from dennisreimann/domain-mapping 2023-02-13 13:41:34 +01:00
72a9e676c1 Feature Descriptor () 2023-02-13 09:25:24 +01:00
3658b396d3 Update db-migration.md 2023-02-11 21:04:43 +09:00
537acab16d Update db-migration.md 2023-02-11 21:04:28 +09:00
8c6fe91c71 After successful migration from SQLite or MySql, there is an error after a restart 2023-02-11 21:01:36 +09:00
3c344331af Improve domain mapping constraint
- Fix potential double assignment to appId, leading to an [exception](https://pastebin.com/j8dhtcTE)
- Add port to redirect, which makes it work in dev env
2023-02-10 18:15:54 +01:00
d14ce2a37f POS: Improve Keypad view ()
* UI updates

* Updates modes and calculation

* Unify tip buttons

* White caret

* Add top margin to calculation

* Add space between mode buttons and keypad

* Discount updates
2023-02-10 16:26:38 +01:00
33d272d4b0 Crowdfund: View updates ()
* Crowdfund: View updates

Improve store branding and remove the card styles, because they had borders which seemed like visual clutter. Other than that I made some changes to the header section and cleaned up the markup and indentation.

* adds column spacing + details header

* Move the Featured Image input

* Center align the Last Updated

* Remove store header, update header section

* Bump description font size

* Improve perk display

* Improve details section

* Fix main image display

---------

Co-authored-by: dstrukt <gfxdsign@gmail.com>
2023-02-10 16:26:09 +01:00
57f5c15670 Merge pull request from btcpayserver/Kukks-patch-1 2023-02-10 09:45:30 +01:00
487faa69c6 Bump version 2023-02-10 09:40:03 +01:00
9148a1e564 fix 2023-02-10 09:10:10 +01:00
4c3f5e1e1a fix 2023-02-10 08:59:18 +01:00
b0bf0824dd Update db migration doc 2023-02-10 15:48:43 +09:00
dea5991e01 bump 2023-02-10 11:53:17 +09:00
739932a280 Changelog 2023-02-10 11:52:37 +09:00
1f8bc5b490 Add ability to migrate from MySQL and SQLite with EF () 2023-02-10 11:43:46 +09:00
753ffd401b BIP21 + LNURL fix ()
In case of the unified invoice, the LNURL wasn't correct — with this change we are simply reusing th one that was issued on invoice creation instead of generating it anew on the fly.

Also fixes missing uppercasing for the QR code in case of non-unified QR.
And removes the `lightning:` scheme from the LNURL that's displayed to the user (unifies it with what we do for Onchain and Lightning)
2023-02-10 11:23:48 +09:00
0d1bab45a0 Fix MySQL migrations 2023-02-10 11:17:52 +09:00
17cc439de3 Merge pull request from dennisreimann/lnurl-cors
LNURL: Add missing CORS
2023-02-09 20:34:44 +01:00
5d03e300fb LNURL: Add missing CORS
In addition to . Closes .
2023-02-09 17:45:09 +01:00
a20408bed1 Fix crash for installations supporting zcash or monero () 2023-02-09 09:49:08 +09:00
ed0ccd6f13 Bump lightning lib, fix warnings 2023-02-08 21:29:20 +09:00
bb1138efb5 Catch exception when creating new invoice with GetLNURL 2023-02-08 20:45:05 +09:00
82b36aaca7 bump 2023-02-08 20:20:56 +09:00
688044429e Changelog 1.7.6 () 2023-02-08 20:14:51 +09:00
7bbfc8e6d4 Greenfield: Currency rate should be strings () 2023-02-08 19:18:37 +09:00
85513aa5c3 Make NFC built in ()
* Make NFC built int

* support checkout v2

* uninstall old plugin

* fix lnurl in unified checkout

* fix tests

* fix tests

* fix old checkout unified qr

* clean up and make nfc submission more sturdy

* support topup invoices for lnurlw

* fix test

* Payment URI fixes

* Fix LNURL exclusion cases

* UI updates

* Adapt test

---------

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-02-08 15:47:38 +09:00
67254cc30c Website is nullable. () 2023-02-07 12:04:13 +01:00
b055844973 Greenfield get app details ()
* Add Greenfield API endpoints for retrieving app details

* add app items details

* Add GetPosApp and GetCrowdfundApp to LocalBTCPayServerClient

* Simplify POS app data items example

* Document app type enum

* make "RequiresRefundEmail" nullable

* remove "Template" and "PerksTemplate" fields
2023-02-07 17:01:53 +09:00
9ba03848f2 Small perf improvement when fetching exactly 1 payout by id 2023-02-07 16:53:44 +09:00
5b96ab89fd Fix Payout Mark Paid in UI ()
fixes 
2023-02-07 16:51:20 +09:00
6a4d8f7404 Fix: Payjoin wasn't always properly choosing utxo for optimal change ()
* Fix: Payjoin wasn't always properly choosing utxo for optimal change

* Update with timeout
2023-02-07 16:43:31 +09:00
219d03b8dd Fix: If PoS item code contains a /, LNUrl would not work (fix ) ()
This is caused by a weird buggy behavior from ASP.NET Core concerning
path value decoding. (More information on
https://github.com/dotnet/aspnetcore/issues/14170#issuecomment-533342396)

This hasn't been fixed for a while, and the dotnet team keeps reporting
it over and over.
2023-02-06 18:17:17 +09:00
523654f2eb Upgrade Lightning lib ()
Includes the updates from .
2023-02-06 13:26:11 +09:00
b9b8cb9f63 Fix test 2023-02-06 12:38:18 +09:00
94f2cd4257 Server Theme: Allow to unset CustomThemeCssUri
It is necessary to have a way to unset the deprecated variable, to get access to the new way of uploading a theme file.
2023-02-04 17:24:19 +01:00
26248774c2 App domain redirect ()
* Fix duplicates in GetAllApps with allowNoUser

* Use domain mapping as canonical reference and redirect to it

* Revert domain mapping to hostname instead of URL
2023-02-02 20:53:42 +09:00
99299ba06f bump nbx 2023-02-02 10:15:04 +01:00
6e42eaa26c fix plugin packer when relative path provided 2023-02-02 10:15:03 +01:00
ae7b621e3d Change Stores.DerivationStrategies to JSONB ()
Gradually changing column from blobs to JSONB allow us to
later take advantages of more powerful queries on postgres.
2023-02-02 09:43:39 +09:00
f2ced20c42 Fix a bunch of open redirect () 2023-02-02 09:42:58 +09:00
e4f256d5cd Lightning Address: Fix availability check and refactor option view ()
As @petzsch rightfully assumed in , the check took only the last available LN payment method into account, which in this case was LN on LTC. We now pass the crypto code as well and I refactored the checks as well as the option view.

Fixes .
2023-02-02 09:42:41 +09:00
ca1dac4cc3 Add missing CORS to ln address of BTCPay (Compatibility Beach Wallet) () 2023-02-02 09:40:31 +09:00
8fc2729fab Merge pull request from dennisreimann/disqus-csp
Fixes https://github.com/btcpayserver/btcpayserver/issues/4572
2023-02-01 13:12:11 +01:00
24c19efd52 Crowdfund: Add CSP rules for Disqus
Fixes .
2023-01-31 22:13:45 +01:00
a3edd829a6 Add onchain wallet send ui extension 2023-01-31 16:49:41 +01:00
9ec475fa40 Fix PluginPacker crash 2023-01-31 23:24:20 +09:00
aad06c583e Greenfield: Add store rates api ()
* Add store rates api

* Improve doc

---------

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-01-31 14:42:25 +09:00
f821e35cb0 Store branding: Unify public pages ()
Closes .
2023-01-30 09:23:49 +01:00
14313291d5 Make test less flaky by ordering GetApps query 2023-01-30 17:17:35 +09:00
b818352a04 Register rate providers in DI, so it can be accessed by plugins () 2023-01-30 09:46:12 +09:00
c0c34fbb41 Add GreenField endpoint for fetching all apps ()
Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-01-30 09:42:24 +09:00
b372dc21d6 handle non built in tag attachments better 2023-01-27 15:44:21 +01:00
3d576cd06b Fix XSS on uploaded files to the file storage () 2023-01-26 19:12:06 +09:00
438dcc4c6f Add Greenfield API endpoint for pull payment LNURL items ()
* Add Greenfield API endpoint for pull payment LNURL items

close 

* Rename GetLNURLs to GetPullPaymentLNURL

* update "ln-url-not-supported" to "lnurl-not-supported"

* remove hardcoding of "BTC"

* update "PullPayments_LNURL" to "PullPayments_GetPullPaymentLNURL"

* update description of 400 status code response

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-01-26 14:43:07 +09:00
de4ac2c830 Greenfield: Add payments list endpoint ()
Based on 
2023-01-26 13:22:49 +09:00
f46443a5e3 Add additional permission for pull payments ()
* Add additional permission for pull payments

* Apply suggestions from code review
2023-01-26 09:46:05 +09:00
69e90b7ff1 Point of Sale: Improve merchant view ()
* Point of Sale: Improve merchant view

Closes .

* Trim bottom section

* Display App Name and Display Title next to each other

* Update views
2023-01-26 09:27:31 +09:00
5089ec9826 Merge pull request from dennisreimann/branding-new 2023-01-25 15:11:08 +01:00
372df93c18 bump 2023-01-25 12:42:40 +09:00
1d2ddeedde Changelog v1.7.5 ()
Inclused updates until f10c1c4730cad394b4361263ffc71e501763f800.
2023-01-25 12:41:29 +09:00
4df2f1f756 Store Branding: Add custom CSS option 2023-01-24 13:24:17 +01:00
f10c1c4730 Checkout v2: UI fixes ()
* Checkout v2: UI fixes

* Improve icon border
2023-01-24 21:00:04 +09:00
92b556e54f Load debug plugins in tests ()
Equivalent to the loading code in Program.cs
2023-01-24 20:12:47 +09:00
b46ae7a651 Checkout v2: Re-add LNURL for top-up invoices ()
My bad, this was excluded erroneously.

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2023-01-24 18:10:38 +09:00
9f3a3c5f51 BIP21: Uppercase addresses only in QR, not in payment URL ()
* BIP21: Uppercase addresses only in QR, not in payment URL

The uppercased address/BOLT11 should only be used for the QR code, the payment URI for the link should stay as it is.

References:

- 
- https://bitcoinqr.dev/

* Improve comments

* Add comments step by step

* Ensure correct delimiter

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2023-01-24 09:44:39 +09:00
b5071237fd Fix swagger file 2023-01-23 12:11:13 +01:00
1d2bebf17a Greenfield: Lightning addresses API ()
* Greenfield: Lightning addresses API

* add docs

* Apply suggestions from code review

Co-authored-by: d11n <mail@dennisreimann.de>
2023-01-23 10:11:34 +01:00
9086822b94 Merge pull request from dennisreimann/pnxbet
Remove pnxbet as a supporter
2023-01-22 12:29:59 +01:00
d90d3c5a0f Remove pnxbet as a supporter
Closes .
2023-01-21 20:51:36 +01:00
a3203e5775 Fix several HTML injections () 2023-01-21 19:08:12 +01:00
5f24b41250 Update Changelog, log restarts 2023-01-19 22:10:38 +09:00
b577c0adb7 Minor UI updates ()
* Minor UI updates

* Lockout page fixes

Fix duplicate headline and model null-check
2023-01-19 18:08:34 +09:00
a9ad0fde9e After a plugin install or uninstall, restart now just kill the process instead of requiring SSH with docker install 2023-01-19 14:27:33 +09:00
9974b6070e Fix NRE in plugin list 2023-01-19 14:22:57 +09:00
bd5e4f3d94 fix NRE in plugins list 2023-01-18 13:47:15 +01:00
e0adb1133d Plugins: Add checkout-noscript-end UI extension point () 2023-01-18 13:38:58 +01:00
3cdb4f5b2a FileService: Null-check stored file before removal () 2023-01-18 13:38:37 +01:00
248401f534 Plugin assemblies shouldn't be unloadable 2023-01-18 16:46:08 +09:00
1228a06a90 Improve detection of plugin bricking an install on startup () 2023-01-18 14:15:27 +09:00
b5cd215643 Use AssemblyProduct rather than AssemblyTitle for default plugin name 2023-01-17 22:05:24 +09:00
7604667b55 Make sure plugin packer has all btcpay deps 2023-01-17 20:04:11 +09:00
3a278d8079 bump 2023-01-16 23:59:09 +09:00
adcc484528 Changelog v1.7.4 ()
Includes commits until 798553e96afeb3aa7ddac125a830fde7a47be187.
2023-01-16 23:58:04 +09:00
798553e96a Greenfield: Add separate permission for viewing LN invoices ()
Based on the diff by @ArttuPakarinen provided in . Closes .
2023-01-16 21:42:54 +09:00
068b717a75 Checkout v2: Configure countdown timer ()
* Checkout v2: Configure countdown timer

This addresses feedback by @astupidmoose left [here](https://github.com/btcpayserver/btcpayserver/discussions/4308#discussioncomment-4438926): Make the countdown timer configurable with a minutes setting. This way the merchant has full control over when to display the timer. They could even set it to equal the invoice expiry, so that it is shown right from the beginning.

* Rename property and adjust wording

* Remove expiration percentage from Checkout v2
2023-01-16 20:45:19 +09:00
785cf597ad Redesign plugin list items ()
* Redesign plugin list items

* Update icon and format code

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2023-01-16 12:12:51 +01:00
ee70fe85c0 Fix loading of plugins in the plugin directory 2023-01-16 16:31:26 +09:00
2e31816979 Can load external plugins during dev to debug more easily ()
* Can load external plugins during dev to debug more easily

* Add again load plugin by project reference

* Make sure we don't load same plugin twice
2023-01-16 10:37:17 +09:00
e4237c9511 Bump (Fix signature hash for some altcoins) 2023-01-16 10:11:33 +09:00
0bc6967dbc Greenfield: Add payment hash and preimage to Lightning invoices ()
* Greenfield: Add payment hash and preimage to Lightning invoices

Closes .

* Greenfield: Add payment hash and preimage to invoice payment method details

* Refactor LN payment method details retrieval
2023-01-13 17:29:41 +09:00
2301769419 Checkout v2: Display and copy addresses ()
* Checkout v2: Display and copy addresses

Closes .

* Refinements
2023-01-12 10:41:33 +09:00
42c5f732a2 Provide sensible default to BaseBTCPayServerPlugin ()
A new plugin overriding BaseBTCpayServerPlugin need to override
Identifier, Name, Version, and Description by default.
This information is actually better saved in the .csproj of the plugin.
Using <Title>, <Description> and <Version> properties.
The identifier should match the assembly name as we assume at several
places than a single plugin is a single dll.
2023-01-11 22:35:45 +09:00
2428b564fd Fix: Version numbers in UI appeared with a suffix zero x.x.x.0 instead of x.x.x () 2023-01-11 18:24:51 +09:00
bb0e96a163 Apply store ids and search term to invoice export ()
This makes the export work like the list in the UI. Exports what one sees.

Fixes .
2023-01-11 13:36:03 +09:00
bb733c5811 Unify 2FA login boxes ()
* Unify 2FA login boxes

* 2FA setup: Make auth code copyable
2023-01-09 16:38:03 +01:00
ffeaf55c4e add extension points for dashboard () 2023-01-09 14:07:05 +01:00
a12bb1d9ce Update license () 2023-01-06 16:19:02 +01:00
313f2a667e Summernote: Allow Twitter embeds ()
Bitcoin Ekasi is planning a crowdfund and they want to embed their Twitter timeline into the page. This adds the necessary domains to the SUmmernote iframe whitelist.
2023-01-06 22:22:49 +09:00
d5d0be5824 Code formatting updates ()
* Editorconfig: Add space_before_self_closing setting

This was a difference between the way dotnet-format and Rider format code. See https://www.jetbrains.com/help/rider/EditorConfig_Index.html

* Editorconfig: Keep 4 spaces indentation for Swagger JSON files

They are all formatted that way, let's keep it like that.

* Apply dotnet-format, mostly white-space related changes
2023-01-06 22:18:07 +09:00
3fa28bb46d Upgrade Lightning lib () 2023-01-06 22:08:03 +09:00
eb90fab640 LNURL updates () 2023-01-05 14:41:18 +01:00
099d65032a Checkout: Fix language dropdown cutoff ()
Fixes  — this time for real. See [this comment](https://github.com/btcpayserver/btcpayserver/issues/4452#issuecomment-1366580849).
2023-01-02 12:09:46 +01:00
e96feb36cd Sync modal: Adjust to Bootstrap changes ()
Fixes .
2022-12-31 09:24:29 +01:00
eb6d01c21e Updates preferred price source copy label ()
* ui+create: updates preferred price source copy label

* Add test case

Co-authored-by: d11n <mail@dennisreimann.de>
2022-12-31 09:24:10 +01:00
03d7dc8971 Ensure only valid non-negative numbers in tip input ()
close 
2022-12-27 20:03:31 +01:00
09d5f5a083 Bump version 2022-12-23 17:54:42 +09:00
1a41b3fb64 Bump NBitcoin 2022-12-23 17:28:44 +09:00
f958550061 Fix tests 2022-12-23 17:21:18 +09:00
1e8e7ec4a4 Fix build 2022-12-23 17:17:09 +09:00
83c4e38fa5 Update NBitcoin 2022-12-23 17:15:14 +09:00
607d2fedb7 Changelog v1.7.3 ()
Includes commits up to 627ada56b753e3da46a0db45690d689b050d085a
2022-12-23 17:13:54 +09:00
627ada56b7 Checkout v2: Minor view improvements () 2022-12-23 17:04:42 +09:00
9ce06fdc4e Update lightning libs (Fix ) 2022-12-23 17:03:37 +09:00
bb63ae6d87 fixes language dropdown cutoff on checkout page ()
* fixes language dropdown cutoff on checkout page

* Use min-height class to fix the tests

Co-authored-by: d11n <mail@dennisreimann.de>
2022-12-22 20:31:08 +01:00
a4182621da Update persian 2022-12-22 22:30:18 +09:00
0534261759 Fix wallet transaction info merging logic and compute color as fallback for labels to not crash 2022-12-22 14:17:23 +01:00
c7baa66a4d Bump lightning lib (Fix ) 2022-12-22 22:01:23 +09:00
1732606581 Automated payout processors shouldn't spam logs on shutdown (Fix ) 2022-12-22 20:33:50 +09:00
68cdd2c2c8 Cleanups: Move test plugin to Plugins subdirectory ()
* Remove unused js-scroll-trigger classes

* Move test plugin to Plugins subdirectory
2022-12-22 15:09:12 +09:00
ea03b6c19c Make checkout CSS and logo paths relative ()
* Make sure custom logo and CSS paths are relative

* match request host and scheme before replacing

* Fix the issue for greenfield as well

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2022-12-22 15:05:56 +09:00
b83eb41df3 Frontend cleanups ()
* Update some buttons

* Potential flaky test fix

* Dark theme: Fix primary accent color

* Pay Button: Remove unused clipboard dependency

The pay button uses the cope-to-clipboard.js

* Remove babel-polyfill

Browser-support should be good by now.

* Remove unused jquery-easing scripts

* Remove unused CSS
2022-12-20 23:11:22 +09:00
e6c68dc5bc Checkout: Fix modal iframe clipboard permissions ()
* Checkout: Fix modal iframe clipboard permissions 

WebKit-based browser require a [permissions policy](https://web.dev/async-clipboard/#permissions-policy-integration) to be set on the iframe element. See the discussions [here](https://github.com/btcpayserver/btcpayserver/discussions/4308#discussioncomment-4399342) and [on Mattermost](https://chat.btcpayserver.org/btcpayserver/pl/z7kdgidcjtnd8f5zs5648t1dhe).

* Updates from code review
2022-12-20 22:54:47 +09:00
76a953819e Add persian language back () 2022-12-20 22:01:29 +09:00
3a2ad48bd6 Checkout v2: Reduce Altcoin name on payment method pill ()
Closes .
2022-12-19 16:06:43 +09:00
674d5bae8a Make sure payment request print view doesn't show table header twice () 2022-12-17 08:00:35 +01:00
5e983641b6 bump 2022-12-16 17:39:14 +09:00
96d4665880 Changelog for v1.7.2
Prepared changelog up to 889ddf6a385748b1ac357312798ae5bdb74b9261
2022-12-16 08:44:38 +01:00
889ddf6a38 Add links to docs and API in the footer ()
* Add links to docs and API in the footer

* Update icons

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-12-16 08:41:58 +01:00
158e613e29 Plugins built with newer version of BTCPay couldn't run on older version () 2022-12-15 16:24:03 +09:00
255c52db26 Upgrade Lightning and ChromeDriver () 2022-12-15 15:26:25 +09:00
072c81177f Add store logo to invoice receipt page () 2022-12-15 06:49:33 +01:00
e5c7fc93e2 fix inconsistent result of labels in greenfield compared to ui wallets tx list 2022-12-14 15:57:18 +01:00
5b7b217b9c update lnurl to fix 2022-12-14 15:45:22 +01:00
06cedaef4b Disabled amount/currency update for payment request with active invoices ()
* Disabled amount/currency update for payment request with active invoices

close 

* Check amount isn't changed in backend

* Add test case

* Update BTCPayServer/Controllers/GreenField/GreenfieldPaymentRequestsController.cs

Co-authored-by: d11n <mail@dennisreimann.de>

* Update BTCPayServer/Controllers/UIPaymentRequestController.cs

Co-authored-by: d11n <mail@dennisreimann.de>

* Improve wording

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-12-14 14:01:48 +09:00
6972e8a3db UI: Theme extensions ()
* Theme extensions

Adds the ability to choose the themeing strategy: Extend one of the existing themes (light or dark) or go fully custom. The latter was the only option up to now, which isn't ideal:

- One had to provide a full-blown theme file overriding all variables
- Tedious, error prone and hard to maintain, because one has to keep track of updates

This PR makes it so that one can choose light or dark as base theme and do modifications on top.

Benefit: You can specify a limited set of variables and might get away with 5-20 lines of CSS.

* Ensure custom theme is present

* Update checkout test
2022-12-14 13:37:31 +09:00
18ba0148ae Use better default than coingecko when creating a new store ()
* Use better default than coingecko when creating a new store

* Improve recommended exchange UX

* Add btcturk for TRY

* Fix recommendation

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-12-14 13:33:27 +09:00
dea019ebdc Add DefaultDescription to LNUrl withdrawal request ()
close 
2022-12-14 13:32:50 +09:00
e27e93aa9a Add BTCTurk rate provider () 2022-12-14 13:14:19 +09:00
c9ee7d477d Fix bitbank and yadio rate providers () 2022-12-14 12:49:30 +09:00
e9deb13ce4 Allow more then 20 accounts when using BTCPayServer.Vault ()
Closes .
2022-12-14 12:06:54 +09:00
cdac238f6d [Greenfield]: Add DescriptionHashOnly to include a description hash in the BOLT11 ()
* [Greenfield]: Add DescriptionHashOnly to include a description hash in the BOLT11

* Add CLN test case

* Improve description in Swagger file

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-12-13 18:56:33 +09:00
e2c5e2c7fb Remove system plugins from the plugin list () 2022-12-13 18:54:41 +09:00
0c3f819200 Have address wallet objects rather than script objects () 2022-12-13 09:09:25 +09:00
3673230fdf Add missing margin 2022-12-12 21:45:41 +01:00
f2cb07ac95 Local file system storage as default ()
* Local file system storage as default

Checks whether or not a file storage has been set. If not, it sets the local file system storage as default.

* Ensure check gets run
2022-12-12 20:28:24 +09:00
484cf9d8a2 PayButton: Fix CSP problems in Firefox ()
* PayButton: Fix CSP problems in Firefox

Firefox does not support [`unsafe-hashes`](https://caniuse.com/?search=unsafe-hashes), so I figured it might be best to get rid of the inline event handlers in general.

Closes .

* Account for multiple paybuttons on one page
2022-12-12 20:27:26 +09:00
5b20be8cfd Checkout fixes ()
* Fix spinner partial usage in Checkout v1

* Update v2 tests
2022-12-10 19:19:13 +09:00
4dbe622a4a Checkout v2: Enable cheating mode on results view () 2022-12-08 14:20:01 +01:00
9a4dec57d1 Generate a wallet object for all scripts, save source in generatedBy rather than receive label () 2022-12-08 13:16:18 +09:00
f5c5178f95 Lock user: Improve return code and fix docs ()
* Lock user: Improve return code and fix docs

The docs state that the `DELETE` method should be used, though the controller wants `POST`. The latter seems appropriate here, as the action can be used for locking and unlocking.

Also adapted the action to return a status code based on the actual outcome of the user toggle call.

Closes .

* Update clients
2022-12-07 19:01:50 +01:00
727cf84080 Fix wallet object script should have script hex as id 2022-12-07 20:26:50 +09:00
80a257e85f Fix Output Descriptor parsing for WSH multisig case ()
* Fix Output Descriptor parsing for WSH multisig case

Reuse existing function for extracting from a multisig descriptor, instead of recursively parsing the inner output descriptor. The latter would run into invalid cases, because it'd be interpreted as bare multisig, which supports only up to three public keys. 

For further details see .

* Add CanParseDerivationSchemes test
2022-12-07 20:18:17 +09:00
ad3c15df9b Fix mobile nav () 2022-12-06 22:52:37 +01:00
c665bd2321 Bump clightning () 2022-12-06 22:15:06 +09:00
948bae9f95 Wallet import: Surface detailed error messages ()
* Wallet import: Surface detailed error messages

Similar to , this checks if the input is an output descriptor and display more detailed information about why an import might fail.

* Add test cases
2022-12-05 17:06:05 +09:00
a1c10b4ea3 Fix store selector transition () 2022-12-05 08:47:51 +01:00
f36df81d9a bump lightning lib (Fix ) 2022-12-05 11:37:03 +09:00
2fd9eb6c68 Adapt ln payouts to handle unknown status ()
Co-authored-by: d11n <mail@dennisreimann.de>
2022-12-04 13:23:59 +01:00
8894d14130 Upgrade Bootstrap to v5.2.3; Design System improvements () 2022-12-04 10:01:38 +01:00
4039e74a82 Do not run label migration for new instances 2022-12-01 19:09:51 +09:00
0af3faf6ff Wallet object scripts ()
* Wallet object scripts

* Adjust comment

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2022-12-01 09:54:55 +09:00
0520b69c18 Update Changelog 2022-11-29 11:55:59 +09:00
932 changed files with 38414 additions and 33491 deletions
.editorconfig
.github
ISSUE_TEMPLATE
codeql
workflows
.gitignore
.run
BTCPayServer.Abstractions
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.ServerInfo.csBTCPayServerClient.StorePayoutProcessors.csBTCPayServerClient.StoreRatesConfiguration.csBTCPayServerClient.StoreUsers.csBTCPayServerClient.Users.csBTCPayServerClient.cs
JsonConverters
Models
Permissions.cs
BTCPayServer.Common
BTCPayServer.Data
BTCPayServer.PluginPacker
BTCPayServer.Plugins.Test
BTCPayServer.Rating
BTCPayServer.Tests
BTCPayServer
BTCPayServer.csprojBufferizedFormFile.csColorPalette.cs
Components
Configuration
Controllers
BitpayInvoiceController.csBitpayRateController.cs
GreenField
LightningAddressService.csLnurlAuthService.csUIAccountController.csUIAppsController.Dashboard.csUIAppsController.csUICustodianAccountsController.csUIHomeController.csUIInvoiceController.Testing.csUIInvoiceController.UI.csUIInvoiceController.csUILNURLAuthController.csUILNURLController.csUIManageController.APIKeys.csUIManageController.Notifications.csUIManageController.csUIPaymentRequestController.csUIPublicController.csUIPublicLightningNodeInfoController.csUIPullPaymentController.csUIReportsController.CheatMode.csUIReportsController.csUIServerController.Plugins.csUIServerController.Roles.csUIServerController.Users.csUIServerController.csUIStorePullPaymentsController.PullPayments.csUIStoresController.Dashboard.csUIStoresController.Email.csUIStoresController.Integrations.csUIStoresController.LightningLike.csUIStoresController.Onchain.csUIStoresController.Roles.csUIStoresController.csUIUserStoresController.csUIWalletsController.PSBT.csUIWalletsController.cs
Data
DerivationSchemeParser.csDerivationSchemeSettings.csEventAggregator.cs
Events
Extensions.cs
Extensions
Fido2
FileTypeDetector.cs
Filters
Forms
HostedServices
Hosting
IHasAdditionalData.cs
Models
PaymentRequest
Payments
PayoutProcessors
Plugins
Program.cs
Properties
Roles.csSearchString.cs
Security
Services
Storage
StorePolicies.cs
TagHelpers
UserManagerExtensions.cs
Views
Shared
UIAccount
UIApps
UICustodianAccounts
UIForms
UIHome
UIInvoice
UILNURL
UILightningAutomatedPayoutProcessors
UIManage
UIOnChainAutomatedPayoutProcessors
UIPaymentRequest
UIPayoutProcessors
UIPublicLightningNodeInfo
UIPullPayment
UIReports
UIServer
UIShopify
UIStorePullPayments
UIStores
UIUserStores
UIWallets
wwwroot
cart
checkout-v2
crowdfund
img
js
light-pos
locales
main
manifest.json
modal
paybutton
pos
swagger/v1
vendor
Build
Changelog.mdLICENSE
Plugins/BTCPayServer.Plugins.Custodians.FakeCustodian
README.mdSECURITY.mdbtcpayserver.slnbtcpayserver.sln.DotSettingsbuild.ps1build.sh
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

@ -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

2
.github/codeql/codeql-config.yml vendored Normal file

@ -0,0 +1,2 @@
paths-ignore:
- 'BTCPayServer/wwwroot/vendor/**/*.js'

80
.github/workflows/codeql.yml vendored Normal file

@ -0,0 +1,80 @@
# For most projects, this workflow file will not need changing; you simply need
# to commit it to your repository.
#
# You may wish to alter this file to override the set of languages analyzed,
# or to provide custom queries or build logic.
#
# ******** NOTE ********
# We have attempted to detect the languages in your repository. Please check
# the `language` matrix defined below to confirm you have the correct set of
# supported CodeQL languages.
#
name: "CodeQL"
on:
# Allow running tests manually. Usefull if scan failure, or need to rescan before next scheduled date.
workflow_dispatch:
# We scan only on a schedule for now, can uncomment the following to scan on commit or PR merge later on if deemed appropriate.
# push:
# branches: [ "master" ]
# pull_request:
# branches: [ "master" ]
schedule:
# Scan every Monday 06:00 UTC.
- cron: '0 6 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'javascript', 'csharp' ]
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Use only 'java' to analyze code written in Java, Kotlin or both
# Use only 'javascript' to analyze code written in JavaScript, TypeScript or both
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps:
- name: Checkout repository
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
languages: ${{ matrix.language }}
config-file: ./.github/codeql/codeql-config.yml
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# Details on CodeQL's query packs refer to : https://docs.github.com/en/code-security/code-scanning/automatically-scanning-your-code-for-vulnerabilities-and-errors/configuring-code-scanning#using-queries-in-ql-packs
# queries: security-extended,security-and-quality
# Autobuild attempts to build any compiled languages (C/C++, C#, Go, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
# If the Autobuild fails above, remove it and uncomment the following three lines.
# modify them (or add more) to build your code if your project, please refer to the EXAMPLE below for guidance.
# - run: |
# echo "Run, Build Application using script"
# ./location_of_script_within_repo/buildscript.sh
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{matrix.language}}"

1
.gitignore vendored

@ -298,3 +298,4 @@ Packed Plugins
Plugins/packed
BTCPayServer/wwwroot/swagger/v1/openapi.json
BTCPayServer/appsettings.dev.json

@ -1,21 +0,0 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Pack Test Plugin" type="DotNetProject" factoryName=".NET Project" singleton="false">
<option name="EXE_PATH" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/bin/Debug/netcoreapp3.1/BTCPayServer.PluginPacker.dll" />
<option name="PROGRAM_PARAMETERS" value="../../../../BTCPayServer.Plugins.Test\bin\Debug\netcoreapp3.1 BTCPayServer.Plugins.Test &quot;../../../../Packed Plugins&quot;" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/bin/Debug/netcoreapp3.1" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/BTCPayServer.PluginPacker.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<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" />
</method>
</configuration>
</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,5 @@
using System;
using System.Data.Common;
using BTCPayServer.Abstractions.Models;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Metadata;
@ -21,7 +22,6 @@ namespace BTCPayServer.Abstractions.Contracts
}
public abstract T CreateContext();
class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator
{
#pragma warning disable EF1001 // Internal EF Core API usage.

@ -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,3 +1,4 @@
using System;
using System.Threading.Tasks;
namespace BTCPayServer.Abstractions.Contracts
@ -6,5 +7,8 @@ namespace BTCPayServer.Abstractions.Contracts
{
Task ApplyAction(string hook, object args);
Task<object> ApplyFilter(string hook, object args);
event EventHandler<(string hook, object args)> ActionInvoked;
event EventHandler<(string hook, object args)> FilterInvoked;
}
}

@ -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);

@ -1,3 +1,4 @@
#nullable enable
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -12,7 +13,7 @@ public interface ICustodian
* Get the unique code that identifies this custodian.
*/
string Code { get; }
string Name { get; }
/**
@ -20,7 +21,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(JObject config, 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.
@ -55,7 +55,7 @@ public class Field
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,114 @@ 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()
{
if (TopMessages?.Any(t => t.Type == AlertMessage.AlertMessageType.Danger) is true)
return false;
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);
HashSet<string> nameReturned = new();
foreach (var f in GetAllFieldsCore(new List<string>(), Fields))
{
var fullName = string.Join('_', f.Path.Where(s => !string.IsNullOrEmpty(s)));
if (!nameReturned.Add(fullName))
continue;
yield return (fullName, f.Path, f.Field);
}
}
private static List<string> GetAllNames(List<Field> fields)
public bool ValidateFieldNames(out List<string> errors)
{
errors = new List<string>();
HashSet<string> nameReturned = new();
foreach (var f in GetAllFieldsCore(new List<string>(), Fields))
{
var fullName = string.Join('_', f.Path.Where(s => !string.IsNullOrEmpty(s)));
if (!nameReturned.Add(fullName))
{
errors.Add($"Form contains duplicate field names '{fullName}'");
}
}
return errors.Count == 0;
}
IEnumerable<(List<string> Path, Field Field)> GetAllFieldsCore(List<string> path, List<Field> fields)
{
var names = new List<string>();
foreach (var field in fields)
{
string prefix = string.Empty;
List<string> thisPath = new(path.Count + 1);
thisPath.AddRange(path);
if (!string.IsNullOrEmpty(field.Name))
{
names.Add(field.Name);
prefix = $"{field.Name}_";
thisPath.Add(field.Name);
yield return (thisPath, field);
}
if (field.Fields.Any())
foreach (var descendant in GetAllFieldsCore(thisPath, field.Fields))
{
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;
descendant.Field.Constant = field.Constant || descendant.Field.Constant;
yield return descendant;
}
}
}
public void ApplyValuesFromForm(IFormCollection form)
public void ApplyValuesFromForm(IEnumerable<KeyValuePair<string, StringValues>> form)
{
var names = GetAllNames();
foreach (var name in names)
var values = form.GroupBy(f => f.Key, f => f.Value).ToDictionary(g => g.Key, g => g.First());
foreach (var f in GetAllFields())
{
var field = GetFieldByName(name);
if (field is null || !form.TryGetValue(name, out var val))
{
if (f.Field.Constant || !values.TryGetValue(f.FullName, out var val))
continue;
}
field.Value = val;
f.Field.Value = val;
}
}
public Dictionary<string, object> GetValues()
public void SetValues(JObject values)
{
return GetValues(Fields);
var fields = GetAllFields().ToDictionary(k => k.FullName, k => k.Field);
SetValues(fields, new List<string>(), values);
}
private static Dictionary<string, object> GetValues(List<Field> fields)
private void SetValues(Dictionary<string, Field> fields, List<string> path, JObject values)
{
var result = new Dictionary<string, object>();
foreach (Field field in fields)
foreach (var prop in values.Properties())
{
var name = field.Name ?? string.Empty;
if (field.Fields.Any())
List<string> propPath = new List<string>(path.Count + 1);
propPath.AddRange(path);
propPath.Add(prop.Name);
if (prop.Value.Type == JTokenType.Object)
{
var values = GetValues(fields);
values.Remove(string.Empty, out var keylessValue);
result.TryAdd(name, values);
if (keylessValue is not Dictionary<string, object> dict) continue;
foreach (KeyValuePair<string,object> keyValuePair in dict)
{
result.TryAdd(keyValuePair.Key, keyValuePair.Value);
}
SetValues(fields, propPath, (JObject)prop.Value);
}
else
else if (prop.Value.Type == JTokenType.String)
{
result.TryAdd(name, field.Value);
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;
}
}

@ -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;

@ -6,31 +6,33 @@ using Microsoft.Extensions.Logging;
namespace BTCPayServer.Abstractions.TagHelpers;
[HtmlTargetElement(Attributes = nameof(Permission))]
[HtmlTargetElement(Attributes = "[permission]")]
[HtmlTargetElement(Attributes = "[not-permission]" )]
public class PermissionTagHelper : TagHelper
{
private readonly IAuthorizationService _authorizationService;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ILogger<PermissionTagHelper> _logger;
public PermissionTagHelper(IAuthorizationService authorizationService, IHttpContextAccessor httpContextAccessor, ILogger<PermissionTagHelper> logger)
public PermissionTagHelper(IAuthorizationService authorizationService, IHttpContextAccessor httpContextAccessor)
{
_authorizationService = authorizationService;
_httpContextAccessor = httpContextAccessor;
_logger = logger;
}
public string Permission { get; set; }
public string NotPermission { get; set; }
public string PermissionResource { get; set; }
public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
{
if (string.IsNullOrEmpty(Permission))
if (string.IsNullOrEmpty(Permission) && string.IsNullOrEmpty(NotPermission))
return;
if (_httpContextAccessor.HttpContext is null)
return;
var key = $"{Permission}_{PermissionResource}";
var expectedResult = !string.IsNullOrEmpty(Permission);
var key = $"{Permission??NotPermission}_{PermissionResource}";
if (!_httpContextAccessor.HttpContext.Items.TryGetValue(key, out var o) ||
o is not AuthorizationResult res)
{
@ -39,7 +41,7 @@ public class PermissionTagHelper : TagHelper
Permission);
_httpContextAccessor.HttpContext.Items.Add(key, res);
}
if (!res.Succeeded)
if (expectedResult != res.Succeeded)
{
output.SuppressOutput();
}

@ -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);
}
}
}

@ -12,9 +12,11 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryUrl>https://github.com/btcpayserver/btcpayserver</RepositoryUrl>
<RepositoryType>git</RepositoryType>
<Configurations>Debug;Release;Altcoins-Debug;Altcoins-Release</Configurations>
<Platforms>AnyCPU</Platforms>
</PropertyGroup>
<PropertyGroup>
<Version Condition=" '$(Version)' == '' ">1.7.1</Version>
<Version Condition=" '$(Version)' == '' ">1.7.2</Version>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PublishRepositoryUrl>true</PublishRepositoryUrl>
@ -28,8 +30,8 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.15" />
<PackageReference Include="NBitcoin" Version="7.0.14" />
<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)
{
@ -52,6 +52,44 @@ namespace BTCPayServer.Client
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)
{
if (appId == null)

@ -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);
@ -81,14 +80,20 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/quote", queryPayload), token);
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<WithdrawalResponseData> GetWithdrawalInfo(string storeId, string accountId, string paymentMethod, string withdrawalId, CancellationToken token = default)
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> 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)
{
@ -114,6 +114,24 @@ namespace BTCPayServer.Client
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)
{
@ -116,6 +116,24 @@ namespace BTCPayServer.Client
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)
{

@ -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);
}
}
}

@ -1,3 +1,4 @@
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
@ -11,5 +12,11 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/server/info"), token);
return await HandleResponse<ServerInfoData>(response);
}
public virtual async Task<List<RoleData>> GetServerRoles(CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/server/roles"), token);
return await HandleResponse<List<RoleData>>(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);
}
}
}

@ -9,6 +9,13 @@ namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<List<RoleData>> GetStoreRoles(string storeId,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/roles"), token);
return await HandleResponse<List<RoleData>>(response);
}
public virtual async Task<IEnumerable<StoreUserData>> GetStoreUsers(string storeId,
CancellationToken token = default)
{

@ -33,14 +33,15 @@ namespace BTCPayServer.Client
return await HandleResponse<ApplicationUserData>(response);
}
public virtual async Task LockUser(string idOrEmail, bool locked, CancellationToken token = default)
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);

@ -51,7 +51,8 @@ namespace BTCPayServer.Client
{
if (message.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldValidationError[]>(await message.Content.ReadAsStringAsync());
var aa = await message.Content.ReadAsStringAsync();
var err = JsonConvert.DeserializeObject<Models.GreenfieldValidationError[]>(aa);
throw new GreenfieldValidationException(err);
}
if (message.StatusCode == System.Net.HttpStatusCode.Forbidden)

@ -30,9 +30,9 @@ namespace BTCPayServer.JsonConverters
case JTokenType.Integer:
case JTokenType.String:
if (objectType == typeof(decimal) || objectType == typeof(decimal?))
return decimal.Parse(token.ToString(), CultureInfo.InvariantCulture);
return decimal.Parse(token.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture);
if (objectType == typeof(double) || objectType == typeof(double?))
return double.Parse(token.ToString(), CultureInfo.InvariantCulture);
return double.Parse(token.ToString(), NumberStyles.Any, CultureInfo.InvariantCulture);
throw new JsonSerializationException("Unexpected object type: " + objectType);
case JTokenType.Null when objectType == typeof(decimal?) || objectType == typeof(double?):
return null;

@ -0,0 +1,36 @@
using System;
using System.Globalization;
using BTCPayServer.Client.Models;
using BTCPayServer.Lightning;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.JsonConverters
{
public class TradeQuantityJsonConverter : JsonConverter<TradeQuantity>
{
public override TradeQuantity ReadJson(JsonReader reader, Type objectType, TradeQuantity existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
switch (token.Type)
{
case JTokenType.Float:
case JTokenType.Integer:
case JTokenType.String:
if (TradeQuantity.TryParse(token.ToString(), out var q))
return q;
break;
case JTokenType.Null:
return null;
}
throw new JsonObjectException("Invalid TradeQuantity, expected string. 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,19 +11,18 @@ 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; }
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
public uint256 DescriptionHash { get; set; }
public bool DescriptionHashOnly { get; set; }
[JsonConverter(typeof(JsonConverters.TimeSpanJsonConverter.Seconds))]
public TimeSpan Expiry { get; set; }
public bool PrivateRouteHints { get; set; }

@ -1,8 +1,11 @@
#nullable enable
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.Models;
public class CreatePayoutThroughStoreRequest : CreatePayoutRequest
{
public string? PullPaymentId { get; set; }
public bool? Approved { get; set; }
public JObject? Metadata { 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; }
}

@ -86,6 +86,7 @@ namespace BTCPayServer.Client.Models
public bool? RequiresRefundEmail { get; set; } = null;
public string DefaultLanguage { get; set; }
public CheckoutType? CheckoutType { get; set; }
public bool? LazyPaymentMethods { get; set; }
}
}
public class InvoiceData : InvoiceDataBase

@ -3,7 +3,6 @@ namespace BTCPayServer.Client.Models
public class LNURLPayPaymentMethodBaseData
{
public bool UseBech32Scheme { get; set; }
public bool EnableForStandardInvoices { get; set; }
public bool LUD12Enabled { get; set; }
public LNURLPayPaymentMethodBaseData()

@ -16,12 +16,11 @@ namespace BTCPayServer.Client.Models
{
}
public LNURLPayPaymentMethodData(string cryptoCode, bool enabled, bool useBech32Scheme, bool enableForStandardInvoices)
public LNURLPayPaymentMethodData(string cryptoCode, bool enabled, bool useBech32Scheme)
{
Enabled = enabled;
CryptoCode = cryptoCode;
UseBech32Scheme = useBech32Scheme;
EnableForStandardInvoices = enableForStandardInvoices;
}
}
}

@ -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))]

@ -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,12 @@ namespace BTCPayServer.Client.Models;
public class LightningAutomatedPayoutSettings
{
public string PaymentMethod { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan IntervalSeconds { get; set; }
public int? CancelPayoutAfterFailures { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public bool ProcessNewPayoutsInstantly { get; set; }
}

@ -17,8 +17,14 @@ 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; }

@ -4,7 +4,6 @@ namespace BTCPayServer.Client.Models
{
public string ConnectionString { get; set; }
public bool DisableBOLT11PaymentOption { get; set; }
public LightningNetworkPaymentMethodBaseData()
{

@ -16,13 +16,12 @@ namespace BTCPayServer.Client.Models
{
}
public LightningNetworkPaymentMethodData(string cryptoCode, string connectionString, bool enabled, string paymentMethod, bool disableBOLT11PaymentOption)
public LightningNetworkPaymentMethodData(string cryptoCode, string connectionString, bool enabled, string paymentMethod)
{
Enabled = enabled;
CryptoCode = cryptoCode;
ConnectionString = connectionString;
PaymentMethod = paymentMethod;
DisableBOLT11PaymentOption = disableBOLT11PaymentOption;
}
public string PaymentMethod { 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,13 @@ 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; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public decimal Threshold { get; set; }
[JsonProperty(DefaultValueHandling = DefaultValueHandling.Populate)]
public bool ProcessNewPayoutsInstantly { 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; }

@ -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; }
}

@ -31,5 +31,6 @@ namespace BTCPayServer.Client.Models
public PayoutState State { get; set; }
public int Revision { get; set; }
public JObject PaymentProof { get; set; }
public JObject Metadata { 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; }
}
}

@ -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; }
}
}

@ -9,6 +9,7 @@ namespace BTCPayServer.Client.Models
{
RateThen,
CurrentRate,
OverpaidAmount,
Fiat,
Custom
}
@ -18,8 +19,13 @@ namespace BTCPayServer.Client.Models
public string? Name { get; set; } = null;
public string? PaymentMethod { get; set; }
public string? Description { get; set; } = null;
[JsonConverter(typeof(StringEnumConverter))]
public RefundVariant? RefundVariant { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal SubtractPercentage { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? CustomAmount { get; set; }
public string? CustomCurrency { get; set; }

@ -16,10 +16,16 @@ namespace BTCPayServer.Client.Models
public string Website { get; set; }
public string SupportUrl { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
[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 +65,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; }

@ -1,3 +1,5 @@
using System.Collections.Generic;
namespace BTCPayServer.Client.Models
{
public class StoreData : StoreBaseData
@ -7,7 +9,7 @@ namespace BTCPayServer.Client.Models
/// </summary>
public string Id { get; set; }
}
public class StoreUserData
{
/// <summary>
@ -17,4 +19,12 @@ namespace BTCPayServer.Client.Models
public string Role { get; set; }
}
public class RoleData
{
public string Id { get; set; }
public List<string> Permissions { get; set; }
public string Role { get; set; }
public bool IsServerRole { get; set; }
}
}

@ -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; }
}

@ -0,0 +1,62 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.Models;
public class StoreReportRequest
{
public string ViewName { get; set; }
public TimePeriod TimePeriod { get; set; }
}
public class StoreReportResponse
{
public class Field
{
public Field()
{
}
public Field(string name, string type)
{
Name = name;
Type = type;
}
public string Name { get; set; }
public string Type { get; set; }
}
public IList<Field> Fields { get; set; } = new List<Field>();
public List<JArray> Data { get; set; }
public DateTimeOffset From { get; set; }
public DateTimeOffset To { get; set; }
public List<ChartDefinition> Charts { get; set; }
public int GetIndex(string fieldName)
{
return Fields.ToList().FindIndex(f => f.Name == fieldName);
}
}
public class ChartDefinition
{
public string Name { get; set; }
public List<string> Groups { get; set; } = new List<string>();
public List<string> Totals { get; set; } = new List<string>();
public bool HasGrandTotal { get; set; }
public List<string> Aggregates { get; set; } = new List<string>();
public List<string> Filters { get; set; } = new List<string>();
}
public class TimePeriod
{
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? From { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? To { get; set; }
}

@ -0,0 +1,16 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace BTCPayServer.Client.Models
{
public class StoreReportsResponse
{
public string ViewName { get; set; }
public StoreReportResponse.Field[] Fields
{
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,8 +1,11 @@
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models;
public class TradeRequestData
{
public string FromAsset { set; get; }
public string ToAsset { set; get; }
public string Qty { set; get; }
[JsonConverter(typeof(JsonConverters.TradeQuantityJsonConverter))]
public TradeQuantity Qty { set; get; }
}

@ -51,6 +51,10 @@ namespace BTCPayServer.Client.Models
public DateTimeOffset Timestamp { get; set; }
[JsonExtensionData]
public IDictionary<string, JToken> AdditionalData { get; set; }
public bool IsPruned()
{
return DeliveryId is null;
}
public T ReadAs<T>()
{
var str = JsonConvert.SerializeObject(this, DefaultSerializerSettings);

@ -1,13 +1,85 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net.Http.Headers;
using Newtonsoft.Json;
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;
}
}

@ -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;
}
}

@ -1,12 +1,16 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Linq.Expressions;
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 +30,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 +63,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 +100,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()
{
PolicyMap = Init();
}
public static Permission Create(string policy, string scope = null)
{
if (TryCreatePermission(policy, scope, out var r))
@ -106,7 +154,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 +207,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 +223,80 @@ 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));
}
public static ReadOnlyDictionary<string, HashSet<string>> PolicyMap { get; private set; }
private static ReadOnlyDictionary<string, HashSet<string>> Init()
{
var policyMap = new Dictionary<string, HashSet<string>>();
PolicyHasChild(policyMap, Policies.CanModifyStoreSettings,
Policies.CanManageCustodianAccounts,
Policies.CanManagePullPayments,
Policies.CanModifyInvoices,
Policies.CanViewStoreSettings,
Policies.CanModifyStoreWebhooks,
Policies.CanModifyPaymentRequests,
Policies.CanUseLightningNodeInStore);
PolicyHasChild(policyMap,Policies.CanManageUsers, Policies.CanCreateUser);
PolicyHasChild(policyMap,Policies.CanManagePullPayments, Policies.CanCreatePullPayments);
PolicyHasChild(policyMap,Policies.CanCreatePullPayments, Policies.CanCreateNonApprovedPullPayments);
PolicyHasChild(policyMap,Policies.CanModifyPaymentRequests, Policies.CanViewPaymentRequests);
PolicyHasChild(policyMap,Policies.CanModifyProfile, Policies.CanViewProfile);
PolicyHasChild(policyMap,Policies.CanUseLightningNodeInStore, Policies.CanViewLightningInvoiceInStore, Policies.CanCreateLightningInvoiceInStore);
PolicyHasChild(policyMap,Policies.CanManageNotificationsForUser, Policies.CanViewNotificationsForUser);
PolicyHasChild(policyMap,Policies.CanModifyServerSettings,
Policies.CanUseInternalLightningNode,
Policies.CanManageUsers);
PolicyHasChild(policyMap, Policies.CanUseInternalLightningNode, Policies.CanCreateLightningInvoiceInternalNode, Policies.CanViewLightningInvoiceInternalNode);
PolicyHasChild(policyMap, Policies.CanManageCustodianAccounts, Policies.CanViewCustodianAccounts);
PolicyHasChild(policyMap, Policies.CanModifyInvoices, Policies.CanViewInvoices, Policies.CanCreateInvoice, Policies.CanCreateLightningInvoiceInStore);
PolicyHasChild(policyMap, Policies.CanViewStoreSettings, Policies.CanViewInvoices, Policies.CanViewPaymentRequests);
var missingPolicies = Policies.AllPolicies.ToHashSet();
//recurse through the tree to see which policies are not included in the tree
foreach (var policy in policyMap)
{
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;
missingPolicies.Remove(policy.Key);
foreach (var subPolicy in policy.Value)
{
missingPolicies.Remove(subPolicy);
}
}
foreach (var missingPolicy in missingPolicies)
{
policyMap.Add(missingPolicy, new HashSet<string>());
}
return new ReadOnlyDictionary<string, HashSet<string>>(policyMap);
}
private static void PolicyHasChild(Dictionary<string, HashSet<string>>policyMap, string policy, params string[] subPolicies)
{
if (policyMap.TryGetValue(policy, out var existingSubPolicies))
{
foreach (string subPolicy in subPolicies)
{
existingSubPolicies.Add(subPolicy);
}
}
else
{
policyMap.Add(policy, subPolicies.ToHashSet());
}
}
@ -212,23 +305,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;

@ -16,7 +16,7 @@ namespace BTCPayServer
DefaultRateRules = new[]
{
"BTG_X = BTG_BTC * BTC_X",
"BTG_BTC = bitfinex(BTG_BTC)",
"BTG_BTC = exmo(BTG_BTC)",
},
CryptoImagePath = "imlegacy/btg.svg",
LightningImagePath = "imlegacy/btg-lightning.svg",

Some files were not shown because too many files have changed in this diff Show More