Compare commits

..

471 Commits

Author SHA1 Message Date
597116bb26 Allow Users to be disabled/enabled 2022-04-14 19:16:55 +02:00
64534efe71 Fix broken "CanCreateRefunds" test () 2022-04-14 14:07:10 +09:00
1235ced355 htmlcoin altcoin updates ()
* remove old logo

* add new logo

* switch name from Althash to Htmlcoin

* increment version NBXplorer.Client

* fix KeyPath BIP-0044, fix name

https://github.com/BEPAL/slips/blob/master/slip-0044.md

* revert increment version
2022-04-14 13:18:12 +09:00
23d383be67 Add transaction info PATCH endpoint ()
* Add transaction info patch endpoint

* Add "#nullable enable" to LabelFactory

* Add Swagger docs

* Update OnChain to onchain

* update feeRate to feerate

* Add test

* replace "Onchain" with "onchain"
2022-04-14 13:17:22 +09:00
fb90ff2fbb updates () 2022-04-14 13:09:37 +09:00
4706aa95e6 Minor Dashboard Adjustments ()
* improves border-radius

* adjusts CF widget wording
2022-04-14 13:08:43 +09:00
8981414705 API: Add Lightning Payment info endpoint ()
* Upgrade Lightning lib

* API: Add Lightning Payment info endpoint
2022-04-12 18:01:58 +09:00
7ec978fcdb Dashboard ()
* Add dashboard and chart basics

* More widgets

* Make widgets responsive

* Layout dashboard

* Prepare ExplorerClient

* Switch to Chartist

* Dynamic data for store numbers and recent transactions tiles

* Dynamic data for recent invoices tile

* Improvements

* Plug NBXPlorer DB

* Properly filter by code

* Reorder cheat mode button

* AJAX update for graph data

* Fix create invoice button

* Retry connection on transient issues

* App Top Items stats

* Design updates

* App Sales stats

* Add points for weekly histogram, set last point to current balance

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2022-04-12 16:55:10 +09:00
d58803a058 Specify PayJoin enabled in Payment Link heading ()
* Specify PayJoin enabled in Payment Link heading

* Fix for non bitcoin payments
2022-04-12 11:05:09 +09:00
fe6b7dc1e3 Fix visual bug when user clicks on "Create refund" without selecting an option ()
* Add missing refund option validation error element

* Add missing hidden inputs for text elements

* Move validation element above button

* Update validation error message
2022-04-11 17:53:52 +09:00
c9f0988b95 Handle possible error when bumping fee ()
fix 
2022-04-11 17:53:10 +09:00
cd9a52706c Use the store's default currency when creating entities ()
* Use default currency for new pull payments

Closes .

* Pull payment: Improve create form

* Use default currency for new invoices

Closes  .

* Clean up old invoice form code

* Use default currency for new payment requests

* Test fixes
2022-04-11 17:50:30 +09:00
bfdb1b4af9 Design updates ()
* Design updates

* Improve table styles

* Form input color improvements

* Form input shadows

* Increase accordion button padding

* Hover transition for checkboxes and radio buttons

* Improve checkbox and radio button spacings

* Improve input styles

* Secondary button updates

* Clear pager floats

* Link improvements

* Don't display border for last table row
2022-04-11 17:49:57 +09:00
e5174b4a29 Lightning: Link to services directly ()
* Allow to access fake LN services in dev mode

* Link directly to Lightning services

Closes .

* Fix typo
2022-04-11 17:49:28 +09:00
8feb60c30d Add ability to set default payment method for pay button ()
* Add ability to set default payment method for pay button

close 

* Add "#nullable enable" to UIStoresController

* Add PaymentMethodOptionViewModel

* Add explicit "Use the store’s default" option
2022-04-11 17:48:12 +09:00
6bd7fb64ab CI test fixes ()
* Test fix


Logs

* Add test logs

* Test change

* Use async overloads in CanPayWithTwoCurrencies test

* Bump NBXplorer

* More test updates

* More logs

* More waiting

* More waiting

* Update GoToUrl calls

* Log request status

* More logs

* More logs, more waits, idk

* Click checkboxes using JS

* Go to url directly

* Double timeout
2022-04-08 18:58:01 +09:00
b9602243d3 Fix tests for litecoin 2022-04-08 13:03:51 +09:00
b7a930ef18 Adjust user search input width ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-04-05 07:34:56 -04:00
add206ae2d Fixes by adding overflow scrolling to StoreSelectorMenu ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-04-05 07:34:14 -04:00
28ce095fb4 Merge pull request from phershbe/master
Link to local development environment instructions corrected
2022-04-05 09:01:00 +02:00
13952a4b79 Bump NBX () 2022-04-05 14:46:42 +09:00
05ec398346 Update CoinGeckoRateProvider 2022-04-04 14:47:50 +09:00
dea2dd52be Link to local development environment instructions corrected
As noted here: https://github.com/btcpayserver/btcpayserver/issues/3590

The link to the local development environment instructions was broken and now is correct.
2022-04-01 22:18:43 -04:00
debe3cda4b fix typo 2022-04-01 13:45:30 +02:00
5b5aa2c721 bump btcpay 2022-04-01 13:22:24 +02:00
e201ddd74c Plugins: Fix plugin installer 2022-04-01 13:20:19 +02:00
4a1580169d Merge pull request from pavlenex/shopify 2022-03-31 15:15:26 +02:00
001ca7de60 Fix UI to match Shopify's 2022-03-31 14:51:16 +02:00
184be4e27b Merge pull request from Kukks/updaart 2022-03-31 13:36:11 +02:00
7652645dda 1.4.8 update 2022-03-31 12:48:10 +02:00
ef6016857b FileService: AddFile from URL () 2022-03-31 11:54:25 +02:00
e449ca2c95 Fix shopify 2022-03-31 10:13:07 +02:00
b0f00773d6 fix issues around local btcpay client and no request obj 2022-03-30 15:04:51 +02:00
451eee549b added additional inputmode attr to relevant form input fields ()
* added inputmode attr to relevant input fields

* missed some numerical form inputs

* removed inputmode attribute from checkout appearnce invoice settings input field
2022-03-30 09:58:50 +02:00
77da261fea Allow plugins to extend swagger docs and fix pull payment test 2022-03-29 20:29:27 +02:00
e23c9ee608 Add missing policies in api key UI 2022-03-29 20:12:02 +02:00
37cb87a9c6 Update CircleCI config () 2022-03-29 16:35:02 +01:00
211db8e0f0 Adjust pull payment badge color ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-03-29 12:09:30 +02:00
d074d60dad Change "was confirmed paid" to "is settled"
As detailed here: https://github.com/btcpayserver/btcpayserver/issues/3572
2022-03-27 07:56:32 +01:00
0bff5e2236 Update BTCPayServer/wwwroot/swagger/v1/swagger.template.stores-email.json
Co-authored-by: d11n <mail@dennisreimann.de>
2022-03-26 21:46:40 +00:00
dca986eb2e Add Greenfield Store Email API 2022-03-26 21:46:40 +00:00
326eb1135b added inputmode attr to relevant input fields 2022-03-26 18:27:22 +00:00
b2f7b4e6b9 Update BTCPayServer/Services/Invoices/InvoiceRepository.cs
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2022-03-25 13:21:43 +00:00
5129d6aa6b Update BTCPayServer/Services/Invoices/InvoiceRepository.cs
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2022-03-25 13:21:43 +00:00
a8cf334616 Update BTCPayServer/Services/Invoices/InvoiceRepository.cs
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2022-03-25 13:21:43 +00:00
3b4d06a1e5 Bugfix: Could not find an order by OrderId after it's OrderId was changed through the API 2022-03-25 13:21:43 +00:00
c7969476b0 Apply suggestions from code review
Co-authored-by: d11n <mail@dennisreimann.de>
2022-03-25 10:45:56 +00:00
7bf24df03a Change payment method name from "Wallet" to "Bitcoin"
As discussed here: https://github.com/btcpayserver/btcpayserver/issues/3571
2022-03-25 10:45:56 +00:00
5ef41294e4 Optimize github plugin fetching 2022-03-23 15:03:39 +00:00
2eb68655c7 FileService: Add method to check availability 2022-03-21 12:38:25 +01:00
23049439c0 API: Add description hash to CreateLightningInvoiceRequest ()
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2022-03-17 10:15:27 +01:00
ce6cd40b92 Adjust wallet receive page layout ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-03-11 10:43:31 +01:00
c36b0c16b0 New API endpoint: Send email using store SMTP ()
Co-authored-by: Kukks <evilkukka@gmail.com>
2022-03-11 10:17:40 +01:00
c15f182377 Streamline JS/CSS bundles () 2022-03-11 08:41:48 +01:00
165cb345b4 Merge pull request from dennisreimann/acinq
Remove ACINQ from README
2022-03-10 11:52:57 +03:00
9b6d2beb4d Remove ACINQ from README
Closes .
2022-03-10 09:50:40 +01:00
722c39a6ff Exclude ChainCoin in rate provider test 2022-03-08 12:12:01 +01:00
e344749d2f Remove Polis
As per [this comment](https://github.com/btcpayserver/btcpayserver/pull/3514#issuecomment-1059583143)
2022-03-08 12:12:01 +01:00
fe782bc3b6 Merge pull request from dennisreimann/2fa-layout
Use simple layout for 2FA views
2022-03-08 13:42:28 +03:00
d372cbad74 Fix null reference error when "destinations" field is not specified or empty when creating a new wallet transaction
fix 
2022-03-08 11:14:34 +01:00
1e1198f4ec Remove Kraken from README 2022-03-08 11:13:19 +01:00
5effc96cff Remove Kraken as a supporter
Closes .
2022-03-08 11:13:19 +01:00
b8d4a1be05 Delete Plugins/packed directory 2022-03-08 09:57:43 +01:00
36a25e6efa Merge pull request from dennisreimann/manage-plugins
Rename Add plugin to Manage plugins
2022-03-08 11:26:35 +03:00
1240e7914d Fixes 2022-03-08 08:17:39 +00:00
e4683b1ea1 Refactoring: Extract ITempDataDictionary extensions 2022-03-08 08:17:39 +00:00
749c22a0c3 Refactoring: Extract HttpRequest extensions 2022-03-08 08:17:39 +00:00
6867774627 Refactoring: Extract StringExtensions 2022-03-08 08:17:39 +00:00
80944972e9 Rename Add plugin to Manage plugins
Closes .
2022-03-08 08:04:15 +01:00
c1f608c0d8 Upgrade Lightning lib () 2022-03-08 10:02:48 +09:00
4dfbb08db3 Try test fix 2022-03-04 10:49:36 +00:00
ead1dffd98 QR container display fixes
Consistently centers the container contents.
2022-03-04 10:49:36 +00:00
5a16e4d132 Use simple layout for 2FA views 2022-03-03 13:43:22 +01:00
a89491e343 Skip Polis and OKEx in rate fetching tests 2022-03-03 10:57:55 +01:00
b1b00ae886 Scroll to checkbox before click 2022-03-03 10:57:55 +01:00
cde5bd87d8 update 1.4.7 2022-03-02 12:37:28 +01:00
3231d5d179 Allow file service to be used in plugins 2022-03-02 12:22:46 +01:00
03e49ea2bf Allow access to global invoices list
The recent changes in 19eea3a6154e73f7fc9d62ab20480134e95be3d5 prevent it to access a global/unfiltered list of invoices across all stores. This removes the fallback to the current store, which brings the global list back at `/invoices`.
2022-03-02 11:00:25 +01:00
7d3eef092c Add missing generate wallet greenfield docs 2022-03-02 10:54:05 +01:00
30d0410b49 fix shopify settings 2022-03-01 09:19:28 +01:00
eb2a887f77 Fix missing store in export for invoices
fixes 
2022-03-01 09:18:46 +01:00
e77b8d29cf Remove policy, set store context manually 2022-03-01 09:18:23 +01:00
490ec299c5 Fix missing store context for Lightning payouts 2022-03-01 09:18:23 +01:00
e47c2aa24d Fix redirect 2022-03-01 09:18:23 +01:00
3eb9fdca6a Syntax improvements 2022-03-01 09:18:23 +01:00
a4173a93b7 Improve display on payout confirm page 2022-03-01 09:18:23 +01:00
ad762cf239 Fix back link on payout confirm page
Fixes .
2022-03-01 09:18:23 +01:00
5a478607dc Fix "Copy Link" button on pull payment and payment request pages
close 
2022-03-01 09:15:15 +01:00
4abc6eb387 Refactoring: Allow GreenfieldExtensions to be used by plugins 2022-03-01 09:14:51 +01:00
c313bba288 Fix mobile content z-index
I think we added this before taking proper care of the main menu z-index. Now that that is fixed we can remove the z-index of the content area, which fixes .
2022-02-26 13:51:59 +01:00
73eaf97afb Fix pos print view
fixes 
2022-02-26 13:22:27 +01:00
8d25df5d4e Fix Pay Button code copying
Fixes .
2022-02-24 12:23:03 +01:00
4a05f16050 Refactoring: Move WellKnownTempData into Abstractions.Constants
This allows plugins to reuse the status message mechanism.
2022-02-21 16:39:08 +01:00
3ef1423263 Update Changelog.md 2022-02-21 13:06:13 +01:00
898652189b Changelog: Fix usernames 2022-02-21 13:06:13 +01:00
2976edf333 Sticky header JS fix
The old version lead to an error on pages that do not contain a sticky header.
2022-02-21 13:05:50 +01:00
248be11e4d fix local client http accessor overrider 2022-02-21 11:48:40 +01:00
19ec8c36e2 Remove debug line in selenium tests 2022-02-21 16:17:36 +09:00
90d989e358 Bump 1.4.6 2022-02-21 14:54:43 +09:00
19eea3a615 Refactor how we get storeids list in invoice filter () 2022-02-21 14:53:48 +09:00
7b81b9786d Fix LNUrl comment truncating 2022-02-21 13:47:00 +09:00
292d302a3d Allow only 2k chars in LNURL comments 2022-02-21 13:27:02 +09:00
557594e34d Test LNUrl Pay payment method information, add doc 2022-02-21 13:22:17 +09:00
48393c3765 Add border for mobile menu ()
In addition to .
2022-02-21 12:20:04 +09:00
022cd666eb Sticky header updates ()
* Add tag helper for sticky header

Encapsulates some of the CSS and JS required and makes the usage easier.

* Make sticky header span full content area horizontally

* Use sticky header on remaining list views

* Use sticky header on remaining edit and detail views

* Adapt pull payments view to be consistent with other list views

* Fix form markup

* PSBT test fix

* Update header actions

* Remove sticky header tag helper
2022-02-21 11:05:42 +09:00
2d0eedb132 CircleCI: Update build image ()
CircleCI recently [deprecated build images](https://circleci.com/blog/ubuntu-14-16-image-deprecation/), including the classic ones we are using. I found this config working for me on another repo.
2022-02-21 11:04:15 +09:00
5d3d664ce6 Update BTCPayServer/Views/UIWallets/WalletTransactions.cshtml
Co-authored-by: d11n <mail@dennisreimann.de>
2022-02-18 10:13:50 +01:00
d1c12d8294 Add ability to clear tx label filter 2022-02-18 10:13:50 +01:00
947a67fcd2 adds border () 2022-02-18 10:56:05 +09:00
9b9540b857 PSBT test fix () 2022-02-18 10:55:54 +09:00
a3b748ffe3 Remove payment methods not currently configured when creating invoice ()
* Add error message when wallet is not configured

* Adjust payment methods based on available ones

* Disable "Create invoice" page if there is an error

* Add test

* update HasErrorMessage

* Add method for checking if payment methods are available

* small pr fixes

Co-authored-by: Kukks <evilkukka@gmail.com>
2022-02-17 18:22:09 +09:00
9a3a7a3444 Add pull payment grouping options ()
* Add grouping by payment methods

* Add filtering by pull payment state

* Hide "Archive" button for archived pull payments

* Don't show payment methods bar if there is only one

* Add "All" payment method option

* Remove filtering by payment method

* Update state queries to not run on the client

* Add filtering by future pull payments
2022-02-17 18:13:28 +09:00
5c8ca15ee2 Redesign Wallet UI ()
* Update wallet navigation

* Find matching text color for label bg color

* Cleanup

* Extract WalletNav component

* Move PSBT link to Send and Rescan link to Settings

* Update transactions view

* Test fixes

* Adapt invoices list actions

* Show invoice actions only if there are any invoices

* Link wallet name and balance to tranactions list

* Move wallet related actions from list to settings

* Fix main menu z-index

Needs a value between fixed and the offcanvas backdrop, see https://getbootstrap.com/docs/5.1/layout/z-index/

* Update receive and send views
2022-02-17 18:07:41 +09:00
cd3807a3d8 Lightning payment info and fee handling ()
* Lightning payment info and fee handling

Builds on the additions in  and .

Adds payment information (total amount and fees) to the API response and allows to set an optional maximum fee percentage when paying.

* Add max fee flat
2022-02-17 18:01:39 +09:00
2a884d6f38 removes redundant header () 2022-02-17 17:59:21 +09:00
6efeb60c41 Fix the PSBT signing flow () 2022-02-17 17:58:56 +09:00
dcdab5b218 Do not show storeid in the invoice filter 2022-02-16 13:43:33 +09:00
288fbda54f New API endpoint: Find 1 user by ID or by email, or list all users. ()
Co-authored-by: Kukks <evilkukka@gmail.com>
2022-02-15 16:19:52 +01:00
03bc91fd1e switch to jobj 2022-02-15 12:23:54 +01:00
1c5cf29540 Greenfield: Invoices Payment Methods: Additional Data
closes 
2022-02-15 12:23:54 +01:00
631ddc0af2 Bump version 2022-02-15 14:33:25 +09:00
1d593df5af Bump lightning lib ()
* Bump lightning lib

* Fix endianness of description hash text
2022-02-14 20:33:27 +09:00
1d3a8bb7bf App updates ()
* Fix toggle alignment

* Crowdfund: Change defaults (disable sounds and Disqus)

* Crowdfund: Move callback notification URL into additional options

Same as with the Point Of Sale options.

* Crowdfund: Make enable toggle more prominent

* Crowdfund: Improve start and end date form group display

* Template Editor: Improve button spacing

* adjusts currency + target

* removes "other actions"

* adjusts text

* adjusts status message bottom margin

Co-authored-by: dstrukt <gfxdsign@gmail.com>
2022-02-14 18:14:21 +09:00
0dc9c183b5 Store guest shouldn't see the bump fee option 2022-02-14 18:13:22 +09:00
05ab43f309 Redirect to transactions list after wallet creation ()
Closes .
2022-02-14 17:09:57 +09:00
f4153ade92 Zcash integration ()
* zcash

* Use Channel instead of Queue
2022-02-14 17:04:34 +09:00
44e84b46b8 Upgrade Lightning lib ()
Prerequisite for .
2022-02-10 19:33:57 +09:00
3fe71e7bdc Avoid NRE on PermissionTagHelper 2022-02-10 18:37:07 +09:00
5d4d8a3422 Simplify swagger 2022-02-10 17:09:55 +09:00
f06199230c Add ability to add description to pull payment ()
* Add ability to add description to pull payment

close 

* Add API support

* Remove 'Model.Description != "<br>"'
2022-02-10 14:54:00 +09:00
da9a6b835a Greenfield: Store Users ()
* Greenfield: Store Users

* fixups

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2022-02-10 14:51:10 +09:00
0afc2cd2cb Add NetworkProvider.DefaultNetwork 2022-02-10 12:43:26 +09:00
9e2f7fb048 Do not register services of altcoins if not used 2022-02-10 12:36:07 +09:00
3fa694c65f Improve Lightning test scripts () 2022-02-10 12:25:14 +09:00
300d84c5d8 [UX/UI] Add CPFP ()
* Add CPFP

* Sign PSBT should go back to the initial page
2022-02-10 12:24:28 +09:00
efed00f58b Setup guide: Link to first crypto if BTC not available 2022-02-10 12:23:45 +09:00
99c4ebe046 Setup guide: Link wallet setup always to BTC () 2022-02-10 12:17:15 +09:00
699231fd92 Fix payment request archival actions () 2022-02-09 23:37:15 +09:00
c18f112f31 Invoice status lookup fix ()
See 4ca152da7cac87ecff7065ae077d72e0985be70b.
2022-02-09 23:35:17 +09:00
605d04580c Fix subnav on store pairing view ()
Fixes .
2022-02-09 12:24:25 +09:00
143211f276 Filter 'complete' = 'confirmed or settled' 2022-02-09 12:17:21 +09:00
4ca152da7c Fix paid invoice filter
Fixes  by reverting the filter changes done [here](ec68d2a0e6 (diff-b7a89b0b45f062f004cdfe6ca8484f6ca519044f63485fd15986af5f7dd5ec76L219)).

The new labels are only used in the UI ­— when filtering one needs to use the old labels, as the filter docs in the view already suggest.
2022-02-09 12:12:32 +09:00
1c1f69fa50 bump 1.4.4 2022-02-08 12:21:58 +09:00
147ccd6c96 Ensure compresed public key is used for SIN generation even if uncompressed key was provided (fix ) () 2022-02-08 11:24:58 +09:00
c8b9906ef3 After login, redirect user to the main page even if root app configured () 2022-02-07 21:18:22 +09:00
cd94a9fac1 Make CheckNoDeadLink more reliable 2022-02-07 21:15:39 +09:00
20a9472ee2 Sticky headers ()
* Make headers sticky

Closes .

* Decrease headline margin bottom on mobile

* increases gap

* adds bottom padding

* Update BTCPayServer/Views/UIApps/UpdatePointOfSale.cshtml

* add "_blank" to view action

* Fix markup and tests

* Spacing updates

* Try test fix

* Re-add sticky account header and add test logs for timeout check

* Fix timeout issues

* Apply scroll padding on pages with sticky header

Co-authored-by: dstrukt <gfxdsign@gmail.com>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2022-02-07 18:37:45 +09:00
c652a2f122 Bumping LND to 0.14.2-beta () 2022-02-07 16:30:17 +09:00
ce174d507d Prevent initial scroll to section nav ()
* Prevent initial scroll to section nav

On pages taht contain a section nav (sub navigation) the previous `scrollIntoView` led to an initial scroll position start at the section nav. See the store or server settings for examples.

This fixes it so that the scroll vertical position always starts at 0.

* Mobile: Prevent anchors from disappearing underneath the fixed header

* Add content padding top to scroll padding
2022-02-06 20:39:52 +09:00
f66b1b644f docker-entrypoint would crash if missing ssh pubkey 2022-02-06 20:39:10 +09:00
5b460f0b4e Error messages when starting BTCPay Server where not shown (Fix ) 2022-02-06 14:37:31 +09:00
ab8d116f11 Fix null reference exception when going to LN node settings before it's been set-up ()
* Fix null reference exception when going to LN node settings before it's been set-up

* Fix-up remaining null reference errors

* Update error message
2022-02-06 12:19:42 +09:00
0535e9c68f 1.4.3 2022-02-02 20:24:56 +09:00
93b52fbdb3 Redirect on 403 page rather than crashing if permission missing 2022-02-02 20:24:22 +09:00
aab1eb0d36 Ensure Swagger docs are semantically and structurally correct ()
* Remove "delete" method from "/api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods" docs

* Remove "requestBody" from "delete" method of "/api/v1/stores/{storeId}/webhooks/{webhookId}"

* Rename "API Key" to "API_Key"

* Remove "scheme" from API_Key security scheme

* Remove "name" and "in" properties from "Basic"security scheme
2022-02-02 20:12:48 +09:00
c07fcc171c Fix Plugin Local Client authorization when user is provided ()
* Fix Plugin Local Client authorization when user is provided

* 1337 hax
2022-02-02 20:09:08 +09:00
8e5b7d2578 Fix crash of payment request list (Fix ) 2022-02-02 20:08:20 +09:00
37b1e9037f files update 2022-02-02 10:19:17 +01:00
7c0999ac9f settings + PSBT constrain 2022-02-02 10:19:17 +01:00
5ce1c9d77f send + receive constrains 2022-02-02 10:19:17 +01:00
14dcb58afa constrain to lightning settings view 2022-02-02 10:19:17 +01:00
04068025c6 fixes edit payment request 2022-02-02 10:19:17 +01:00
2cd0c7a407 Fix responsive POS and Crowdfund form display
Fixes .
2022-02-02 10:19:17 +01:00
f3592c4782 Update invoice doc link
close 
2022-02-02 10:14:36 +01:00
1e5934895d Reference correct payment type definition for webhook events in Swagger docs 2022-02-02 10:09:58 +01:00
0f5d932726 Add test IDs for Lightning and Plugins ()
I came across these when writing a Selenium test for LNbank.
2022-02-02 12:47:22 +09:00
4125726be9 Fix pay button type comparison ()
Fixes . We need to compare the button type value loosely, because initially the type is an integer and after it gets set by Vue it is a string.
2022-02-02 12:37:56 +09:00
bcb692caf0 Pay Button Alert: Add missing alert-link classes ()
* Pay Button Alert: Add missing alert-link classes

* Update alert link styles
2022-02-02 12:37:22 +09:00
ff9a1a1f55 Delete user preferences cookie on logout ()
I think it is a good practice to remove those settings on logout. Otherwise they get persisted across multiple accounts, which might not be desired.
2022-02-01 10:42:31 +09:00
faef6d82ff No error in crowdfund if canvas unavailable 2022-01-31 18:15:28 +09:00
d3a123373e No error in crowdfund if canvas unavailable 2022-01-31 17:05:42 +09:00
7c66f024ed adjust footer () 2022-01-31 16:52:50 +09:00
20c7259174 Bump z-index on header ()
close 
2022-01-31 16:52:14 +09:00
16a4c072a9 Bump 2022-01-28 22:52:56 +09:00
254e8d48f2 Fix test 2022-01-28 22:51:12 +09:00
52fe374aaa Fix new guest store redirect after login
Fixes .
2022-01-28 09:59:40 +01:00
f776725096 Guest users shouldn't see Payouts menu item 2022-01-28 17:49:21 +09:00
6e864c2631 Fix error message when trying to remove last admin 2022-01-28 17:09:54 +09:00
4221554dc8 Add back plugins link in server nav
Not all plugins appear in the side nav menu, and there is no intuitive link to view all installed plugins
2022-01-28 08:56:52 +01:00
6b50fdae43 fixes stray < text () 2022-01-28 14:52:34 +09:00
7bae6b2e8f bump 2022-01-27 17:17:20 +01:00
5c6a0f22c0 fix ln address
fixes 
2022-01-27 17:17:20 +01:00
a9b755fa1d Changelog 1.4.0 () 2022-01-27 22:24:39 +09:00
72bdf9e0d7 Update "Close Wallet & Lightning Setup" Path ()
* update path

* updates center
2022-01-27 14:33:12 +09:00
cbf8b23385 Adapt desktop breakpoints in views ()
* Add XXL breakpoint

* Unify setup guide display

* Adapt desktop breakpoints in views

* Fix POS code display

* Fix syntax in home view

* store settings + constrain update

* account settings

Co-authored-by: dstrukt <gfxdsign@gmail.com>
Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2022-01-27 11:56:46 +09:00
4aacd0d23a Adapt warning message for pay button 2022-01-27 11:43:39 +09:00
69202ed752 Add loading indicator for "Pay" button in POS terminal app ()
* Add loading indicator for "Pay" button in POS terminal app

close 

* move feature over to Vue

* replace click handler with form submit handler
2022-01-27 10:58:25 +09:00
aa762821ce Spacing fixes 2022-01-26 15:58:21 +09:00
8a7bb6bc5a Retry SaveChanges if deadlock detected in delete store 2022-01-26 15:09:06 +09:00
35cb4d4cc3 Update Plugins View ()
* visual updates

* badges

* copy update
2022-01-26 15:01:49 +09:00
8ceda3eab1 Fixes ()
* Improve wording

* Fix redirect action
2022-01-26 14:57:35 +09:00
cc1233e8d5 Adjust Pay Button ()
* updates padding

* padding adjustments

* updates

* Redirect to paybutton enable page when disabling

* Fix test

* Fix test

Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-01-26 14:55:48 +09:00
70883c0869 Simple Wallet View Inconsistencies () 2022-01-26 14:54:29 +09:00
fe9de98dd1 Merge pull request from dennisreimann/merge-general-payment
Store: Combine General and Payment settings
2022-01-25 20:26:45 +09:00
ecde91ff25 Plugins: Support plugin git remote with multiple versions of same plugins 2022-01-25 11:15:19 +01:00
240ad49a43 Add currency selection attributes 2022-01-25 06:57:55 +01:00
10adb23e71 Remove obsolete store hints 2022-01-25 06:57:55 +01:00
c2fc099439 Create store: Add default currency and rate provider fields 2022-01-25 06:57:55 +01:00
723a38da68 Store: Combine General and Payment settings 2022-01-25 06:57:55 +01:00
74037fd605 Make CanUseTorClient more reliable 2022-01-25 12:27:44 +09:00
e917796fce Set new LN defaults ()
fixes 
2022-01-25 12:17:39 +09:00
5661798601 Allow plugins access in nav when there is no store () 2022-01-25 12:15:59 +09:00
a8adac9c5a Rename LNUrlAuthController -> UILNAuthController () 2022-01-25 11:51:14 +09:00
c62018f984 1.4.0 Final Polish ()
* adds pay button icon

adds more

update icons

* reduces update app titles

* capitalize PP

* more icons

notification icon update

adds more

* Truncate long titles in nav

* Adjust "off" color state for the wallet/lightning

* Theme switch alignment

* Update store selector

* adds more space in store selector span

* Prevent form zoom on mobile Safari

* updates lightning + settings view

* updates store icon

* adjusts notification icon

* removes notifications setting button icon

* Update status colors

* Fix Lightning nav markup

* Prevent icons from shrinking

* Move main menu styles to css

* Remove max-width container for content area

* Update headlines

* Use fixed header on mobile

* Extract custom pills component

* Form field update

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-01-25 11:07:52 +09:00
06f2d4425c re-add theme ui extension 2022-01-24 13:12:12 +01:00
090da6cfb6 Add configurable BOLT11Expiration for refunds (Fix ) ()
* Add configurable BOLT11Expiration for refunds (Fix )

* Add BOLT11Expiration configuration in Payment
2022-01-24 20:17:09 +09:00
28dbf10a31 Do not rely on element's id for payment button ()
* Do not rely on element's id for payment button

* Update BTCPayServer/Views/UIStores/PayButton.cshtml

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

* Update BTCPayServer/Views/UIStores/PayButton.cshtml

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

* Update BTCPayServer/Views/UIStores/PayButton.cshtml

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

* Update BTCPayServer/Views/UIStores/PayButton.cshtml

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

Co-authored-by: d11n <mail@dennisreimann.de>
2022-01-24 20:05:22 +09:00
7a66d0feda Shorten environment info ()
Also uses the copyright symbol (instead of an `@`).
2022-01-24 20:01:17 +09:00
e23ddf118e Add warning about the tradeoff the paybutton ()
* Add warning about the security tradeoff of the paybutton

* Update BTCPayServer/Views/UIStores/PayButtonEnable.cshtml

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

* Move message in column

Co-authored-by: d11n <mail@dennisreimann.de>
2022-01-24 20:00:42 +09:00
11d6588249 Add suggestion list for currency inputs ()
* Move tagHelpers in their own directory

* Add suggestion list for currency inputs
2022-01-24 20:00:13 +09:00
30db0cd4f4 Make users table responsive () 2022-01-24 14:03:56 +09:00
692b57a1ad Fix the notification dropdown not updating without page refresh 2022-01-23 15:49:43 +09:00
7505c65401 Logo Replaced
ETB logo change with a new, more consistent logo with other liquid assets.
2022-01-21 20:49:05 +01:00
54a735ffd9 Pay Button: Fix CSP violations for custom amount and slider ()
Fixes .
2022-01-21 11:11:08 +09:00
6a20d9036c Refactor signed out action views (login, register, etc.) ()
* Refactor signed out action views (login, register, etc.)

Extract common layout and some more cleanups.

* Optimize supporters display on mobile

* Optimize footer display on mobile
2022-01-21 11:10:03 +09:00
c338846d63 Mobile navigation ()
* Mobile nav: Horizontal scrolling

* Reduce nav item spacing on mobile

* Update overlay color

* Fix modal colors

* Improve mobile nav styles

* Improve navbar on mobile Safari

* Scroll active nav item into viewport
2022-01-21 10:35:12 +09:00
c419ad68bb Remove redundant payment methods from store settings ()
* Add enabled toggle to wallet settings view

* Add enabled toggle to Lightning settings view

* Remove redundant payment methods from store settings

* Rename Payment Methods to Payments

* Adapt tests

* Fix invoice state toggle on details page

* Add spacing on Lightning sett8ings page
2022-01-19 20:58:02 +09:00
51c486c15a Add Lightning page with services ()
* Add Lightning page with services

* Adapt other services pages

* Display Lightning services only for internal node
2022-01-19 11:52:05 +09:00
306ff3d919 Auto-submit scanned login code
Closes .
2022-01-18 15:42:09 +01:00
d667b8ae8b Add LNURL support to Crowdfund 2022-01-18 12:26:15 +01:00
72d728eb47 Update BTCPayServer/Views/UIAccount/LoginWithFido2.cshtml 2022-01-18 12:25:56 +01:00
801ab862a3 Improve 2FA auth UI 2022-01-18 12:25:56 +01:00
d7b4dd2d4c Show action button for safari browsers when using FIDO2 ()
fixes 
2022-01-18 10:23:07 +09:00
1d3f74c8bb Home sweet home ()
* Link to store home, show home only if there is no store

* Handle store guest case

* Apply correct policies to nav items
2022-01-18 10:20:59 +09:00
c3f73c0de3 Content Consistency Updates (1.4.0) ()
* updates

* updates

* updates

* updates

* updates

* moves api key CTA to top right

* updates

* more updates

* more updates

* Fix active state when "Account" is selected

* Update wording in subnav: Profile becomes Account

* Fix email test

* Update Emails wording

* Try to fix email test

* Make General first tab in store settings

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-01-18 10:19:27 +09:00
1fc2fc7a11 Merge pull request from BTCparadigm/patch-1
Update LICENSE
2022-01-17 17:18:36 +09:00
13ea1898b6 Merge pull request from dennisreimann/theme-colors
Theme colors
2022-01-17 17:16:26 +09:00
586303f47e Merge pull request from NicolasDorier/wfuoi
Make sure the SubscribeAsync handlers are executed in order
2022-01-17 17:16:03 +09:00
ce86a838f2 Merge pull request from dennisreimann/2fa-login
Fix secondary login view
2022-01-17 17:15:51 +09:00
21e69251e3 CanSendIPN can't ensure received payment is sent first 2022-01-17 16:59:37 +09:00
a42323a527 Make sure the SubscribeAsync handlers are executed in order 2022-01-17 13:36:33 +09:00
14da3023d8 Merge pull request from NicolasDorier/niceurl
Use nicer urls, part2 (Fix )
2022-01-17 11:41:20 +09:00
7eb5f57478 Fix Rates page 2022-01-17 11:25:33 +09:00
2cb443df8a Update LICENSE 2022-01-16 16:11:22 +02:00
961769ebd0 Fix AssertNoError to detect page exception 2022-01-16 12:39:08 +09:00
3266cc8e3b Improve Lightning node toggle colors 2022-01-15 21:07:01 +01:00
3dec14b89d Fix secondary login view 2022-01-15 20:49:04 +01:00
a67f989dda Theme variable value updates 2022-01-15 20:20:52 +01:00
2d05464b17 Light theme: Use off-white bg for content 2022-01-15 19:56:38 +01:00
a39082e565 Add scrollbar styles 2022-01-15 19:54:50 +01:00
d1f567eade Add Include Error Details to postgres connection string 2022-01-15 14:54:06 +09:00
b9fdd54538 Use nicer urls, part2 (Fix ) 2022-01-15 14:54:06 +09:00
7243aec213 Support LNURL Auth 2022-01-14 13:26:30 +01:00
1fb582c35d Rename the Fido2Controller 2022-01-14 18:34:30 +09:00
c6da0409b0 Merge pull request from NicolasDorier/fewiwqi
Update some code style enforcement
2022-01-14 18:05:50 +09:00
50d4b55f73 Warning if not using 'simple using' 2022-01-14 17:50:29 +09:00
c6a7e90c1a Warning if not using 'is not null' 2022-01-14 17:48:15 +09:00
5cbc2e96e7 Merge pull request from NicolasDorier/qfouq
Rename controllers
2022-01-14 16:23:47 +09:00
23a96c07ae Rename GreenField -> Greenfield 2022-01-14 13:46:04 +09:00
7a787fc945 Rename UI controllers 2022-01-14 13:46:03 +09:00
ce43de0c57 Rename greenfield controllers 2022-01-14 12:21:06 +09:00
eaf47d3739 Rename controllers Bitpay controllers 2022-01-14 12:21:06 +09:00
5eebdb6774 Use nicer urls (Fix ) () 2022-01-14 12:20:50 +09:00
51db1593d6 Remove stores list () 2022-01-14 11:59:27 +09:00
223c71ce8b Fix tests 2022-01-13 23:50:33 +09:00
127afdb5c1 Store-Centric Minor Tweaks ()
* padding above store selector + left & right content padding

* Adapt vertical spacing for content area

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-01-13 20:29:38 +09:00
f34706f9f0 Update lightning lib 2022-01-13 19:18:14 +09:00
f76ce54109 Fix tests 2022-01-13 18:14:27 +09:00
f67fa6a5d6 Remove right to admins to bypass permissions to modify/view invoices or stores () 2022-01-13 17:42:32 +09:00
5ad6d77973 The notification dropdown wasn't fetching events if rootPath used () 2022-01-13 17:08:33 +09:00
69d1acc797 Empty states: Setup guide for store and wallet ()
* Store Selector: Create first store button

* Add setup guide to homepage

* Policy update for stores list

* Fix test

* Initial create store button as primary

* Add notifications list to homepage

* Remove back to list from store create view

* Adapt content padding on desktop

* Add store home view with setup guide

* Fix active page nav highlighting

* Test fix

* Remove What's Next section

* Rename Store Home to Dashboard

* Fix Lightning setup link

* Add tests for store setup guide

* Update BTCPayServer/Views/Home/Home.cshtml

Co-authored-by: Pavlenex <pavle@pavle.org>

* Update BTCPayServer/Views/Stores/Dashboard.cshtml

Co-authored-by: Pavlenex <pavle@pavle.org>

* Remove setup guide on global homepage

* Remove Shopify setup link from nav

* Fix content container max-width on desktop

Co-authored-by: Pavlenex <pavle@pavle.org>
2022-01-13 17:08:15 +09:00
0c0235a56e Merge pull request from NicolasDorier/wfwiouoi
Add version to svg's href files to prevent cache issues
2022-01-13 15:55:14 +09:00
7b0558dc8e Add version to svg's href files to prevent cache issues 2022-01-13 15:54:40 +09:00
77be2fa9d5 Make CanUseWebhooks less flaky 2022-01-13 13:27:02 +09:00
8f320337e0 Merge pull request from dennisreimann/clipboard
Fix clipboard copy edge case
2022-01-13 13:23:26 +09:00
2327b97fa3 Make CanUseWebhooks less flaky 2022-01-13 13:21:54 +09:00
a411a6a81a Fix copy functionality without navigator.clipboard 2022-01-13 11:50:37 +09:00
d66f1f5513 Remove duplicate event handler 2022-01-12 16:22:56 +01:00
7503fde48c Merge pull request from NicolasDorier/foiuw
Make BTCPayServer insensitive to the working directory in which it is started (Fix )
2022-01-12 20:45:09 +09:00
20c8916610 Make BTCPayServer insensitive to the working directory in which it is started (Fix ) 2022-01-12 20:20:26 +09:00
5a2a933b64 Add more logs to the canusetor test 2022-01-12 18:26:45 +09:00
ffc0e996db Merge pull request from NicolasDorier/fewouq
Bump Clipboard.js
2022-01-12 16:59:36 +09:00
a02ad104ee Bump Clipboard.js 2022-01-12 16:06:28 +09:00
625876ff07 Merge pull request from bolatovumar/fix/vscode-browser-launch
Adjust VSCode browser launch regex
2022-01-12 14:25:34 +09:00
b935275fd9 Adjust VSCode browser launch regex
VSCode stopped launching BTCPay in a new browser tab after this commit: ab3aab9c22 (diff-2baea61aec1a18e36f951b0060f693c9bd10d9610e2681d36277e79d101005bcR66)
2022-01-11 21:11:15 -08:00
4c032e9e6a Merge pull request from dennisreimann/tor-url-in-footer
Improve footer
2022-01-12 11:19:54 +09:00
1b770c66cd Improve footer 2022-01-11 18:56:30 +01:00
96259dfb49 Merge pull request from NicolasDorier/oiufew
Do not send email twice for bitpay API, log whether IPN is an ExtendedNotification. (Fix )
2022-01-12 00:42:44 +09:00
e4d9e3e22e Do not send email twice for bitpay API, log whether IPN is an ExtendedNotification. (Fix ) 2022-01-12 00:26:12 +09:00
fbfab88257 Remove obsolete code in BitpayIPNSender 2022-01-12 00:10:55 +09:00
708f8b49df [Greenfield] Let non-admin update LN payment method with internal node if it is unchanged (Fix ) () 2022-01-11 23:38:05 +09:00
323e5e14a3 Update Payment Request View ()
* removes "back to list"

* changes currency label + formats currency and amount

* adjust sizing

* Wording: Create and Save button

* Improve search responsive behaviour

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2022-01-11 22:16:16 +09:00
5bbaa48b49 Fix change state broken in the UI and update invoice's status in payment request to new convention (Fix ) () 2022-01-11 21:49:56 +09:00
cd91e48713 Swagger: Added explanation for empty currency field in Create Payment Request ()
* Swagger: Added explanation for empty currency field in Create Payment Request

* Added nullable true
2022-01-11 20:11:11 +09:00
7444bd06e4 [Greenfield] Fix create/update payment requests expiry field and allow null currency field (Fix ) () 2022-01-11 18:42:44 +09:00
0017e687db A store's guest should be able to manage lightning invoices (Fix ) () 2022-01-11 17:22:10 +09:00
5865fd5022 Improve Payout View ()
* updates payouts

* update spacing

* improvements

* View updates

* updates spacing

* Fix spacing

* Fix markup

* Fix test

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-01-11 17:15:23 +09:00
4b941a5145 Update Invoice Views ()
* updates create invoice

* updates invoice list

* formats

* updates row

* updates

* Improve invoice list markup and fix mass action form

* Responsive invoice table

* Improve spacing on invoice detail view

* Improve archive message

* Responsive status change partial

* Add test case for mass archiving

* Add mass unarchiving

Closes .

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-01-11 17:14:34 +09:00
3c5d809cf9 Merge pull request from NicolasDorier/wofiq
The IPN notification manager should preserve IPN ordering
2022-01-11 15:22:07 +09:00
ba101015f6 Use the MultiProcessingQueue in IPNSender 2022-01-11 15:06:00 +09:00
6999abe1ca Rename WebhookNotificationManager -> WebhookSender 2022-01-11 13:21:38 +09:00
cb295e20d4 Rename InvoiceNotificationManager -> BitpayIPNSender 2022-01-11 13:21:38 +09:00
c6df43363f Extract MultiProcessingQueue from WebhookNotificationManager 2022-01-11 13:21:38 +09:00
81cec36b68 Merge pull request from NicolasDorier/quofwe
[Greenfield] if some json property are invalid, throw nice error instead of an exception (Fix )
2022-01-10 23:56:57 +09:00
47c1ffe53f Fix doc for address preview of derivation scheme 2022-01-10 23:03:30 +09:00
90a9051827 Merge pull request from dstrukt/improve-lightning-config-view
Simple Lightning Node Selector Improvement
2022-01-10 22:13:38 +09:00
8bea3dd21e [Greenfield] if some json property are invalid, throw nice error instead of an exception (fix ) 2022-01-10 22:11:04 +09:00
e164b1f169 The PayButton should select the default currency of the store as default 2022-01-10 20:37:36 +09:00
383765f5fe Solve spacing via CSS 2022-01-10 12:22:12 +01:00
25a59fff4a Merge pull request from NicolasDorier/oifwuq
Improve error message for create store wallet transaction (Fix )
2022-01-10 18:00:39 +09:00
03af471f65 Improve error message for create store wallet transaction (Fix ) 2022-01-10 11:59:13 +09:00
d189deefb4 adds secondary button look to rounded tab nav 2022-01-09 03:04:32 -08:00
e957180618 Merge pull request from btcpayserver/odqiq
Validate the name of controllers when LinkGenerator
2022-01-08 14:32:55 +09:00
47d8d3cdb1 Validate the name of controllers when LinkGenerator 2022-01-08 14:16:17 +09:00
f364451a96 Merge pull request from dstrukt/remove-back-to-list-ctas
Remove remaining "Back to list" CTAs
2022-01-08 12:21:04 +09:00
2c51b31c62 Merge pull request from dennisreimann/store-centric-account
Account menu improvement
2022-01-08 12:20:04 +09:00
0dcf240faf Account menu improvement 2022-01-07 17:25:28 +01:00
88bc1c64d2 Fix tests 2022-01-07 21:47:19 +09:00
84bd8a6e98 fix tests 2022-01-07 21:16:26 +09:00
0d657fc646 Fix tests 2022-01-07 20:54:26 +09:00
64b85ac1f9 Fix AssertNoError 2022-01-07 19:49:33 +09:00
81c1cc6728 Add rockstar friendly error 403 2022-01-07 19:46:38 +09:00
098879585a Merge pull request from NicolasDorier/qouif
Fix CookieAuthHandler and guest permission to invoice's view
2022-01-07 18:31:23 +09:00
fc91077430 A store's guest should be able to see invoice information 2022-01-07 18:10:31 +09:00
b71a04943b CookieAuthHandler shouldn't set store context if appId/payReqId/invoiceId is not found 2022-01-07 18:10:31 +09:00
dd4fb68e5b invoices - remove 2022-01-06 23:01:04 -08:00
a085a2a557 apps - remove 2022-01-06 22:58:14 -08:00
fa84e34def Fix test 2022-01-07 13:02:07 +09:00
8c3f377fc0 fix elements 2022-01-06 18:09:06 +01:00
f9d14c64ce Simple Improve Receive Wallet View ()
* removes card styles

* removes card styles

* removes card style

* Minor improvements

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2022-01-05 20:23:36 +09:00
fc687f9fc0 Fixed LND admin macaroon hexdump command ()
Argument `-plain` didn't work for me in the LND container, but `-p` did. 
The error I got was `xxd: invalid number 'ain'`

Added the `-c 256` for better readability. This param maxes out at 256.
2022-01-05 20:23:21 +09:00
57071d7bc8 Replace Square Crypto with Spiral ()
Closes 
2022-01-05 20:22:24 +09:00
324a246189 Fix dockerfile 2022-01-03 22:11:33 +09:00
a706f81760 Fix VSCode launch.json for .NET 6 () 2022-01-03 12:09:43 +09:00
ab3aab9c22 Make BTCPayServer works with dotnet watch hot reload 2022-01-01 22:05:51 +09:00
fd2e55e444 Simplify tests to take advantage of context () 2021-12-31 22:02:53 +09:00
04b8eafacb Run dotnet format () 2021-12-31 16:59:02 +09:00
e2d0b7c5f7 Store centric UI: Part 3 ()
* Set store context in cookie

* Fix page id usages in view

* Move Pay Button to nav

* Move integrations to plugins nav

* Store switch links to wallet if present

* Test fixes

* Nav fixes

* Fix altcoin view

* Main nav updates

* Wallet setttings nav update

* Move storeId cookie fallback to cookie auth handler

* View fixes

* Test fixes

* Fix profile check

* Rename integrations nav extension point to store-integrations-nav-list

* Allow strings for Active page/category for plugins

* Make invoice list filter based on store context

* Do not set context if we are running authorizer through tag helper

* Fix test and unfiltered invoices

* Add permission helper for wallet links

* Add sanity checks for payment requests and invoices

* Store context in home controller

* Fix PayjoinViaUI test

* Store context for notifications

* Minor UI improvements

* Store context for userstores and vault controller

* Bring back integrations page

* Rename notifications nav pages file

* Fix user stores controller policies

* Controller policy fixes from code review

* CookieAuthHandler: Simplify CanViewInvoices case

* Revert "Controller policy fixes from code review"

This reverts commit 97e8b8379c2f2f373bac15a96632d2c8913ef4bd.

* Simplify LayoutSimple

* Fix CanViewInvoices condition

Co-authored-by: Kukks <evilkukka@gmail.com>
2021-12-31 16:36:38 +09:00
db1a124ffb Do not check certificates for SMTP settings if local server 2021-12-29 18:24:24 +09:00
0dcfbe8581 Remove internal socks http proxy and use .net60 socks support () 2021-12-28 18:57:22 +09:00
0e1b872777 Update dotnet version in README 2021-12-28 17:40:36 +09:00
ed5b159fb6 Use ArgumentNullException.ThrowIfNull everywhere () 2021-12-28 17:39:54 +09:00
9b7ca76b99 Use Outstanding amount for shopify order invoices ()
* Use Outstanding amount for shopify order invoices

* consider shopify order may have multiple transactions

* Use presentment currency not just currency

fixes 
2021-12-28 15:56:54 +09:00
eeebb99ca3 Consistent and simplified button CTA text ()
* refine pull payments cta

* payment requests cta

* invoice cta

* add user cta

* webhooks cta

* set password cta

* removes whitespace

* set password cta

* api key cta

* change password cta

* add device 2fa cta

* create token cta

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2021-12-28 15:54:31 +09:00
e2b18cf9db Make sure dotnet test show test progress 2021-12-27 14:26:03 +09:00
955ba91770 Merge pull request from NicolasDorier/fwihqb
Bump to C#10, remove warnings
2021-12-27 14:10:23 +09:00
c0e9f91bdc Fix warnings 2021-12-27 13:58:18 +09:00
259f0b5aad Bump to C# 10 2021-12-27 13:20:57 +09:00
02419dcdd1 Migrate to .net6.0 () 2021-12-27 13:15:43 +09:00
4a66c91cac Fix app permissions ()
* Fix app permissions

As pointed out by @nicolasdorier [here](https://github.com/btcpayserver/btcpayserver/pull/3205#issuecomment-999437555).

* Fix for login codes view

* Ensure app belongs to store
2021-12-26 12:20:46 +09:00
48ac996d77 Sign in with other device (quick mobile login) ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2021-12-24 09:27:00 +01:00
82b4debcac Renamed Payment Request "Created" field to "CreatedTime" for consistancy since we already have a breaking change () 2021-12-23 14:48:10 +01:00
5f5f71bf37 Normalize greenfield responses for 404s () 2021-12-23 13:32:08 +09:00
ae33fc3031 PaymentReq "Created" field is not really a unix timestamp in JSON. Also renamed to "CreatedTime" like with invoices ()
* PaymentReq "Created" is not really a unix timestamp in JSON. Also renamed to "CreatedTime" like with invoices

* Renamed field so it is not a breaking change

* Update swagger.template.payment-requests.json
2021-12-23 13:30:49 +09:00
f63a9ed1a0 Added field "StoreId" to a Payment Request in Greenfield 2021-12-22 16:17:35 +01:00
9843f66bb6 Add example to cryptoCode in greenfield doc 2021-12-22 11:39:43 +09:00
b2c1846ebb Update link in README.md () 2021-12-21 09:32:39 +01:00
8e5a9251d6 Address feedback from code review
Thanks @kukks
2021-12-21 09:24:09 +01:00
3a59e2a5c4 Cache resolved store items in HTTP context 2021-12-21 09:24:09 +01:00
38ff3e5e89 Fix footer position on large breakpoints 2021-12-21 09:24:09 +01:00
1f0653985a Apply permission tag helpers to main navigation 2021-12-21 09:24:09 +01:00
a4fa61e5f6 Authorize invoice refund route
The customer gets a pull payment route to initiate the refund, so this one is only for merchants and needs to be authorized.
2021-12-21 09:24:09 +01:00
b68eae6f7d Re-add status messages to pull payments and payout views 2021-12-21 09:24:09 +01:00
2d7c5cabab Refactor page titles and active page functionality 2021-12-21 09:24:09 +01:00
42e731369e Remove section nav for pull payments and payouts 2021-12-21 09:24:09 +01:00
7d2627551b Store Settings nav update 2021-12-21 09:24:09 +01:00
f4bde164bf Changed API policy for calculating feeRate () 2021-12-20 11:16:23 +01:00
bb751793c8 Various minor UI fixes and cleanups ()
* Copy to clipboard fix

* Improve invoice status change wording and JS

* Re-add ability to delete apps

Now that the list view is gone, we need to move this option to the edit view

* Clean up app and payment request bundles

* Fix for invoice status change when dismissed
2021-12-19 13:05:10 +09:00
c68141119c [Greenfield] Send forbid 403 rather than empty results on /api/v1/stores () 2021-12-19 01:01:54 +09:00
163d1a195d Fix: DateTime passed to bitpay API weren't assumed UTC, remove DateTime.Now references () 2021-12-17 15:31:06 +09:00
6de4f6a3ac Mention the missing API permission in the response of a Greenfield request ()
* Mention the missing API permission in the response header or body

* Fixes + Added a unit test. 1 TODO remains.

* Added MissingPermissionDescription to the error

* Update BTCPayServer.Tests/GreenfieldAPITests.cs

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

* Fix tests

* [GreenField]: Make sure we are sending fully typed errors

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2021-12-16 23:04:06 +09:00
89a52703f6 Merge pull request from NicolasDorier/fixlightningapi
[Greenfield] Various store's lightning api fixes
2021-12-16 14:41:46 +09:00
4f7eeea14e Greenfield: Improve error message, do not use internal lightning node on store's lightning API 2021-12-16 14:27:34 +09:00
bbddd72780 Fix permissions required for store's lightning node in doc 2021-12-16 12:31:24 +09:00
ac099aa513 Change implementation of the Smtp server ()
* Change implementation of the Smtp server

* Update BTCPayServer/Services/Mails/EmailSettings.cs

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

Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2021-12-15 21:30:46 +09:00
ece5401121 Bump QR and LNURL libs 2021-12-15 10:14:20 +01:00
fd7b11518c Update changelog 2021-12-14 12:14:33 +09:00
9a70b4487c Fix: serverinfo 'available' wasn't set for BTC 2021-12-14 00:05:41 +09:00
19af02e71b Fix issue in invoice - changing the payment method () 2021-12-12 15:04:43 +09:00
619aa05e14 Update invoice state hint display () 2021-12-12 00:26:45 +09:00
cc60958b30 Upgrade Lightning lib () 2021-12-11 14:32:28 +09:00
bd2f35a241 Remove Ethereum support () 2021-12-11 14:31:41 +09:00
cf78987fab Fix LN Node availability check () 2021-12-11 14:31:25 +09:00
f8e6b51e9d Store-centric UI ()
* Update layout structure and header

* Implement store selector

* Simplify homepage

* Update layout

* Use dropdown for store selector

* Hide global nav in store context

* Horizontal section nav

* Remove outer section and container from content views

* Update nav

* Set store context for invoice and payment request lists

* Test fixes

* Persist menu collapse state on client-side

* MainNav as view component

* Update app routes to incorporate store context

* Test fixes

* Display ticker for altcoins build only

* Plugins nav

* Incorporate category for active page as well

* Update invoice icon

* Add apps list to nav

* Add store context to app type controllers

* Incorporate id for active page as well

* Test fixes

* AppsController cleanup

* Nav: Display only apps for the current store

* Remove leftover from merge

* Nav styles optimization

* Left-align content container

* Increase sidebar padding on desktop

* Use min-width for store selector menu

* Store settings nav update

* Update app and payment request routes

* Test fixes

* Refactor MainNav component to use StoresController

* Set store context for invoice actions

* Cleanups

* Remove CurrentStore checks

The response will be "Access denied" in case the CookieAuthorizationHandler cannot resolve the store.

* Remove unnecessary store context setters

* Test fix
2021-12-11 12:32:23 +09:00
2b1436e303 Fix build warning in Invoice Testing Controller () 2021-12-10 12:31:04 +01:00
cf772bb9e0 Improvements for disabled plugins status indicators ()
* Improvements for disabled plugins status indicators

close 

* Improve spacing

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2021-12-08 13:47:35 +09:00
fd75008499 Allow pull payments for store guests () 2021-12-08 00:40:24 +09:00
e113c12768 Fix copy pay button code () 2021-12-04 21:12:15 +01:00
3acda5b342 Fix code display () 2021-12-04 09:20:35 +01:00
bbea9d7a27 Swagger fixes () 2021-12-04 09:20:23 +01:00
b0125adfe9 Merge pull request from MsFloofie/patch-1
Fixed spelling mistake
2021-11-30 20:56:46 +01:00
d3b28a98be Fixed spelling mistake
Changed a misspelling from "synch" to "sync" ;)
2021-11-29 16:17:38 -05:00
c679654ada Send block reward to a random address instead of the invoice address. Default mine 1 block. ()
* Send block reward to a random address instead of the invoice address. Default mine 1 block.

* Using a random address for the block reward
2021-11-29 19:44:56 +09:00
26f3cffe5c Fix possible null reference exception when creating a pull payment ()
Co-authored-by: Andrew Camilleri <evilkukka@gmail.com>
2021-11-29 07:26:30 +01:00
8f0d82d219 Cheat mode to mine blocks () 2021-11-29 07:23:56 +01:00
6fec929656 Remove infinite loop in test 2021-11-27 11:40:06 +09:00
ec68d2a0e6 Remove Confirmed state in UI ()
* Remove Confirmed state in UI

Closes .

* Add infobox & improve refund tooltip

* Update BTCPayServer/Views/Invoice/ListInvoices.cshtml

Add @dennisreimann suggestion

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

* Add "don't show again" button

Adds a "Don't Show Again" button to the infobox. Also a bugfix that was preventing the new status from showing in the invoice details page.

* Add User blob and move invoice status notice to it

Co-authored-by: d11n <mail@dennisreimann.de>
Co-authored-by: Kukks <evilkukka@gmail.com>
2021-11-26 23:13:41 +09:00
f6afb9a3f0 CheatMode should use NBXplorer RPC proxy rather than hardcoded client 2021-11-26 18:34:40 +09:00
70bb6d999e Fix lightnign flaky test 2021-11-26 15:08:28 +09:00
e9074a8ec1 Test improvement exposing failing test ()
* Test improvement exposing failing test

* Test fixes

* Fix test

* update alt compose

* Fix test CanUsePullPaymentsViaUI

* Fix CanChangeUserMail

Co-authored-by: Kukks <evilkukka@gmail.com>
Co-authored-by: nicolas.dorier <nicolas.dorier@gmail.com>
2021-11-26 15:02:30 +09:00
9b730e784f Add pagination for API GetNotifications () 2021-11-26 11:55:59 +09:00
57852821f5 Remove sync modal from "Forgot password" page ()
* Update "Forgot password" page layout

* Fix null reference error
2021-11-26 11:54:33 +09:00
87061ecfc0 Support BC-UR v1 wallet import ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2021-11-25 10:25:22 +01:00
d555d2f3f6 Fix flaky alert message lookup 2021-11-25 10:24:14 +01:00
3b3fac98ad Improve Lightning settings display 2021-11-25 10:24:14 +01:00
285a30f67a Plugins: Provide extension points for Lightning setup 2021-11-25 10:24:14 +01:00
fa83304697 Improve time helper to also work with future datetimes 2021-11-25 10:24:14 +01:00
e42ef4b2f8 Plugins: Update startup for plugin compatibility 2021-11-25 10:24:14 +01:00
cc3908cdb3 Checkout: Fix UI flickering on payment method change () 2021-11-25 10:22:45 +01:00
e3def45c83 Update Bitbank API ()
Co-authored-by: Kukks <evilkukka@gmail.com>
2021-11-25 09:34:49 +01:00
4fe4cdb7bf Redirect to payment requests page instead of edit page on archive action ()
* Redirect to payment requests page instead of edit page on archive action

* Remove unused "using" directive
2021-11-24 20:27:56 +09:00
11a9b10a54 Minor visual improvements to various Server Settings views () 2021-11-24 09:59:19 +01:00
5164402e27 Merge pull request from btcpayserver/qoufhe
Remove Logs static singletons
2021-11-24 17:37:47 +09:00
20f32e94a8 Run tests in parallel 2021-11-23 19:17:17 +09:00
35aad4ebf9 Remove Logs static singletons 2021-11-23 13:55:34 +09:00
d60e4f8fe4 Merge pull request from btcpayserver/fweoqh
Isolate tests requiring internet access
2021-11-23 13:28:05 +09:00
e5a5eb3547 Add third party tests to the suite, skip azure test if not configured 2021-11-23 13:26:47 +09:00
fbb4b13898 Isolate tests requiring internet access 2021-11-23 12:53:05 +09:00
573f1ddf76 Move fast tests in own class () 2021-11-23 00:49:51 +09:00
ead0f284f2 Simple Invoice Detail View Cleanup ()
* changes copy to "unarchive", more clear

* adds semibold custom class

* adds class to TH elements & uppercases labels

* whitespace and padding patches

* uppercase patches

* removes class in site.css + updates class name

* Fix test

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2021-11-22 13:57:20 +09:00
6ff659fb99 Simple Payment Request and Pull Payment Views Improvements ()
* adds border radius to payment request view

* adds border radius to pull payments view

* spacings + font weights

* paddings + font weights

* updates text color

* updates font weights + text colors

* padding consistency

* switches padding to empty state

* update

* another padding fix

* Add "no details provided" when empty description

Co-authored-by: Samuel Adams <samuel.atwood@gmail.com>
2021-11-22 13:56:43 +09:00
194c0f14cb Format perk value correctly in crowdfund app ()
close 
2021-11-22 13:55:07 +09:00
7ab78fff3f Invoice View Improvements ()
* view improvements

* improves label, adds section headers, re-orders

* Available payment methods as checkboxes

* adds required label

* Update default payment method label

Thanks @woutersamaey for the suggestion.

* Move POS data and notifications to additional options

* Update display names

* adds checkbox to pull payments

* updates label

* Revert "updates label"

This reverts commit 9ed320e863951534d0dd359c13ec7dbaa4e1bd56.

* Revert "adds checkbox to pull payments"

This reverts commit 28ea6bfb6ed17df8cc44117814bffdfc80c12e70.

* removes required label

* Select all supported tx currencies by default

Slight modification to the checkbox list.

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
Co-authored-by: Samuel Adams <samuel.atwood@gmail.com>
2021-11-22 13:54:42 +09:00
eabe24bb3e changelog and bump 2021-11-20 22:45:21 +09:00
c01fae5fcd Bump LND () 2021-11-20 22:41:35 +09:00
c088e0fd55 add extension point in ui 2021-11-18 16:07:54 +01:00
cb1dbe7662 Improve invoice warning for no payment method configured
Closes .
2021-11-18 10:05:37 +01:00
03f8d6693d Improve Access Tokens View ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2021-11-18 10:04:20 +01:00
6813a6ea63 Refactoring: Invoice UI Controller cleanups
Simple and IDE proposed changes and cleanups I came across while working on .
2021-11-18 10:02:24 +01:00
4cd18a1b28 Improve Pay Button View ()
Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2021-11-18 09:58:29 +01:00
90907c6306 Improve Store User View () 2021-11-18 09:56:25 +01:00
c67b2be9d2 Fix Taproot checks after code removal
Necessary additions to 8d6c5dcd651c661e27f7dd7bfeac1e9a30540afa
2021-11-17 13:40:55 +01:00
8d6c5dcd65 Remove useless code 2021-11-16 21:02:25 +09:00
e5fa6fa55a Updates Pull Payment Payment Method ()
* adds checkbox to pull payment

* adds label improvement

* removes "back to list"

* Remove superfluous style block

Seems to be a copy and paste remainder

* Make custom CSS additional options

* Fix input name and test

* Improve display for case with only one payment method

* Fix test

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2021-11-16 12:58:17 +09:00
748c92436f Improve Rates View ()
* updates headers + changes copy

* type improvement

* updated copy

* updates copy

* updates copy

* Advanced rate rule scripting toggle

Co-authored-by: Dennis Reimann <mail@dennisreimann.de>
2021-11-16 12:50:35 +09:00
e98c6e69d4 Update POS accordion 2021-11-15 16:43:59 +01:00
c389aa0b99 Apply form styles to rich text editor 2021-11-15 16:43:59 +01:00
8696710ad1 Update app accordions 2021-11-15 16:43:59 +01:00
ce3bf91b29 Move custom CSS into additional options 2021-11-15 16:43:59 +01:00
2f5f397d33 Remove taproot activation code 2021-11-15 23:03:10 +09:00
b196bad75f Update changelog 2021-11-15 22:50:13 +09:00
b97dfa841a make elements regtest start with dynfed 2021-11-15 13:10:00 +01:00
31cf2671f5 Optimize admin user list 2021-11-15 10:28:45 +01:00
56c8e43ce8 Test fix 2021-11-15 09:35:56 +01:00
d7dc70c679 adds required label dot 2021-11-15 09:35:56 +01:00
ed0d7b75b5 updates left nav 2021-11-15 09:35:56 +01:00
7649f88173 updates title 2021-11-15 09:35:56 +01:00
e9b8035eae adds title and exposes delete 2021-11-15 09:35:56 +01:00
46486704ab notification updates 2021-11-15 09:35:56 +01:00
a6cee23591 2FA updates 2021-11-15 09:35:56 +01:00
33b5ade2b1 padding 2021-11-15 09:35:09 +01:00
0299eb1d24 whitespace 2021-11-15 09:35:09 +01:00
4f9ea39554 updates title 2021-11-15 09:35:09 +01:00
a2a49636e0 cleans up api key list view 2021-11-15 09:35:09 +01:00
609fd131eb Fix indentation. 2021-11-15 09:33:12 +01:00
08a3fb76fb Adding job to rebuild docs (swagger api) on new tag. 2021-11-15 09:33:12 +01:00
d5c38ef336 Add crypto code for invoice and pull payment payout API response ()
* Add "cryptoCode" for invoice payment method API endpoint response

* Add "cryptoCode" for pull payment payout API endpoint response

* Add "#nullable enable" to GreenFieldInvoiceController

* Add "#nullable enable" to GreenfieldPullPaymentController
2021-11-15 14:25:59 +09:00
03d2b6eabe Checkout page of 0 amount invoices shouldn't crash, but 404 2021-11-15 13:51:36 +09:00
cbcd59c996 Prevent creation of on-chain invoices below the dust limit ()
* Prevent creation of on-chain invoices below the dust limit

Fixes .

* Apply suggestions from code review

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

* small fix

* Fix selenium test

0.000000012 BTC (whether rounded or not) is below the dust threshold, causing this test to fail.

* fix CanCreateTopupInvoices test

Don't apply dust threshold conditional for topup invoices.

* Fix test, and minor changes

Co-authored-by: Nicolas Dorier <nicolas.dorier@gmail.com>
2021-11-15 13:48:07 +09:00
c5dc7475a6 Fix type of property cryptoCode () 2021-11-15 13:15:48 +09:00
40dff0381b Fix bug with fraction amount display in crowdfund app ()
* Update formatting

* Adjust formatting

* Adjust formatting

* Fix bug with BTC fraction amount display
2021-11-15 13:14:55 +09:00
39a1834a75 Merge pull request from satwo/fix-pull-payout-bug
Fix payout/pull payment crash when no payment method bug
2021-11-15 13:13:40 +09:00
84694d55ad Merge pull request from bolatovumar/fix/crowdfund-public-display-text
Show correct note when crowdfund is publicly visible
2021-11-15 13:10:07 +09:00
605920b421 Merge pull request from bolatovumar/fix-transaction-row-display-issues
Fix transaction row display issues
2021-11-15 13:09:32 +09:00
c2a420a291 Fix typo: "Prioriy" -> "Priority" () 2021-11-15 13:09:15 +09:00
037a77a573 Update Swagger docs for webhook event types ()
close 
2021-11-15 13:08:54 +09:00
b366e5dbf7 Fix issue with too much padding in comment input box 2021-11-14 16:18:59 -08:00
a277072968 Fix issue with weird label buttons 2021-11-14 16:17:16 -08:00
5523b554f1 Fix issue with giant label input group button 2021-11-14 16:07:27 -08:00
6ae9dee982 Fix giant "Save comment" button issue 2021-11-14 16:02:32 -08:00
dae4577b43 Fix label display issue 2021-11-14 16:02:11 -08:00
6ac9c74028 Show correct note when crowdfund is publicly visible
See discussion here: https://github.com/btcpayserver/btcpayserver/discussions/2968
2021-11-14 15:34:18 -08:00
a7ef9c7c27 Fix payout/pull payment crash when no payment method bug
Fixes .
2021-11-12 20:09:32 -05:00
08f57558da Fake payment fixes ()
Fixes and various minor improvements for the fake payment form.
2021-11-11 18:31:15 +09:00
28694859c9 Wallet settings merge ()
* Wallet settings merge

Merges both wallet settings screen from the wallets and the store section. Closes .

* Improve wallet transactions view

* Remove unnecessary row/col construct
2021-11-11 14:30:19 +09:00
be7cef29d8 UI changes
Removes the separate column for view style and instead appends it to the App Type column.
2021-11-10 10:52:14 +01:00
e914c84ad3 Adds View Style to Apps list 2021-11-10 10:52:14 +01:00
193b209c92 Add setup links for LN URL integration () 2021-11-10 10:50:39 +01:00
d5b25dde3d Add admin badge to user list ()
Co-authored-by: d11n <mail@dennisreimann.de>
2021-11-10 10:49:16 +01:00
931aa297cd Fix LockSubscription bug ()
This addresses an obscure issue where `LockSubscription` is unintentionally set to `true`,
which results in a large number of tests failing. h/t to @NicholasDorier for the assist.
2021-11-10 12:28:54 +09:00
fa10249893 Update Changelog.md 2021-11-10 10:49:56 +09:00
956 changed files with 36084 additions and 25622 deletions
.circleci
.editorconfig.gitignore
.vscode
BTCPayServer.Abstractions
BTCPayServer.Client
BTCPayServer.Client.csprojBTCPayServerClient.Invoices.csBTCPayServerClient.Lightning.Internal.csBTCPayServerClient.Lightning.Store.csBTCPayServerClient.Notifications.csBTCPayServerClient.OnChainPaymentMethods.csBTCPayServerClient.OnChainWallet.csBTCPayServerClient.PaymentRequests.csBTCPayServerClient.StoreEmail.csBTCPayServerClient.StoreUsers.csBTCPayServerClient.Users.csBTCPayServerClient.csGreenFieldAPIException.csGreenFieldValidationException.cs
JsonConverters
Models
Permissions.cs
BTCPayServer.Common
BTCPayServer.Data
BTCPayServer.PluginPacker
BTCPayServer.Plugins.Test
BTCPayServer.Rating
BTCPayServer.Tests
BTCPayServer
BTCPayServer.csproj
Components
Configuration
Controllers
AppsController.csBitpayAccessTokenController.csBitpayInvoiceController.csBitpayRateController.cs
GreenField
LnurlAuthService.csMacaroons.csUIAccountController.csUIAppsController.Crowdfund.csUIAppsController.PointOfSale.csUIAppsController.csUIAppsPublicController.csUIErrorController.csUIHomeController.csUIInvoiceController.Testing.csUIInvoiceController.UI.csUIInvoiceController.csUILNURLAuthController.csUILNURLController.csUIManageController.2FA.csUIManageController.APIKeys.csUIManageController.LoginCodes.csUIManageController.Notifications.csUIManageController.csUINotificationsController.csUIPaymentRequestController.csUIPublicController.csUIPublicLightningNodeInfoController.csUIPullPaymentController.csUIServerController.Plugins.csUIServerController.Storage.csUIServerController.Users.csUIServerController.csUIStorageController.csUIStorePullPaymentsController.PullPayments.csUIStoresController.Email.csUIStoresController.Integrations.csUIStoresController.LightningLike.csUIStoresController.Onchain.csUIStoresController.csUIUserStoresController.csUIVaultController.csUIWalletsController.PSBT.csUIWalletsController.csUserStoresController.cs
Data
DerivationSchemeParser.csDerivationSchemeSettings.csEventAggregator.cs
Events
ExplorerClientProvider.csExtensions.cs
Extensions
Fido2
Filters
HostedServices
Hosting
JsonHttpException.cs
Logging
ModelBinders
Models
PaymentRequest
Payments
Plugins
Program.cs
Properties
SSH
SearchString.cs
Security
Services
Altcoins
Apps
BTCPayNetworkJsonSerializerSettings.csBTCPayServerEnvironment.csCheater.csDefaultSwaggerProvider.csDelayedTransactionBroadcaster.cs
Fees
Invoices
Labels
LanguageService.csLightningClientFactoryService.cs
Mails
MigrationSettings.csNBXSyncSummaryProvider.csNBXplorerConnectionFactory.cs
Notifications
PaymentRequests
PoliciesSettings.csSettingsRepository.csSocks5HttpClientHandler.cs
Stores
ThemesSettings.csTorServices.csUserService.csWalletRepository.cs
Wallets
Storage
TagHelpers.cs
TagHelpers
Views
Account
Apps
AppsPublic
EthereumLikeStore
Fido2
Home
Invoice
LNURL
LightningLikePayout
Manage
Notifications
PaymentRequest
Public
Server
Shared
Shopify
StorePullPayments
Stores
UIAccount
UIApps
UIAppsPublic
UIError
UIFido2
UIHome
UIInvoice
UILNURL
UILNURLAuth
UILightning
UILightningLikePayout
UIManage
UIMoneroLikeStore
UINotifications
UIPaymentRequest
UIPublic
UIPublicLightningNodeInfo
UIPullPayment
UIServer
UIShopify
UIStorePullPayments
UIStores
UIUserStores
UIWallets
UIZcashLikeStore
UserStores
Wallets
WalletId.csWebSocketHelper.csWellKnownTempData.csbundleconfig.json
wwwroot
Build
Changelog.mdLICENSEREADME.mdamd64.Dockerfilearm32v7.Dockerfilearm64v8.Dockerfiledocker-entrypoint.sh

@ -2,15 +2,15 @@ version: 2
jobs:
fast_tests:
machine:
enabled: true
image: ubuntu-2004:202111-02
steps:
- checkout
- run:
command: |
cd .circleci && ./run-tests.sh "Fast=Fast" && ./can-build.sh
cd .circleci && ./run-tests.sh "Fast=Fast|ThirdParty=ThirdParty" && ./can-build.sh
selenium_tests:
machine:
enabled: true
image: ubuntu-2004:202111-02
steps:
- checkout
- run:
@ -18,32 +18,26 @@ jobs:
cd .circleci && ./run-tests.sh "Selenium=Selenium"
integration_tests:
machine:
enabled: true
image: ubuntu-2004:202111-02
steps:
- checkout
- run:
command: |
cd .circleci && ./run-tests.sh "Integration=Integration"
external_tests:
trigger_docs_build:
machine:
enabled: true
image: ubuntu-2004:202111-02
steps:
- checkout
- run:
command: |
if [ "$CIRCLE_PROJECT_USERNAME" == "btcpayserver" ] && [ "$CIRCLE_PROJECT_REPONAME" == "btcpayserver" ]; then
cd .circleci && ./run-tests.sh "ExternalIntegration=ExternalIntegration"
else
echo "Skipping running ExternalIntegration tests outside of context of main user and repository that have access to secrets"
fi
curl -X POST -H "Authorization: token $GH_PAT" -H "Accept: application/vnd.github.everest-preview+json" -H "Content-Type: application/json" https://api.github.com/repos/btcpayserver/btcpayserver-doc/dispatches --data '{"event_type": "build_docs"}'
# publish jobs require $DOCKERHUB_REPO, $DOCKERHUB_USER, $DOCKERHUB_PASS defined
amd64:
machine:
enabled: true
image: ubuntu-2004:202111-02
steps:
- checkout
- checkout
- run:
command: |
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
@ -56,9 +50,9 @@ jobs:
arm32v7:
machine:
enabled: true
image: ubuntu-2004:202111-02
steps:
- checkout
- checkout
- run:
command: |
sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset
@ -72,9 +66,9 @@ jobs:
arm64v8:
machine:
enabled: true
image: ubuntu-2004:202111-02
steps:
- checkout
- checkout
- run:
command: |
sudo docker run --rm --privileged multiarch/qemu-user-static:register --reset
@ -88,15 +82,10 @@ jobs:
multiarch:
machine:
enabled: true
image: circleci/classic:201808-01
image: ubuntu-2004:202201-02
steps:
- run:
command: |
# Turn on Experimental features
sudo mkdir $HOME/.docker
sudo sh -c 'echo "{ \"experimental\": \"enabled\" }" >> $HOME/.docker/config.json'
#
sudo docker login --username=$DOCKERHUB_USER --password=$DOCKERHUB_PASS
#
LATEST_TAG=${CIRCLE_TAG:1} #trim v from tag
@ -105,8 +94,7 @@ jobs:
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-arm32v7 --os linux --arch arm --variant v7
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG $DOCKERHUB_REPO:$LATEST_TAG-arm64v8 --os linux --arch arm64 --variant v8
sudo docker manifest push $DOCKERHUB_REPO:$LATEST_TAG -p
sudo docker manifest create --amend $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64 $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7 $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm64v8
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-amd64 --os linux --arch amd64
sudo docker manifest annotate $DOCKERHUB_REPO:$LATEST_TAG-altcoins $DOCKERHUB_REPO:$LATEST_TAG-altcoins-arm32v7 --os linux --arch arm --variant v7
@ -120,12 +108,15 @@ workflows:
- fast_tests
- selenium_tests
- integration_tests
- external_tests:
filters:
branches:
only: master
publish:
jobs:
- trigger_docs_build:
filters:
branches:
ignore: /.*/
# only act on version tags
tags:
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
- amd64:
filters:
# ignore any commit on any branch by default
@ -135,7 +126,6 @@ workflows:
# OR feature tags like vlndseedbackup
# OR features on specific versions like v1.0.0.88-lndseedbackup-1
tags:
only: /(v[1-9]+(\.[0-9]+)*(-[a-z0-9-]+)?)|(v[a-z0-9-]+)/
- arm32v7:
filters:

@ -121,8 +121,11 @@ csharp_space_between_method_declaration_name_and_open_parenthesis = false
csharp_space_between_method_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
csharp_style_prefer_null_check_over_type_check = true:warning
csharp_prefer_simple_using_statement = true:warning
# C++ Files
[*.{cpp,h,in}]
curly_bracket_next_line = true
indent_brace_style = Allman

1
.gitignore vendored

@ -299,3 +299,4 @@ BTCPayServer/wwwroot/bundles/*
BTCPayServer/testpwd
.DS_Store
Packed Plugins
Plugins/packed

4
.vscode/launch.json vendored

@ -10,14 +10,14 @@
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/BTCPayServer/bin/Debug/netcoreapp3.1/BTCPayServer.dll",
"program": "${workspaceFolder}/BTCPayServer/bin/Debug/net6.0/BTCPayServer.dll",
"args": [],
"cwd": "${workspaceFolder}/BTCPayServer",
"stopAtEntry": false,
// Enable launching a web browser when ASP.NET Core starts. For more information: https://aka.ms/VSCode-CS-LaunchJson-WebBrowser
"serverReadyAction": {
"action": "openExternally",
"pattern": "\\bListening on\\s+(https?://\\S+)"
"pattern": "\\bNow listening on:\\s+(https?://\\S+)"
},
"env": {
"ASPNETCORE_ENVIRONMENT": "Development"

@ -31,10 +31,10 @@
<None Include="icon.png" Pack="true" PackagePath="\" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="3.1.19" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="3.1.19" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="3.1.18" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="3.2.7" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.1" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Sqlite" Version="6.0.1" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="6.0.1" />
<PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="6.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\BTCPayServer.Client\BTCPayServer.Client.csproj" />

@ -2,11 +2,10 @@ namespace BTCPayServer.Configuration
{
public class DataDirectories
{
public string DataDir { get; set; }
public string PluginDir { get; set; }
public string DataDir { get; set; }
public string PluginDir { get; set; }
public string TempStorageDir { get; set; }
public string StorageDir { get; set; }
public string TempDir { get; set; }
}
}

@ -0,0 +1,7 @@
namespace BTCPayServer.Abstractions.Constants;
public class WellKnownTempData
{
public const string SuccessMessage = nameof(SuccessMessage);
public const string ErrorMessage = nameof(ErrorMessage);
}

@ -9,7 +9,7 @@ using Npgsql.EntityFrameworkCore.PostgreSQL.Migrations.Operations;
namespace BTCPayServer.Abstractions.Contracts
{
public abstract class BaseDbContextFactory<T> where T: DbContext
public abstract class BaseDbContextFactory<T> where T : DbContext
{
private readonly IOptions<DatabaseOptions> _options;
private readonly string _schemaPrefix;
@ -24,7 +24,9 @@ namespace BTCPayServer.Abstractions.Contracts
class CustomNpgsqlMigrationsSqlGenerator : NpgsqlMigrationsSqlGenerator
{
public CustomNpgsqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, IMigrationsAnnotationProvider annotations, Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlOptions opts) : base(dependencies, annotations, opts)
#pragma warning disable EF1001 // Internal EF Core API usage.
public CustomNpgsqlMigrationsSqlGenerator(MigrationsSqlGeneratorDependencies dependencies, Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure.Internal.INpgsqlOptions opts) : base(dependencies, opts)
#pragma warning restore EF1001 // Internal EF Core API usage.
{
}
@ -90,10 +92,10 @@ namespace BTCPayServer.Abstractions.Contracts
.ReplaceService<IMigrationsSqlGenerator, CustomNpgsqlMigrationsSqlGenerator>();
break;
case DatabaseType.MySQL:
builder.UseMySql(_options.Value.ConnectionString, o =>
builder.UseMySql(_options.Value.ConnectionString, ServerVersion.AutoDetect(_options.Value.ConnectionString), o =>
{
o.EnableRetryOnFailure(10);
if (!string.IsNullOrEmpty(_schemaPrefix))
{
o.MigrationsHistoryTable(_schemaPrefix);
@ -104,6 +106,6 @@ namespace BTCPayServer.Abstractions.Contracts
throw new ArgumentOutOfRangeException();
}
}
}
}

@ -1,10 +1,12 @@
using System.Threading.Tasks;
using BTCPayServer.Client;
using Microsoft.AspNetCore.Http;
namespace BTCPayServer.Abstractions.Contracts
{
public interface IBTCPayServerClientFactory
{
Task<BTCPayServerClient> Create(string userId, params string[] storeIds);
Task<BTCPayServerClient> Create(string userId, string[] storeIds, HttpContext httpRequest);
}
}

@ -28,5 +28,5 @@ namespace BTCPayServer.Abstractions.Contracts
}
}
}
}

@ -0,0 +1,17 @@
#nullable enable
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;
namespace BTCPayServer.Abstractions.Contracts;
public interface IFileService
{
Task<bool> IsAvailable();
Task<IStoredFile> AddFile(IFormFile file, string userId);
Task<IStoredFile> AddFile(Uri file, string userId);
Task<string?> GetFileUrl(Uri baseUri, string fileId);
Task<string?> GetTemporaryFileUrl(Uri baseUri, string fileId, DateTimeOffset expiry,
bool isDownload);
Task RemoveFile(string fileId, string userId);
}

@ -7,7 +7,7 @@ namespace BTCPayServer.Abstractions.Contracts
public abstract string Identifier { get; }
public abstract string NotificationType { get; }
}
public interface INotificationHandler
{
string NotificationType { get; }
@ -15,7 +15,7 @@ namespace BTCPayServer.Abstractions.Contracts
public (string identifier, string name)[] Meta { get; }
void FillViewModel(object notification, NotificationViewModel vm);
}
public class NotificationViewModel
{
public string Id { get; set; }

@ -5,7 +5,7 @@ namespace BTCPayServer.Abstractions.Contracts
public interface IPluginHookFilter
{
public string Hook { get; }
Task<object> Execute(object args);
}
}

@ -0,0 +1,12 @@
using System;
namespace BTCPayServer.Abstractions.Contracts;
public interface IStoredFile
{
string Id { get; set; }
string FileName { get; set; }
string StorageFileName { get; set; }
DateTime Timestamp { get; set; }
string ApplicationUserId { get; set; }
}

@ -0,0 +1,9 @@
using System.Threading.Tasks;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Abstractions.Contracts;
public interface ISwaggerProvider
{
Task<JObject> Fetch();
}

@ -3,7 +3,7 @@ namespace BTCPayServer.Abstractions.Contracts
public interface IUIExtension
{
string Partial { get; }
string Location { get; }
}
}

@ -1,20 +0,0 @@
using System.Text.Json;
using BTCPayServer.Abstractions.Models;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
namespace BTCPayServer.Abstractions.Extensions
{
public static class SetStatusMessageModelExtensions
{
public static void SetStatusMessageModel(this ITempDataDictionary tempData, StatusMessageModel statusMessage)
{
if (statusMessage == null)
{
tempData.Remove("StatusMessageModel");
return;
}
tempData["StatusMessageModel"] = JsonSerializer.Serialize(statusMessage, new JsonSerializerOptions());
}
}
}

@ -0,0 +1,43 @@
using System.Collections.Generic;
using BTCPayServer.Client.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
namespace BTCPayServer.Abstractions.Extensions;
public static class GreenfieldExtensions
{
public static IActionResult CreateValidationError(this ControllerBase controller, ModelStateDictionary modelState)
{
return controller.UnprocessableEntity(modelState.ToGreenfieldValidationError());
}
public static List<GreenfieldValidationError> ToGreenfieldValidationError(this ModelStateDictionary modelState)
{
List<GreenfieldValidationError> errors = new List<GreenfieldValidationError>();
foreach (var error in modelState)
{
foreach (var errorMessage in error.Value.Errors)
{
errors.Add(new GreenfieldValidationError(error.Key, errorMessage.ErrorMessage));
}
}
return errors;
}
public static IActionResult CreateAPIError(this ControllerBase controller, string errorCode, string errorMessage)
{
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));
}
}

@ -0,0 +1,120 @@
using System;
using Microsoft.AspNetCore.Http;
namespace BTCPayServer.Abstractions.Extensions;
public static class HttpRequestExtensions
{
public static bool IsOnion(this HttpRequest request)
{
if (request?.Host.Host == null)
return false;
return request.Host.Host.EndsWith(".onion", StringComparison.OrdinalIgnoreCase);
}
public static string GetAbsoluteRoot(this HttpRequest request)
{
return string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent(),
request.PathBase.ToUriComponent());
}
public static Uri GetAbsoluteRootUri(this HttpRequest request)
{
return new Uri(request.GetAbsoluteRoot());
}
public static string GetCurrentUrl(this HttpRequest request)
{
return string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent(),
request.PathBase.ToUriComponent(),
request.Path.ToUriComponent());
}
public static string GetCurrentPath(this HttpRequest request)
{
return string.Concat(
request.PathBase.ToUriComponent(),
request.Path.ToUriComponent());
}
public static string GetCurrentPathWithQueryString(this HttpRequest request)
{
return request.PathBase + request.Path + request.QueryString;
}
/// <summary>
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
/// If 'toto' and RootPath is empty returns '/toto'
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <returns></returns>
public static string GetRelativePath(this HttpRequest request, string path)
{
if (path.Length > 0 && path[0] != '/')
path = $"/{path}";
return string.Concat(
request.PathBase.ToUriComponent(),
path);
}
/// <summary>
/// If 'https://example.com/toto' returns 'https://example.com/toto'
/// If 'toto' and RootPath is 'rootpath' returns '/rootpath/toto'
/// If 'toto' and RootPath is empty returns '/toto'
/// </summary>
/// <param name="request"></param>
/// <param name="path"></param>
/// <returns></returns>
public static string GetRelativePathOrAbsolute(this HttpRequest request, string path)
{
if (!Uri.TryCreate(path, UriKind.RelativeOrAbsolute, out var uri) ||
uri.IsAbsoluteUri)
return path;
if (path.Length > 0 && path[0] != '/')
path = $"/{path}";
return string.Concat(
request.PathBase.ToUriComponent(),
path);
}
public static string GetAbsoluteUri(this HttpRequest request, string redirectUrl)
{
bool isRelative =
(redirectUrl.Length > 0 && redirectUrl[0] == '/')
|| !new Uri(redirectUrl, UriKind.RelativeOrAbsolute).IsAbsoluteUri;
return isRelative ? request.GetAbsoluteRoot() + redirectUrl : redirectUrl;
}
/// <summary>
/// Will return an absolute URL.
/// If `relativeOrAsbolute` is absolute, returns it.
/// If `relativeOrAsbolute` is relative, send absolute url based on the HOST of this request (without PathBase)
/// </summary>
/// <param name="request"></param>
/// <param name="relativeOrAbsolte"></param>
/// <returns></returns>
public static Uri GetAbsoluteUriNoPathBase(this HttpRequest request, Uri relativeOrAbsolute = null)
{
if (relativeOrAbsolute == null)
{
return new Uri(string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent()), UriKind.Absolute);
}
if (relativeOrAbsolute.IsAbsoluteUri)
return relativeOrAbsolute;
return new Uri(string.Concat(
request.Scheme,
"://",
request.Host.ToUriComponent()) + relativeOrAbsolute.ToString().WithStartingSlash(), UriKind.Absolute);
}
}

@ -0,0 +1,59 @@
using System.Text.Json;
using BTCPayServer.Abstractions.Constants;
using BTCPayServer.Abstractions.Models;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Abstractions.Extensions;
public static class SetStatusMessageModelExtensions
{
public static void SetStatusMessageModel(this ITempDataDictionary tempData, StatusMessageModel statusMessage)
{
if (statusMessage == null)
{
tempData.Remove("StatusMessageModel");
return;
}
tempData["StatusMessageModel"] = JsonSerializer.Serialize(statusMessage, new JsonSerializerOptions());
}
public static StatusMessageModel GetStatusMessageModel(this ITempDataDictionary tempData)
{
tempData.TryGetValue(WellKnownTempData.SuccessMessage, out var successMessage);
tempData.TryGetValue(WellKnownTempData.ErrorMessage, out var errorMessage);
tempData.TryGetValue("StatusMessageModel", out var model);
if (successMessage != null || errorMessage != null)
{
var parsedModel = new StatusMessageModel();
parsedModel.Message = (string)successMessage ?? (string)errorMessage;
if (successMessage != null)
{
parsedModel.Severity = StatusMessageModel.StatusSeverity.Success;
}
else
{
parsedModel.Severity = StatusMessageModel.StatusSeverity.Error;
}
return parsedModel;
}
else if (model != null && model is string str)
{
return JObject.Parse(str).ToObject<StatusMessageModel>();
}
return null;
}
public static bool HasStatusMessage(this ITempDataDictionary tempData)
{
return (tempData.Peek(WellKnownTempData.SuccessMessage) ??
tempData.Peek(WellKnownTempData.ErrorMessage) ??
tempData.Peek("StatusMessageModel")) != null;
}
public static bool HasErrorMessage(this ITempDataDictionary tempData)
{
return GetStatusMessageModel(tempData)?.Severity == StatusMessageModel.StatusSeverity.Error;
}
}

@ -0,0 +1,45 @@
using System;
using System.IO;
using System.Linq;
namespace BTCPayServer.Abstractions.Extensions;
public static class StringExtensions
{
public static bool IsValidFileName(this string fileName)
{
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c)
|| c == Path.AltDirectorySeparatorChar
|| c == Path.DirectorySeparatorChar
|| c == Path.PathSeparator
|| c == '\\');
}
public static string Truncate(this string value, int maxLength)
{
if (string.IsNullOrEmpty(value))
return value;
return value.Length <= maxLength ? value : value.Substring(0, maxLength);
}
public static string WithTrailingSlash(this string str)
{
if (str.EndsWith("/", StringComparison.InvariantCulture))
return str;
return str + "/";
}
public static string WithStartingSlash(this string str)
{
if (str.StartsWith("/", StringComparison.InvariantCulture))
return str;
return $"/{str}";
}
public static string WithoutEndingSlash(this string str)
{
if (str.EndsWith("/", StringComparison.InvariantCulture))
return str.Substring(0, str.Length - 1);
return str;
}
}

@ -9,44 +9,70 @@ namespace BTCPayServer.Abstractions.Extensions
{
private const string ACTIVE_CATEGORY_KEY = "ActiveCategory";
private const string ACTIVE_PAGE_KEY = "ActivePage";
private const string ACTIVE_ID_KEY = "ActiveId";
public static void SetActivePageAndTitle<T>(this ViewDataDictionary viewData, T activePage, string title = null, string mainTitle = null)
public static void SetActivePage<T>(this ViewDataDictionary viewData, T activePage, string title = null, string activeId = null)
where T : IConvertible
{
// Browser Title
viewData["Title"] = title ?? activePage.ToString();
// Breadcrumb
viewData["MainTitle"] = mainTitle;
viewData["PageTitle"] = title;
SetActivePage(viewData, activePage.ToString(), activePage.GetType().ToString(), title, activeId);
}
public static void SetActivePage(this ViewDataDictionary viewData, string activePage, string category, string title = null, string activeId = null)
{
// Page Title
viewData["Title"] = title ?? activePage;
// Navigation
viewData[ACTIVE_PAGE_KEY] = activePage;
SetActiveCategory(viewData, activePage.GetType());
viewData[ACTIVE_ID_KEY] = activeId;
SetActiveCategory(viewData, category);
}
public static void SetActiveCategory<T>(this ViewDataDictionary viewData, T activeCategory)
{
SetActiveCategory(viewData, activeCategory.ToString());
}
public static void SetActiveCategory(this ViewDataDictionary viewData, string activeCategory)
{
viewData[ACTIVE_CATEGORY_KEY] = activeCategory;
}
public static string IsActiveCategory<T>(this ViewDataDictionary viewData, T category)
public static string IsActiveCategory<T>(this ViewDataDictionary viewData, T category, object id = null)
{
return IsActiveCategory(viewData, category.ToString(), id);
}
public static string IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY))
{
return null;
}
var activeCategory = (T)viewData[ACTIVE_CATEGORY_KEY];
return category.Equals(activeCategory) ? "active" : null;
var activeId = viewData[ACTIVE_ID_KEY];
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
var categoryMatch = category.Equals(activeCategory, StringComparison.InvariantCultureIgnoreCase);
var idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryMatch && idMatch ? "active" : null;
}
public static string IsActivePage<T>(this ViewDataDictionary viewData, T page)
public static string IsActivePage<T>(this ViewDataDictionary viewData, T page, object id = null)
where T : IConvertible
{
return IsActivePage(viewData, page.ToString(), page.GetType().ToString(), id);
}
public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
{
return null;
}
var activePage = (T)viewData[ACTIVE_PAGE_KEY];
return page.Equals(activePage) ? "active" : null;
var activeId = viewData[ACTIVE_ID_KEY];
var activePage = viewData[ACTIVE_PAGE_KEY]?.ToString();
var activeCategory = viewData[ACTIVE_CATEGORY_KEY]?.ToString();
var categoryAndPageMatch = (category == null || activeCategory.Equals(category, StringComparison.InvariantCultureIgnoreCase)) && page.Equals(activePage, StringComparison.InvariantCultureIgnoreCase);
var idMatch = id == null || activeId == null || id.Equals(activeId);
return categoryAndPageMatch && idMatch ? "active" : null;
}
public static HtmlString ToBrowserDate(this DateTimeOffset date)
@ -60,10 +86,13 @@ namespace BTCPayServer.Abstractions.Extensions
var displayDate = date.ToString("o", CultureInfo.InvariantCulture);
return new HtmlString($"<span class='localizeDate'>{displayDate}</span>");
}
public static string ToTimeAgo(this DateTimeOffset date)
{
var formatted = (DateTimeOffset.UtcNow - date).TimeString() + " ago";
var diff = DateTimeOffset.UtcNow - date;
var formatted = diff.Seconds > 0
? $"{diff.TimeString()} ago"
: $"in {diff.Negate().TimeString()}";
return formatted;
}

@ -96,8 +96,7 @@ namespace BTCPayServer.Security
/// <param name="script"></param>
public void AllowInline(string script)
{
if (script is null)
throw new ArgumentNullException(nameof(script));
ArgumentNullException.ThrowIfNull(script);
var sha = GetSha256(script);
Add("script-src", $"'sha256-{sha}'");
}

@ -3,7 +3,7 @@ using BTCPayServer.Abstractions.Contracts;
namespace BTCPayServer.Abstractions.Services
{
public abstract class PluginAction<T>:IPluginHookAction
public abstract class PluginAction<T> : IPluginHookAction
{
public abstract string Hook { get; }
public Task Execute(object args)

@ -3,7 +3,7 @@ using BTCPayServer.Abstractions.Contracts;
namespace BTCPayServer.Abstractions.Services
{
public abstract class PluginHookFilter<T>:IPluginHookFilter
public abstract class PluginHookFilter<T> : IPluginHookFilter
{
public abstract string Hook { get; }

@ -2,7 +2,7 @@ using BTCPayServer.Abstractions.Contracts;
namespace BTCPayServer.Abstractions.Services
{
public class UIExtension: IUIExtension
public class UIExtension : IUIExtension
{
public UIExtension(string partial, string location)
{

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<LangVersion>10.0</LangVersion>
<Company>BTCPay Server</Company>
<Copyright>Copyright © BTCPay Server 2020</Copyright>
<Description>A client library for BTCPay Server Greenfield API</Description>
@ -13,7 +14,7 @@
<RepositoryType>git</RepositoryType>
</PropertyGroup>
<PropertyGroup>
<Version Condition=" '$(Version)' == '' ">1.5.0</Version>
<Version Condition=" '$(Version)' == '' ">1.6.0</Version>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PublishRepositoryUrl>true</PublishRepositoryUrl>
@ -27,8 +28,8 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="NBitcoin" Version="6.0.17" />
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.2.7" />
<PackageReference Include="NBitcoin" Version="7.0.1" />
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.2" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>

@ -35,16 +35,18 @@ namespace BTCPayServer.Client
if (textSearch != null)
queryPayload.Add(nameof(textSearch), textSearch);
if (status != null)
queryPayload.Add(nameof(status), status.Select(s=> s.ToString().ToLower()).ToArray());
queryPayload.Add(nameof(status), status.Select(s => s.ToString().ToLower()).ToArray());
if(skip != null) {
if (skip != null)
{
queryPayload.Add(nameof(skip), skip);
}
if(take != null) {
if (take != null)
{
queryPayload.Add(nameof(take), take);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices",
@ -114,7 +116,7 @@ namespace BTCPayServer.Client
public virtual async Task<InvoiceData> UnarchiveInvoice(string storeId, string invoiceId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive",
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/unarchive",
method: HttpMethod.Post), token);
return await HandleResponse<InvoiceData>(response);
}
@ -122,7 +124,7 @@ namespace BTCPayServer.Client
public virtual async Task ActivateInvoicePaymentMethod(string storeId, string invoiceId, string paymentMethod, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate",
CreateHttpRequest($"api/v1/stores/{storeId}/invoices/{invoiceId}/payment-methods/{paymentMethod}/activate",
method: HttpMethod.Post), token);
await HandleResponse(response);
}

@ -54,8 +54,7 @@ namespace BTCPayServer.Client
return await HandleResponse<string>(response);
}
public virtual async Task PayLightningInvoice(string cryptoCode, PayLightningInvoiceRequest request,
public virtual async Task<LightningPaymentData> PayLightningInvoice(string cryptoCode, PayLightningInvoiceRequest request,
CancellationToken token = default)
{
if (request == null)
@ -63,7 +62,18 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/invoices/pay", bodyPayload: request,
method: HttpMethod.Post), token);
await HandleResponse(response);
return await HandleResponse<LightningPaymentData>(response);
}
public virtual async Task<LightningPaymentData> GetLightningPayment(string cryptoCode,
string paymentHash, CancellationToken token = default)
{
if (paymentHash == null)
throw new ArgumentNullException(nameof(paymentHash));
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/payments/{paymentHash}",
method: HttpMethod.Get), token);
return await HandleResponse<LightningPaymentData>(response);
}
public virtual async Task<LightningInvoiceData> GetLightningInvoice(string cryptoCode,

@ -67,6 +67,17 @@ namespace BTCPayServer.Client
await HandleResponse(response);
}
public virtual async Task<LightningPaymentData> GetLightningPayment(string storeId, string cryptoCode,
string paymentHash, CancellationToken token = default)
{
if (paymentHash == null)
throw new ArgumentNullException(nameof(paymentHash));
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/payments/{paymentHash}",
method: HttpMethod.Get), token);
return await HandleResponse<LightningPaymentData>(response);
}
public virtual async Task<LightningInvoiceData> GetLightningInvoice(string storeId, string cryptoCode,
string invoiceId, CancellationToken token = default)
{

@ -9,13 +9,22 @@ namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<NotificationData>> GetNotifications(bool? seen = null,
CancellationToken token = default)
public virtual async Task<IEnumerable<NotificationData>> GetNotifications(bool? seen = null, int? skip = null,
int? take = null, CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/users/me/notifications",
seen != null ? new Dictionary<string, object>() {{nameof(seen), seen}} : null), token);
Dictionary<string, object> queryPayload = new Dictionary<string, object>();
if (seen != null)
queryPayload.Add(nameof(seen), seen);
if (skip != null)
queryPayload.Add(nameof(skip), skip);
if (take != null)
queryPayload.Add(nameof(take), take);
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/users/me/notifications",
queryPayload), token);
return await HandleResponse<IEnumerable<NotificationData>>(response);
}
@ -32,7 +41,7 @@ namespace BTCPayServer.Client
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/users/me/notifications/{notificationId}",
method: HttpMethod.Put, bodyPayload: new UpdateNotification() {Seen = seen}), token);
method: HttpMethod.Put, bodyPayload: new UpdateNotification() { Seen = seen }), token);
return await HandleResponse<NotificationData>(response);
}

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

@ -16,7 +16,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet"), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet"), token);
return await HandleResponse<OnChainWalletOverviewData>(response);
}
public virtual async Task<OnChainWalletFeeRateData> GetOnChainFeeRate(string storeId, string cryptoCode, int? blockTarget = null,
@ -25,35 +25,35 @@ namespace BTCPayServer.Client
Dictionary<string, object> queryParams = new Dictionary<string, object>();
if (blockTarget != null)
{
queryParams.Add("blockTarget",blockTarget);
queryParams.Add("blockTarget", blockTarget);
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/feeRate", queryParams), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/feeRate", queryParams), token);
return await HandleResponse<OnChainWalletFeeRateData>(response);
}
public virtual async Task<OnChainWalletAddressData> GetOnChainWalletReceiveAddress(string storeId, string cryptoCode, bool forceGenerate = false,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address", new Dictionary<string, object>()
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address", new Dictionary<string, object>()
{
{"forceGenerate", forceGenerate}
}), token);
return await HandleResponse<OnChainWalletAddressData>(response);
}
public virtual async Task UnReserveOnChainWalletReceiveAddress(string storeId, string cryptoCode,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/address",method:HttpMethod.Delete), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/address", method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<IEnumerable<OnChainWalletTransactionData>> ShowOnChainWalletTransactions(
string storeId, string cryptoCode, TransactionStatus[] statusFilter = null,
CancellationToken token = default)
@ -65,30 +65,41 @@ namespace BTCPayServer.Client
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", query), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions", query), token);
return await HandleResponse<IEnumerable<OnChainWalletTransactionData>>(response);
}
public virtual async Task<OnChainWalletTransactionData> GetOnChainWalletTransaction(
string storeId, string cryptoCode, string transactionId,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions/{transactionId}"), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions/{transactionId}"), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
public virtual async Task<OnChainWalletTransactionData> PatchOnChainWalletTransaction(
string storeId, string cryptoCode, string transactionId,
PatchOnChainTransactionRequest request,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions/{transactionId}", queryPayload: null, bodyPayload: request, HttpMethod.Patch), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
public virtual async Task<IEnumerable<OnChainWalletUTXOData>> GetOnChainWalletUTXOs(string storeId,
string cryptoCode,
CancellationToken token = default)
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/utxos"), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/utxos"), token);
return await HandleResponse<IEnumerable<OnChainWalletUTXOData>>(response);
}
public virtual async Task<OnChainWalletTransactionData> CreateOnChainTransaction(string storeId,
string cryptoCode, CreateOnChainTransactionRequest request,
CancellationToken token = default)
@ -100,10 +111,10 @@ namespace BTCPayServer.Client
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
return await HandleResponse<OnChainWalletTransactionData>(response);
}
public virtual async Task<Transaction> CreateOnChainTransactionButDoNotBroadcast(string storeId,
string cryptoCode, CreateOnChainTransactionRequest request, Network network,
CancellationToken token = default)
@ -115,7 +126,7 @@ namespace BTCPayServer.Client
}
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/Onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/transactions", null, request, HttpMethod.Post), token);
return Transaction.Parse(await HandleResponse<string>(response), network);
}
}

@ -16,7 +16,7 @@ namespace BTCPayServer.Client
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-requests",
new Dictionary<string, object>() {{nameof(includeArchived), includeArchived}}), token);
new Dictionary<string, object>() { { nameof(includeArchived), includeArchived } }), token);
return await HandleResponse<IEnumerable<PaymentRequestData>>(response);
}

@ -0,0 +1,37 @@
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<EmailSettingsData> GetStoreEmailSettings(string storeId,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/email", method: HttpMethod.Get),
token);
return await HandleResponse<EmailSettingsData>(response);
}
public virtual async Task<EmailSettingsData> UpdateStoreEmailSettings(string storeId, EmailSettingsData request,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/email", bodyPayload: request, method: HttpMethod.Put),
token);
return await HandleResponse<EmailSettingsData>(response);
}
public virtual async Task SendEmail(string storeId, SendEmailRequest request,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/email/send", bodyPayload: request, method: HttpMethod.Post),
token);
await HandleResponse(response);
}
}
}

@ -0,0 +1,37 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<StoreUserData>> GetStoreUsers(string storeId,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/users"), token);
return await HandleResponse<IEnumerable<StoreUserData>>(response);
}
public virtual async Task RemoveStoreUser(string storeId, string userId, CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/users/{userId}", method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task AddStoreUser(string storeId, StoreUserData request,
CancellationToken token = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/users", bodyPayload: request, method: HttpMethod.Post),
token);
await HandleResponse(response);
}
}
}

@ -27,6 +27,27 @@ namespace BTCPayServer.Client
await HandleResponse(response);
}
public virtual async Task<ApplicationUserData> GetUserByIdOrEmail(string idOrEmail, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{idOrEmail}", null, HttpMethod.Get), token);
return await HandleResponse<ApplicationUserData>(response);
}
public virtual async Task ToggleUser(string idOrEmail, bool enabled, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{idOrEmail}/toggle", null,new
{
enabled
} , HttpMethod.Post), token);
await HandleResponse(response);
}
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);
}
public virtual async Task DeleteCurrentUser(CancellationToken token = default)
{
await DeleteUser("me", token);

@ -18,7 +18,6 @@ namespace BTCPayServer.Client
private readonly string _username;
private readonly string _password;
private readonly HttpClient _httpClient;
public Uri Host => _btcpayHost;
public string APIKey => _apiKey;
@ -48,18 +47,25 @@ namespace BTCPayServer.Client
protected async Task HandleResponse(HttpResponseMessage message)
{
if (message.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity)
if (!message.IsSuccessStatusCode && message.Content?.Headers?.ContentType?.MediaType?.StartsWith("application/json", StringComparison.OrdinalIgnoreCase) is true)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldValidationError[]>(await message.Content.ReadAsStringAsync());
;
throw new GreenFieldValidationException(err);
if (message.StatusCode == System.Net.HttpStatusCode.UnprocessableEntity)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldValidationError[]>(await message.Content.ReadAsStringAsync());
throw new GreenfieldValidationException(err);
}
if (message.StatusCode == System.Net.HttpStatusCode.Forbidden)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldPermissionAPIError>(await message.Content.ReadAsStringAsync());
throw new GreenfieldAPIException((int)message.StatusCode, err);
}
else
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldAPIError>(await message.Content.ReadAsStringAsync());
if (err.Code != null)
throw new GreenfieldAPIException((int)message.StatusCode, err);
}
}
else if (message.StatusCode == System.Net.HttpStatusCode.BadRequest)
{
var err = JsonConvert.DeserializeObject<Models.GreenfieldAPIError>(await message.Content.ReadAsStringAsync());
throw new GreenFieldAPIException(err);
}
message.EnsureSuccessStatusCode();
}
@ -77,6 +83,13 @@ namespace BTCPayServer.Client
using var resp = await _httpClient.SendAsync(CreateHttpRequest(path, queryPayload, method), cancellationToken);
return await HandleResponse<T>(resp);
}
public async Task<T> SendHttpRequest<T>(string path,
object bodyPayload = null,
HttpMethod method = null, CancellationToken cancellationToken = default)
{
using var resp = await _httpClient.SendAsync(CreateHttpRequest(path: path, bodyPayload: bodyPayload, method: method), cancellationToken);
return await HandleResponse<T>(resp);
}
protected virtual HttpRequestMessage CreateHttpRequest(string path,
Dictionary<string, object> queryPayload = null,
HttpMethod method = null)

@ -2,14 +2,16 @@ using System;
namespace BTCPayServer.Client
{
public class GreenFieldAPIException : Exception
public class GreenfieldAPIException : Exception
{
public GreenFieldAPIException(Models.GreenfieldAPIError error) : base(error.Message)
public GreenfieldAPIException(int httpCode, Models.GreenfieldAPIError error) : base(error.Message)
{
if (error == null)
throw new ArgumentNullException(nameof(error));
HttpCode = httpCode;
APIError = error;
}
public Models.GreenfieldAPIError APIError { get; }
public int HttpCode { get; set; }
}
}

@ -4,9 +4,9 @@ using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public class GreenFieldValidationException : Exception
public class GreenfieldValidationException : Exception
{
public GreenFieldValidationException(Models.GreenfieldValidationError[] errors) : base(BuildMessage(errors))
public GreenfieldValidationException(Models.GreenfieldValidationError[] errors) : base(BuildMessage(errors))
{
ValidationErrors = errors;
}

@ -1,4 +1,4 @@
using System;
using System;
using NBitcoin;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;

@ -19,7 +19,7 @@ namespace BTCPayServer.Client.JsonConverters
public override void WriteJson(JsonWriter writer, [AllowNull] NodeInfo value, JsonSerializer serializer)
{
if (value is NodeInfo)
if (value is not null)
writer.WriteValue(value.ToString());
}
}

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

@ -29,6 +29,17 @@ namespace BTCPayServer.Client.JsonConverters
return TimeSpan.FromMinutes(value);
}
}
public class Days : TimeSpanJsonConverter
{
protected override long ToLong(TimeSpan value)
{
return (long)value.TotalDays;
}
protected override TimeSpan ToTimespan(long value)
{
return TimeSpan.FromDays(value);
}
}
public override bool CanConvert(Type objectType)
{
return objectType == typeof(TimeSpan) || objectType == typeof(TimeSpan?);

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;

@ -1,4 +1,4 @@
using System;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
@ -21,7 +21,7 @@ public class WordlistJsonConverter : JsonConverter
{"PortugueseBrazil", Wordlist.PortugueseBrazil},
{"Czech", Wordlist.Czech}
};
_WordlistsReverse = _Wordlists.ToDictionary(kv => kv.Value, kv => kv.Key);
}

@ -4,4 +4,4 @@ namespace BTCPayServer.Client.Models
{
public string Email { get; set; }
}
}
}

@ -35,5 +35,7 @@ namespace BTCPayServer.Client.Models
/// </summary>
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? Created { get; set; }
public bool Disabled { get; set; }
}
}

@ -1,6 +1,6 @@
using System;
using BTCPayServer.Lightning;
using BTCPayServer.Lightning.JsonConverters;
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
@ -11,15 +11,19 @@ namespace BTCPayServer.Client.Models
{
}
public CreateLightningInvoiceRequest(LightMoney amount, string description, TimeSpan expiry)
{
Amount = amount;
Description = description;
Expiry = expiry;
}
[JsonConverter(typeof(BTCPayServer.Client.JsonConverters.LightMoneyJsonConverter))]
[JsonConverter(typeof(JsonConverters.LightMoneyJsonConverter))]
public LightMoney Amount { get; set; }
public string Description { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.UInt256JsonConverter))]
public uint256 DescriptionHash { get; set; }
[JsonConverter(typeof(JsonConverters.TimeSpanJsonConverter.Seconds))]
public TimeSpan Expiry { get; set; }
public bool PrivateRouteHints { get; set; }

@ -18,7 +18,7 @@ namespace BTCPayServer.Client.Models
}
[JsonConverter(typeof(FeeRateJsonConverter))]
public FeeRate FeeRate { get; set; }
public bool ProceedWithPayjoin { get; set; }= true;
public bool ProceedWithPayjoin { get; set; } = true;
public bool ProceedWithBroadcast { get; set; } = true;
public bool NoChange { get; set; } = false;
[JsonProperty(ItemConverterType = typeof(OutpointJsonConverter))]

@ -8,11 +8,15 @@ namespace BTCPayServer.Client.Models
public class CreatePullPaymentRequest
{
public string Name { get; set; }
public string Description { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string Currency { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan? Period { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Days))]
[JsonProperty("BOLT11Expiration")]
public TimeSpan? BOLT11Expiration { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? ExpiresAt { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]

@ -0,0 +1,33 @@
namespace BTCPayServer.Client.Models;
public class EmailSettingsData
{
public string Server
{
get; set;
}
public int? Port
{
get; set;
}
public string Login
{
get; set;
}
public string Password
{
get; set;
}
public string FromDisplay
{
get; set;
}
public string From
{
get; set;
}
}

@ -1,4 +1,4 @@
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.Client.JsonConverters;
using NBitcoin;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@ -8,7 +8,7 @@ namespace BTCPayServer.Client
public class GenerateOnChainWalletRequest
{
public int AccountNumber { get; set; } = 0;
[JsonConverter(typeof(MnemonicJsonConverter))]
[JsonConverter(typeof(MnemonicJsonConverter))]
public Mnemonic ExistingMnemonic { get; set; }
[JsonConverter(typeof(WordlistJsonConverter))]
public NBitcoin.Wordlist WordList { get; set; }

@ -1,4 +1,4 @@
namespace BTCPayServer.Client.Models
namespace BTCPayServer.Client.Models
{
public class GenericPaymentMethodData
{

@ -0,0 +1,17 @@
using System;
namespace BTCPayServer.Client.Models
{
public class GreenfieldPermissionAPIError : GreenfieldAPIError
{
public GreenfieldPermissionAPIError(string missingPermission, string message = null) : base()
{
MissingPermission = missingPermission;
Code = "missing-permission";
Message = message ?? $"Insufficient API Permissions. Please use an API key with permission \"{MissingPermission}\". You can create an API key in your account's settings / Api Keys.";
}
public string MissingPermission { get; }
}
}

@ -9,4 +9,4 @@ namespace BTCPayServer.Client.Models
Invalid,
PaidOver
}
}
}

@ -3,6 +3,7 @@ using System.Collections.Generic;
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.Models
{
@ -34,6 +35,7 @@ namespace BTCPayServer.Client.Models
public string PaymentMethod { get; set; }
public string CryptoCode { get; set; }
public JObject AdditionalData { get; set; }
public class Payment
{
@ -52,7 +54,7 @@ namespace BTCPayServer.Client.Models
public PaymentStatus Status { get; set; }
public string Destination { get; set; }
public enum PaymentStatus
{
Invalid,

@ -1,4 +1,4 @@
namespace BTCPayServer.Client.Models
namespace BTCPayServer.Client.Models
{
public class LNURLPayPaymentMethodBaseData
{
@ -8,7 +8,7 @@
public LNURLPayPaymentMethodBaseData()
{
}
}
}

@ -1,6 +1,6 @@
namespace BTCPayServer.Client.Models
namespace BTCPayServer.Client.Models
{
public class LNURLPayPaymentMethodData: LNURLPayPaymentMethodBaseData
public class LNURLPayPaymentMethodData : LNURLPayPaymentMethodBaseData
{
/// <summary>
/// Whether the payment method is enabled
@ -16,7 +16,7 @@
{
}
public LNURLPayPaymentMethodData(string cryptoCode, bool enabled, bool useBech32Scheme, bool enableForStandardInvoices)
public LNURLPayPaymentMethodData(string cryptoCode, bool enabled, bool useBech32Scheme, bool enableForStandardInvoices)
{
Enabled = enabled;
CryptoCode = cryptoCode;

@ -11,4 +11,4 @@ namespace BTCPayServer.Client.Models
[JsonExtensionData] public Dictionary<string, JToken> AdditionalData { get; set; }
}
}
}

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

@ -1,6 +1,6 @@
namespace BTCPayServer.Client.Models
{
public class LightningNetworkPaymentMethodData: LightningNetworkPaymentMethodBaseData
public class LightningNetworkPaymentMethodData : LightningNetworkPaymentMethodBaseData
{
/// <summary>
/// Whether the payment method is enabled

@ -0,0 +1,32 @@
using System;
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.Lightning;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
namespace BTCPayServer.Client.Models
{
public class LightningPaymentData
{
public string Id { get; set; }
public string PaymentHash { get; set; }
[JsonConverter(typeof(StringEnumConverter))]
public LightningPaymentStatus Status { get; set; }
[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; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney FeeAmount { get; set; }
}
}

@ -1,4 +1,4 @@
using NBitcoin;
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
@ -19,6 +19,6 @@ namespace BTCPayServer.Client.Models
{
}
}
}

@ -11,7 +11,7 @@ namespace BTCPayServer.Client.Models
public OnChainPaymentMethodDataPreview()
{
}
public OnChainPaymentMethodDataPreview(string cryptoCode, string derivationScheme, string label, RootedKeyPath accountKeyPath)
@ -34,7 +34,7 @@ namespace BTCPayServer.Client.Models
public OnChainPaymentMethodData()
{
}
public OnChainPaymentMethodData(string cryptoCode, string derivationScheme, bool enabled, string label, RootedKeyPath accountKeyPath, string paymentMethod) :

@ -1,4 +1,4 @@
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.Client.JsonConverters;
using NBitcoin;
using Newtonsoft.Json;

@ -21,9 +21,9 @@ namespace BTCPayServer.Client.Models
[JsonConverter(typeof(UInt256JsonConverter))]
public uint256 BlockHash { get; set; }
public int? BlockHeight { get; set; }
public long? BlockHeight { get; set; }
public int Confirmations { get; set; }
public long Confirmations { get; set; }
[JsonConverter(typeof(DateTimeToUnixTimeConverter))]
public DateTimeOffset Timestamp { get; set; }

@ -21,6 +21,6 @@ namespace BTCPayServer.Client.Models
[JsonConverter(typeof(KeyPathJsonConverter))]
public KeyPath KeyPath { get; set; }
public string Address { get; set; }
public int Confirmations { get; set; }
public long Confirmations { get; set; }
}
}

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

@ -1,8 +1,20 @@
#nullable enable
using BTCPayServer.Client.JsonConverters;
using BTCPayServer.JsonConverters;
using NBitcoin;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public class PayLightningInvoiceRequest
{
[Newtonsoft.Json.JsonProperty("BOLT11")]
[JsonProperty("BOLT11")]
public string BOLT11 { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public float? MaxFeePercent { get; set; }
[JsonConverter(typeof(MoneyJsonConverter))]
public Money? MaxFeeFlat { get; set; }
}
}

@ -8,10 +8,12 @@ namespace BTCPayServer.Client.Models
{
public class PaymentRequestBaseData
{
public string StoreId { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public string Currency { get; set; }
public DateTime? ExpiryDate { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? ExpiryDate { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public string Email { get; set; }

@ -8,7 +8,8 @@ namespace BTCPayServer.Client.Models
{
[JsonConverter(typeof(StringEnumConverter))]
public PaymentRequestData.PaymentRequestStatus Status { get; set; }
public DateTimeOffset Created { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset CreatedTime { get; set; }
public string Id { get; set; }
public bool Archived { get; set; }

@ -5,6 +5,13 @@ using Newtonsoft.Json;
namespace BTCPayServer.Client.Models
{
public enum PullPaymentState
{
Active,
Expired,
Archived,
Future
}
public class PullPaymentData
{
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
@ -13,11 +20,15 @@ namespace BTCPayServer.Client.Models
public DateTimeOffset? ExpiresAt { get; set; }
public string Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string Currency { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan? Period { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Days))]
[JsonProperty("BOLT11Expiration")]
public TimeSpan BOLT11Expiration { get; set; }
public bool Archived { get; set; }
public string ViewLink { get; set; }
}

@ -0,0 +1,10 @@
namespace BTCPayServer.Client.Models
{
public class SendEmailRequest
{
public string Email;
public string Subject;
public string Body;
}
}

@ -29,14 +29,14 @@ namespace BTCPayServer.Client.Models
/// </summary>
public IEnumerable<SyncStatus> SyncStatus { get; set; }
}
public class SyncStatus
{
public string CryptoCode { get; set; }
public virtual bool Available { get; set; }
}
public class ServerInfoSyncStatusData: SyncStatus
public class ServerInfoSyncStatusData : SyncStatus
{
public int ChainHeight { get; set; }
public int? SyncHeight { get; set; }

@ -41,9 +41,9 @@ namespace BTCPayServer.Client.Models
public bool ShowRecommendedFee { get; set; } = true;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public int RecommendedFeeBlockTarget { get; set; } = 1;
public string DefaultPaymentMethod { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string DefaultLang { get; set; } = "en";

@ -7,4 +7,14 @@ namespace BTCPayServer.Client.Models
/// </summary>
public string Id { get; set; }
}
public class StoreUserData
{
/// <summary>
/// the id of the user
/// </summary>
public string UserId { get; set; }
public string Role { get; set; }
}
}

@ -6,4 +6,4 @@ namespace BTCPayServer.Client.Models
Confirmed,
Replaced
}
}
}

@ -1,6 +1,6 @@
namespace BTCPayServer.Client.Models
{
public class UpdateLightningNetworkPaymentMethodRequest: LightningNetworkPaymentMethodBaseData
public class UpdateLightningNetworkPaymentMethodRequest : LightningNetworkPaymentMethodBaseData
{
/// <summary>
/// Whether the payment method is enabled

@ -11,7 +11,7 @@ namespace BTCPayServer.Client.Models
public UpdateOnChainPaymentMethodRequest()
{
}
public UpdateOnChainPaymentMethodRequest(bool enabled, string derivationScheme, string label, RootedKeyPath accountKeyPath)

@ -24,6 +24,7 @@ namespace BTCPayServer.Client
public const string CanViewProfile = "btcpay.user.canviewprofile";
public const string CanManageNotificationsForUser = "btcpay.user.canmanagenotificationsforuser";
public const string CanViewNotificationsForUser = "btcpay.user.canviewnotificationsforuser";
public const string CanViewUsers = "btcpay.server.canviewusers";
public const string CanCreateUser = "btcpay.server.cancreateuser";
public const string CanDeleteUser = "btcpay.user.candeleteuser";
public const string CanManagePullPayments = "btcpay.store.canmanagepullpayments";
@ -43,6 +44,7 @@ namespace BTCPayServer.Client
yield return CanModifyPaymentRequests;
yield return CanModifyProfile;
yield return CanViewProfile;
yield return CanViewUsers;
yield return CanCreateUser;
yield return CanDeleteUser;
yield return CanManageNotificationsForUser;
@ -175,7 +177,9 @@ namespace BTCPayServer.Client
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:

@ -11,7 +11,7 @@ namespace BTCPayServer
Add(new BTCPayNetwork()
{
CryptoCode = nbxplorerNetwork.CryptoCode,
DisplayName = "Althash",
DisplayName = "Htmlcoin",
BlockExplorerLink = NetworkType == ChainName.Mainnet ? "https://explorer.htmlcoin.com/api/tx/{0}" : "https://explorer.htmlcoin.com/api/tx/{0}",
NBXplorerNetwork = nbxplorerNetwork,
DefaultRateRules = new[]
@ -21,7 +21,7 @@ namespace BTCPayServer
},
CryptoImagePath = "imlegacy/althash.png",
DefaultSettings = BTCPayDefaultSettings.GetDefaultSettings(NetworkType),
CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("88'") : new KeyPath("1'")
CoinType = NetworkType == ChainName.Mainnet ? new KeyPath("172'") : new KeyPath("1'")
});
}
}

@ -1,78 +0,0 @@
#if ALTCOINS
using NBitcoin;
namespace BTCPayServer
{
public partial class BTCPayNetworkProvider
{
public void InitEthereum()
{
Add(new EthereumBTCPayNetwork()
{
CryptoCode = "ETH",
DisplayName = "Ethereum",
DefaultRateRules = new[] {"ETH_X = ETH_BTC * BTC_X", "ETH_BTC = kraken(ETH_BTC)"},
BlockExplorerLink =
NetworkType == ChainName.Mainnet
? "https://etherscan.io/address/{0}"
: "https://ropsten.etherscan.io/address/{0}",
CryptoImagePath = "/imlegacy/eth.png",
ShowSyncSummary = true,
CoinType = NetworkType == ChainName.Mainnet? 60 : 1,
ChainId = NetworkType == ChainName.Mainnet ? 1 : 3,
Divisibility = 18,
});
}
public void InitERC20()
{
if (NetworkType != ChainName.Mainnet)
{
Add(new ERC20BTCPayNetwork()
{
CryptoCode = "FAU",
DisplayName = "Faucet Token",
DefaultRateRules = new[]
{
"FAU_X = FAU_BTC * BTC_X",
"FAU_BTC = 0.01",
},
BlockExplorerLink = "https://ropsten.etherscan.io/address/{0}#tokentxns",
ShowSyncSummary = false,
CoinType = 1,
ChainId = 3,
//use https://erc20faucet.com for testnet
SmartContractAddress = "0xFab46E002BbF0b4509813474841E0716E6730136",
Divisibility = 18,
CryptoImagePath = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR42mNkYAAAAAYAAjCB0C8AAAAASUVORK5CYII=",
});
}
else
{
Add(new ERC20BTCPayNetwork()
{
CryptoCode = "USDT20",
DisplayName = "Tether USD (ERC20)",
DefaultRateRules = new[]
{
"USDT20_UST = 1",
"USDT20_X = USDT20_BTC * BTC_X",
"USDT20_BTC = bitfinex(UST_BTC)",
},
BlockExplorerLink =
NetworkType == ChainName.Mainnet
? "https://etherscan.io/address/{0}#tokentxns"
: "https://ropsten.etherscan.io/address/{0}#tokentxns",
CryptoImagePath = "/imlegacy/liquid-tether.svg",
ShowSyncSummary = false,
CoinType = NetworkType == ChainName.Mainnet? 60 : 1,
ChainId = NetworkType == ChainName.Mainnet ? 1 : 3,
SmartContractAddress = "0xdAC17F958D2ee523a2206206994597C13D831ec7",
Divisibility = 6
});
}
}
}
}
#endif

@ -1,20 +0,0 @@
#if ALTCOINS
namespace BTCPayServer
{
public class EthereumBTCPayNetwork : BTCPayNetworkBase
{
public int ChainId { get; set; }
public int CoinType { get; set; }
public string GetDefaultKeyPath()
{
return $"m/44'/{CoinType}'/0'/0/x";
}
}
public class ERC20BTCPayNetwork : EthereumBTCPayNetwork
{
public string SmartContractAddress { get; set; }
}
}
#endif

@ -1,20 +0,0 @@
#if ALTCOINS
using System.Collections.Generic;
using System.Linq;
namespace BTCPayServer
{
public static class EthereumExtensions
{
public static IEnumerable<string> GetAllEthereumSubChains(this BTCPayNetworkProvider networkProvider, BTCPayNetworkProvider unfiltered)
{
var ethBased = networkProvider.GetAll().OfType<EthereumBTCPayNetwork>();
var chainId = ethBased.Select(network => network.ChainId).Distinct();
return unfiltered.GetAll().OfType<EthereumBTCPayNetwork>()
.Where(network => chainId.Contains(network.ChainId))
.Select(network => network.CryptoCode.ToUpperInvariant());
}
}
}
#endif

@ -0,0 +1,29 @@
using NBitcoin;
namespace BTCPayServer
{
public partial class BTCPayNetworkProvider
{
// Change this if you want another zcash coin
public void InitZcash()
{
Add(new ZcashLikeSpecificBtcPayNetwork()
{
CryptoCode = "ZEC",
DisplayName = "Zcash",
Divisibility = 8,
BlockExplorerLink =
NetworkType == ChainName.Mainnet
? "https://www.exploreZcash.com/transaction/{0}"
: "https://testnet.xmrchain.net/tx/{0}",
DefaultRateRules = new[]
{
"ZEC_X = ZEC_BTC * BTC_X",
"ZEC_BTC = kraken(ZEC_BTC)"
},
CryptoImagePath = "/imlegacy/zcash.png",
UriScheme = "zcash"
});
}
}
}

@ -0,0 +1,102 @@
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC
{
public class JsonRpcClient
{
private readonly Uri _address;
private readonly string _username;
private readonly string _password;
private readonly HttpClient _httpClient;
public JsonRpcClient(Uri address, string username, string password, HttpClient client = null)
{
_address = address;
_username = username;
_password = password;
_httpClient = client ?? new HttpClient();
}
public async Task<TResponse> SendCommandAsync<TRequest, TResponse>(string method, TRequest data,
CancellationToken cts = default(CancellationToken))
{
var jsonSerializer = new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
};
var httpRequest = new HttpRequestMessage()
{
Method = HttpMethod.Post,
RequestUri = new Uri(_address, method),
Content = new StringContent(
JsonConvert.SerializeObject(data, jsonSerializer),
Encoding.UTF8, "application/json")
};
// httpRequest.Headers.Accept.Clear();
// httpRequest.Headers.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
// httpRequest.Headers.Authorization = new AuthenticationHeaderValue("Basic",
// Convert.ToBase64String(Encoding.Default.GetBytes($"{_username}:{_password}")));
var rawResult = await _httpClient.SendAsync(httpRequest, cts);
var rawJson = await rawResult.Content.ReadAsStringAsync();
rawResult.EnsureSuccessStatusCode();
var response = JsonConvert.DeserializeObject<TResponse>(rawJson, jsonSerializer);
return response;
}
public class NoRequestModel
{
public static NoRequestModel Instance = new NoRequestModel();
}
internal class JsonRpcApiException : Exception
{
public JsonRpcResultError Error { get; set; }
public override string Message => Error?.Message;
}
public class JsonRpcResultError
{
[JsonProperty("code")] public int Code { get; set; }
[JsonProperty("message")] public string Message { get; set; }
[JsonProperty("data")] dynamic Data { get; set; }
}
internal class JsonRpcResult<T>
{
[JsonProperty("result")] public T Result { get; set; }
[JsonProperty("error")] public JsonRpcResultError Error { get; set; }
[JsonProperty("id")] public string Id { get; set; }
}
internal class JsonRpcCommand<T>
{
[JsonProperty("jsonRpc")] public string JsonRpc { get; set; } = "2.0";
[JsonProperty("id")] public string Id { get; set; } = Guid.NewGuid().ToString();
[JsonProperty("method")] public string Method { get; set; }
[JsonProperty("params")] public T Parameters { get; set; }
public JsonRpcCommand()
{
}
public JsonRpcCommand(string method, T parameters)
{
Method = method;
Parameters = parameters;
}
}
}
}

@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class CreateAccountRequest
{
[JsonProperty("label")] public string Label { get; set; }
}
}

@ -0,0 +1,10 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class CreateAccountResponse
{
[JsonProperty("account_index")] public long AccountIndex { get; set; }
[JsonProperty("address")] public string Address { get; set; }
}
}

@ -0,0 +1,10 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class CreateAddressRequest
{
[JsonProperty("account_index")] public long AccountIndex { get; set; }
[JsonProperty("label")] public string Label { get; set; }
}
}

@ -0,0 +1,10 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class CreateAddressResponse
{
[JsonProperty("address")] public string Address { get; set; }
[JsonProperty("address_index")] public long AddressIndex { get; set; }
}
}

@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class GetAccountsRequest
{
[JsonProperty("tag")] public string Tag { get; set; }
}
}

@ -0,0 +1,14 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class GetAccountsResponse
{
[JsonProperty("subaddress_accounts")] public List<SubaddressAccount> SubaddressAccounts { get; set; }
[JsonProperty("total_balance")] public decimal TotalBalance { get; set; }
[JsonProperty("total_unlocked_balance")]
public decimal TotalUnlockedBalance { get; set; }
}
}

@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public class GetFeeEstimateRequest
{
[JsonProperty("grace_blocks")] public int? GraceBlocks { get; set; }
}
}

@ -0,0 +1,11 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public class GetFeeEstimateResponse
{
[JsonProperty("fee")] public long Fee { get; set; }
[JsonProperty("status")] public string Status { get; set; }
[JsonProperty("untrusted")] public bool Untrusted { get; set; }
}
}

@ -0,0 +1,9 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class GetHeightResponse
{
[JsonProperty("height")] public long Height { get; set; }
}
}

@ -0,0 +1,11 @@
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public class GetTransferByTransactionIdRequest
{
[JsonProperty("txid")] public string TransactionId { get; set; }
[JsonProperty("account_index")] public long AccountIndex { get; set; }
}
}

@ -0,0 +1,31 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class GetTransferByTransactionIdResponse
{
[JsonProperty("transfer")] public TransferItem Transfer { get; set; }
[JsonProperty("transfers")] public IEnumerable<TransferItem> Transfers { get; set; }
public partial class TransferItem
{
[JsonProperty("address")] public string Address { get; set; }
[JsonProperty("amount")] public long Amount { get; set; }
[JsonProperty("confirmations")] public long Confirmations { get; set; }
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
[JsonProperty("height")] public long Height { get; set; }
[JsonProperty("note")] public string Note { get; set; }
[JsonProperty("payment_id")] public string PaymentId { get; set; }
[JsonProperty("subaddr_index")] public SubaddrIndex SubaddrIndex { get; set; }
[JsonProperty("suggested_confirmations_threshold")]
public long SuggestedConfirmationsThreshold { get; set; }
[JsonProperty("timestamp")] public long Timestamp { get; set; }
[JsonProperty("txid")] public string Txid { get; set; }
[JsonProperty("type")] public string Type { get; set; }
[JsonProperty("unlock_time")] public long UnlockTime { get; set; }
}
}
}

@ -0,0 +1,19 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class GetTransfersRequest
{
[JsonProperty("in")] public bool In { get; set; }
[JsonProperty("out")] public bool Out { get; set; }
[JsonProperty("pending")] public bool Pending { get; set; }
[JsonProperty("failed")] public bool Failed { get; set; }
[JsonProperty("pool")] public bool Pool { get; set; }
[JsonProperty("filter_by_height ")] public bool FilterByHeight { get; set; }
[JsonProperty("min_height")] public long MinHeight { get; set; }
[JsonProperty("max_height")] public long MaxHeight { get; set; }
[JsonProperty("account_index")] public long AccountIndex { get; set; }
[JsonProperty("subaddr_indices")] public List<long> SubaddrIndices { get; set; }
}
}

@ -0,0 +1,35 @@
using System.Collections.Generic;
using Newtonsoft.Json;
namespace BTCPayServer.Services.Altcoins.Zcash.RPC.Models
{
public partial class GetTransfersResponse
{
[JsonProperty("in")] public List<GetTransfersResponseItem> In { get; set; }
[JsonProperty("out")] public List<GetTransfersResponseItem> Out { get; set; }
[JsonProperty("pending")] public List<GetTransfersResponseItem> Pending { get; set; }
[JsonProperty("failed")] public List<GetTransfersResponseItem> Failed { get; set; }
[JsonProperty("pool")] public List<GetTransfersResponseItem> Pool { get; set; }
public partial class GetTransfersResponseItem
{
[JsonProperty("address")] public string Address { get; set; }
[JsonProperty("amount")] public long Amount { get; set; }
[JsonProperty("confirmations")] public long Confirmations { get; set; }
[JsonProperty("double_spend_seen")] public bool DoubleSpendSeen { get; set; }
[JsonProperty("height")] public long Height { get; set; }
[JsonProperty("note")] public string Note { get; set; }
[JsonProperty("payment_id")] public string PaymentId { get; set; }
[JsonProperty("subaddr_index")] public SubaddrIndex SubaddrIndex { get; set; }
[JsonProperty("suggested_confirmations_threshold")]
public long SuggestedConfirmationsThreshold { get; set; }
[JsonProperty("timestamp")] public long Timestamp { get; set; }
[JsonProperty("txid")] public string Txid { get; set; }
[JsonProperty("type")] public string Type { get; set; }
[JsonProperty("unlock_time")] public long UnlockTime { get; set; }
}
}
}

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