Compare commits

..

304 Commits

Author SHA1 Message Date
Dennis Reimann
3c7751ae80 Move plugins to separate repos 2022-12-05 11:26:47 +01:00
Dennis Reimann
6d9bbb50d6 Merge branch 'master' into plugins 2022-12-05 09:26:26 +01:00
Dennis Reimann
508002503e Merge branch 'master' into plugins 2022-12-04 12:50:38 +01:00
Dennis Reimann
031bb7b224 Merge branch 'master' into plugins 2022-11-27 15:31:39 +01:00
Dennis Reimann
2d6827dd19 Merge branch 'master' into plugins 2022-11-14 19:05:13 +01:00
Dennis Reimann
5e00bc43d5 Merge branch 'master' into plugins 2022-11-05 12:22:46 +01:00
Dennis Reimann
db8a2930a4 Merge branch 'master' into plugins 2022-11-02 13:44:33 +01:00
Dennis Reimann
7325610ac5 Merge branch 'master' into plugins 2022-10-27 09:17:17 +02:00
Dennis Reimann
36b064b50f Merge branch 'master' into plugins 2022-10-24 17:40:38 +02:00
Dennis Reimann
7ecf6504d0 LNbank: IMprove exception handling 2022-10-08 19:51:39 +02:00
Dennis Reimann
7c971df109 PodServer v0.1.4 2022-10-08 18:14:54 +02:00
Dennis Reimann
c7f6784364 Update changelogs 2022-10-08 18:12:21 +02:00
Dennis Reimann
b816c4462e Merge branch 'master' into plugins 2022-10-08 18:07:35 +02:00
Dennis Reimann
ca750f4152 LNbank: Date display improvements 2022-10-05 11:34:37 +02:00
Dennis Reimann
6be968f7bf PodServer: Fix publish date in feed
Fixes btcpayserver/btcpayserver-plugins#57.
2022-10-05 11:34:37 +02:00
Dennis Reimann
89cd1079fe Merge branch 'master' into plugins 2022-10-04 18:48:07 +02:00
Dennis Reimann
fa5470c587 LNbank v1.3.4 2022-09-30 22:47:40 +02:00
Dennis Reimann
820421fcbc PodServer v0.1.3 2022-09-30 22:44:40 +02:00
Dennis Reimann
a4ab2dcd84 Merge branch 'lnurl-flow' into plugins 2022-09-30 22:43:06 +02:00
Dennis Reimann
d14f4f8173 PodServer: Fix podcast lookup on public pages
Fixes btcpayserver/btcpayserver-plugins#53.
2022-09-30 22:42:14 +02:00
Dennis Reimann
386c18b897 Minor Send and Receive view improvements 2022-09-30 18:09:07 +02:00
Dennis Reimann
5d98fe7b34 LNbank: Improve LNURL payment flow 2022-09-30 18:04:23 +02:00
Dennis Reimann
2008d15dda LNbank: Improve invoice canceling and invalidating 2022-09-29 22:10:45 +02:00
Dennis Reimann
d206a88e3a PodServer v0.1.2 2022-09-29 18:55:40 +02:00
Dennis Reimann
bbce88f269 PodServer: Fix permissions
Fixes btcpayserver/btcpayserver-plugins#49.
2022-09-29 18:54:40 +02:00
Dennis Reimann
edbfafcaf2 PodServer v0.1.1 2022-09-29 18:07:49 +02:00
Dennis Reimann
b64ddab08b LNbank: Invalidate unresolved payments 2022-09-29 16:11:29 +02:00
Dennis Reimann
c34b4d64e5 Use LND as default LN node; bind to 0.0.0.0 2022-09-29 14:44:03 +02:00
Dennis Reimann
90308ce6b9 LNbank v1.3.3 2022-09-29 14:37:22 +02:00
Dennis Reimann
a3b702c360 Merge branch 'master' into plugins 2022-09-29 14:32:26 +02:00
Dennis Reimann
4f9820ae1b Update bug report template 2022-09-29 14:29:43 +02:00
Dennis Reimann
6884db431f LNbank: Fix setting LNbank wallet in WebKit-based browsers
Fixes btcpayserver/btcpayserver-plugins#44.
2022-09-29 14:29:22 +02:00
Dennis Reimann
349dbdc85d LNbank: Refactor Lightning invoice watcher 2022-09-29 13:53:38 +02:00
Dennis Reimann
dc795311fa PodServer: Fix public podcast page without episodes
Fixes btcpayserver/btcpayserver-plugins#46.
2022-09-29 13:29:11 +02:00
Dennis Reimann
7ff2f58f34 LNbank: Break long words in description text 2022-09-29 13:28:37 +02:00
Dennis Reimann
c736babd40 LNbank: Fix send error in LNDhub API 2022-09-29 13:28:13 +02:00
Dennis Reimann
b5174dcbcd PodServer: Fix public podcast page without episodes
Fixes btcpayserver/btcpayserver#4176.
2022-09-28 14:25:29 +02:00
Dennis Reimann
ffe40daaa6 Merge branch 'master' into plugins 2022-09-28 14:08:36 +02:00
Dennis Reimann
43649026c1 LNbank v1.3.2 2022-09-27 17:38:01 +02:00
Dennis Reimann
84212de830 Update docs 2022-09-27 17:35:54 +02:00
Dennis Reimann
d958ef2ec7 LNbank: Update changelog 2022-09-27 15:53:55 +02:00
Dennis Reimann
b60dcb6927 LNbank: Add invoices API for Lightning client 2022-09-27 15:53:29 +02:00
Dennis Reimann
9af32e7089 LNbank: Upgrade LNDhub integration
Fixes btcpayserver/btcpayserver#4168.
2022-09-27 15:53:29 +02:00
Dennis Reimann
7b10067ce5 Remove unused icon sprites 2022-09-27 14:17:14 +02:00
Dennis Reimann
7746e5beef LNbank v1.3.1 2022-09-26 20:00:59 +02:00
Dennis Reimann
38fd1d338b LNbank: Update changelog 2022-09-26 19:58:42 +02:00
Dennis Reimann
b0e4186733 LNbank: Fix LNURL metadata
Fixes btcpayserver/btcpayserver#4165.
2022-09-26 19:56:39 +02:00
Dennis Reimann
c6c0a7b6ac LNbank: Potential migration fix
Might fix dennisreimann/btcpayserver#22.
2022-09-26 19:50:40 +02:00
Dennis Reimann
f2e35529e9 PodServer v0.1.0 2022-09-26 17:46:38 +02:00
Dennis Reimann
1deddbcf14 PodServer: Update changelog and release script 2022-09-26 17:42:47 +02:00
Dennis Reimann
c14f26340e LNbank v1.3.0 2022-09-26 17:37:04 +02:00
Dennis Reimann
ab5497eb3d LNbank: Update changelog 2022-09-26 17:29:32 +02:00
Dennis Reimann
1b1fdd4360 LNbank: Add custom invoice expiry 2022-09-26 17:29:21 +02:00
Dennis Reimann
fbc4dde974 LNbank: Expire invoices explicitely 2022-09-26 16:50:47 +02:00
Dennis Reimann
4d1f8c1d16 LNbank: Update LightningInvoiceWatcher logging and error handling 2022-09-26 16:28:06 +02:00
Dennis Reimann
524ad8393d Bump BTCPay version requirements 2022-09-26 16:00:40 +02:00
Dennis Reimann
0def52416d Merge branch 'master' into plugins 2022-09-26 15:57:19 +02:00
Dennis Reimann
375405ba51 Merge branch 'master' into plugins 2022-09-26 10:38:22 +02:00
Dennis Reimann
9ce1ba0019 Merge branch 'master' into plugins 2022-09-20 13:36:20 +02:00
Dennis Reimann
ff6043cf67 PodServer: Refactoring: Services and repos 2022-09-20 13:35:58 +02:00
Dennis Reimann
e6e3efb709 Merge branch 'master' into plugins 2022-09-20 13:03:56 +02:00
Dennis Reimann
ec029fa5cd PodServer: Add editors and policies 2022-09-19 15:59:58 +02:00
Dennis Reimann
5f9926896a Merge branch 'master' into plugins 2022-09-16 11:57:28 +02:00
Dennis Reimann
e68cb1805f Merge branch 'master' into plugins 2022-09-13 20:37:16 +02:00
Dennis Reimann
f554478254 PodServer: Feed updates 2022-09-13 20:35:29 +02:00
Dennis Reimann
45a8852799 PodServer: View updates 2022-09-13 20:35:14 +02:00
Dennis Reimann
92dae8dff6 PodServer: Import updates 2022-09-13 20:34:52 +02:00
Dennis Reimann
beb58cb90b PodServer: Minor view updates 2022-09-13 16:04:47 +02:00
Dennis Reimann
f379593a2f PodServer: Various contribution-related updates 2022-09-12 18:05:00 +02:00
Dennis Reimann
15ddf9d619 Merge branch 'master' into plugins 2022-09-12 14:57:17 +02:00
Dennis Reimann
82b479cc7c Merge branch 'lnbank-lndhub' into plugins 2022-09-09 12:57:47 +02:00
Dennis Reimann
ba2db52859 Updates for Zeus compatibility
See https://github.com/ZeusLN/zeus/tree/master/stores
2022-09-09 12:36:46 +02:00
Dennis Reimann
8f5af29f23 Updates for Alby compatibility
See https://github.com/getAlby/lightning-browser-extension/blob/master/src/extension/background-script/connectors/lndhub.ts
2022-09-09 12:36:46 +02:00
Dennis Reimann
7b5049099c Use models from LNDhub library 2022-09-09 12:36:46 +02:00
Dennis Reimann
5d37f31d72 LNbank: Add LNDhub compatibility
Closes #4.
2022-09-09 12:36:46 +02:00
Dennis Reimann
05aac2801c Merge branch 'master' into plugins 2022-09-09 12:36:24 +02:00
Dennis Reimann
160a19f6c7 PodServer: Update public pages 2022-09-08 17:32:04 +02:00
Dennis Reimann
afedb48eeb Merge branch 'master' into plugins 2022-08-31 19:15:57 +02:00
Dennis Reimann
25716c8ab7 Merge branch 'master' into plugins 2022-08-29 18:05:45 +02:00
Dennis Reimann
61c9466374 PodServer: Various updates 2022-08-26 19:48:09 +02:00
Dennis Reimann
4b3d7fd004 PodServer: Contribution basics 2022-08-26 17:01:09 +02:00
Dennis Reimann
e8657da952 PodServer: Update image upload UI 2022-08-25 20:02:38 +02:00
Dennis Reimann
b4e3c8f0b5 Merge branch 'master' into plugins 2022-08-25 19:28:21 +02:00
Dennis Reimann
405def199f PodServer: Feed updates 2022-08-23 18:19:40 +02:00
Dennis Reimann
ea9fe8386d PodServer: Public pages updates 2022-08-22 17:38:18 +02:00
Dennis Reimann
5dd8b3701f Merge branch 'master' into plugins 2022-08-22 12:09:19 +02:00
Dennis Reimann
e6b4b83bc0 Merge branch 'master' into plugins 2022-08-19 19:17:21 +02:00
Dennis Reimann
253cfda4b4 PodServer: Add value recipient form 2022-08-19 19:17:05 +02:00
Dennis Reimann
f03063e390 PodServer: Add slug to podcast and episode 2022-08-19 17:41:43 +02:00
Dennis Reimann
5e295bab89 PodServer: Various updates 2022-08-18 17:25:32 +02:00
Dennis Reimann
92cf26dc3b LNbank: Minor style updates 2022-08-18 12:03:25 +02:00
Dennis Reimann
a3ed557244 PodServer: Add README 2022-08-17 10:18:19 +02:00
Dennis Reimann
475f16b280 LNbank: Fix typos in README 2022-08-17 10:18:09 +02:00
Dennis Reimann
b3b54ccaf7 Merge branch 'master' into plugins 2022-08-17 09:41:58 +02:00
Dennis Reimann
07cba914bb LNbank: Add README with some documentation 2022-08-16 22:10:20 +02:00
Dennis Reimann
7e569c044f LNbank: Update access keys; add test 2022-08-16 13:21:43 +02:00
Dennis Reimann
7bb32e3fdf LNbank: Update LNURL controller 2022-08-15 19:25:45 +02:00
Dennis Reimann
8aea701f6c Merge branch 'lnbank-lnurl' into plugins 2022-08-15 13:31:28 +02:00
Dennis Reimann
177628d05b LNbank: Handle payment API errors 2022-08-15 13:31:17 +02:00
Dennis Reimann
fe644bb979 LNbank: Send to LNURL 2022-08-15 10:10:28 +02:00
Dennis Reimann
70168f73ce Merge branch 'master' into plugins 2022-08-15 10:10:18 +02:00
Dennis Reimann
5a27155984 Merge branch 'master' into plugins 2022-08-10 17:26:12 +02:00
Dennis Reimann
b38c05f33f Merge branch 'master' into plugins 2022-08-09 22:59:07 +02:00
Dennis Reimann
2ff1c80661 Merge branch 'master' into plugins 2022-08-08 17:07:04 +02:00
Dennis Reimann
6f7bce216c LNbank: Custom policies refactoring 2022-08-02 17:57:57 +02:00
Dennis Reimann
f7981b2b12 Merge branch 'master' into plugins 2022-08-02 12:29:22 +02:00
Dennis Reimann
2b81ea5040 LNbank: Add custom authorization policies 2022-08-02 09:32:34 +02:00
Dennis Reimann
733dc7561a Merge branch 'master' into plugins 2022-08-02 09:08:37 +02:00
Dennis Reimann
c323ef51fa LNbank: Owner stays admin, even without access key 2022-07-22 12:30:50 +02:00
Dennis Reimann
4d97de8208 Merge branch 'master' into plugins 2022-07-22 12:19:04 +02:00
Dennis Reimann
dd99fec838 LNbank: AccessKeys refactoring 2022-07-17 22:36:58 +02:00
Dennis Reimann
539352f598 Merge branch 'master' into plugins 2022-07-15 09:40:43 +02:00
Dennis Reimann
a63288fce8 LNbank: Split WalletService and WalletRepository 2022-07-14 18:23:04 +02:00
Dennis Reimann
0f57c09aff LNbank: Manage access keys for wallet access 2022-07-13 20:35:52 +02:00
Dennis Reimann
15068c1398 Move ConfirmModel to Abstractions
To make it available to plugins.
2022-07-12 14:44:07 +02:00
Dennis Reimann
6ef4822ad2 LNbank: Update on model creating calls 2022-07-11 12:34:55 +02:00
Dennis Reimann
f2f3e472b0 LNbank: Extend access keys; add migration runner 2022-07-11 12:34:26 +02:00
Dennis Reimann
57e42df769 LNbank v1.2.3 2022-07-08 16:12:13 +02:00
Dennis Reimann
0918c79305 Update release scripts 2022-07-08 16:10:49 +02:00
Dennis Reimann
ef0f61dafa LNbank: Update BTCPay version requirement 2022-07-08 16:02:49 +02:00
Dennis Reimann
4e1c841615 LNbank: Watcher should not invalidate on null 2022-07-08 16:02:09 +02:00
Dennis Reimann
713e0bf5e5 Merge branch 'master' into plugins 2022-07-08 16:00:25 +02:00
Dennis Reimann
aa6f41bace Improve send error handling 2022-07-07 15:55:31 +02:00
Dennis Reimann
d44c06320e Merge branch 'master' into plugins 2022-07-06 16:39:02 +02:00
Dennis Reimann
0d2603dd5a Merge branch 'master' into plugins 2022-07-06 13:12:48 +02:00
Dennis Reimann
c87a4511cd LNbank: Send improvements 2022-07-04 19:00:59 +02:00
Dennis Reimann
3b61be1b82 Merge branch 'master' into plugins 2022-07-04 16:37:34 +02:00
Dennis Reimann
28d05edd96 Merge branch 'master' into plugins 2022-06-28 10:45:01 +02:00
Dennis Reimann
21d159d5f9 Merge branch 'master' into plugins 2022-06-21 12:05:14 +02:00
Dennis Reimann
d2d02e18e7 LNbank: Add API endpoint for balance check 2022-06-20 18:06:29 +02:00
Dennis Reimann
47208db8db Merge branch 'master' into plugins 2022-06-20 07:06:26 +02:00
Dennis Reimann
ea6ad0995f LNbank: Update BTCPay version requirement 2022-06-16 15:06:24 +02:00
Dennis Reimann
0c1b474c35 Merge branch 'master' into plugins 2022-06-16 15:05:16 +02:00
Dennis Reimann
0e90f1219c Merge branch 'master' into plugins 2022-06-07 12:58:17 +02:00
Dennis Reimann
abb21c68cb Merge branch 'master' into plugins 2022-06-02 17:27:33 +02:00
Dennis Reimann
9c1404c261 LNbank: Update logging 2022-05-31 15:18:09 +02:00
Dennis Reimann
ceb722c71f LNbank: Validate invoice expiry 2022-05-31 13:39:51 +02:00
Dennis Reimann
d863dfa0c8 Greenfield: Fix GetDepositAddress return type
The local clients GetFromActionResult cannot handle the JValue return type, because it gets invoked with GetFromActionResult<string>.
2022-05-31 10:58:29 +02:00
Dennis Reimann
0cc849be91 LNbank: Map explicit LightningInvoiceStatuses 2022-05-31 10:27:48 +02:00
Dennis Reimann
110524391b LNbank: Allow creation of zero amount invoices 2022-05-31 10:27:38 +02:00
Dennis Reimann
d452c1e578 LNbank: Improve API responses 2022-05-31 10:27:25 +02:00
Dennis Reimann
86fead2809 Update release scripts 2022-05-30 13:31:56 +02:00
Dennis Reimann
6c80ca1d18 Merge branch 'master' into plugins 2022-05-30 12:55:03 +02:00
Dennis Reimann
aa742b3079 LNbank v1.2.2 2022-05-30 11:28:12 +02:00
Dennis Reimann
01eb93bc43 Merge branch 'master' into plugins 2022-05-30 09:01:17 +02:00
Dennis Reimann
e6d29afed6 LNbank: Update changelog and version requirement 2022-05-30 09:00:21 +02:00
Dennis Reimann
3f88ea1e15 LNbank: Improve API response 2022-05-26 22:04:44 +02:00
Dennis Reimann
409b6df8a2 Merge branch 'master' into plugins 2022-05-25 14:03:48 +02:00
Dennis Reimann
8304afd36c LNbank: Fix routing fee accessor 2022-05-25 13:50:10 +02:00
Dennis Reimann
56400dcc27 Merge branch 'master' into plugins 2022-05-25 13:46:18 +02:00
Dennis Reimann
d59ab2ef01 Merge branch 'master' into plugins 2022-05-24 15:45:39 +02:00
Dennis Reimann
458f8979fb Merge branch 'master' into plugins 2022-05-19 17:04:42 +02:00
Dennis Reimann
ca7b306dea LNbank: Update changelog 2022-05-19 16:33:57 +02:00
Dennis Reimann
f509b937fd LNbank: Improve test 2022-05-19 16:33:41 +02:00
Dennis Reimann
19c75f51bd LNbank: Distinguish original invoice amount and actual amount settled 2022-05-19 16:04:18 +02:00
Dennis Reimann
ca821a643e LNbank: Update hold invoice handling 2022-05-19 15:59:00 +02:00
Dennis Reimann
d8d3172b17 LNbank: Zero amount invoice handling fixes 2022-05-19 14:48:37 +02:00
Dennis Reimann
14ce5dd41f LNbank: Use info log instead of debug in invoice watcher 2022-05-19 11:59:27 +02:00
Dennis Reimann
505b1d8310 Update project settings 2022-05-19 11:49:18 +02:00
Dennis Reimann
c60a95a6fe Merge branch 'master' into plugins 2022-05-18 15:49:52 +02:00
Dennis Reimann
63119c63f1 LNbank: Require BTCPay Server v1.5.3 2022-05-18 08:38:26 +02:00
Dennis Reimann
c5f4db4df6 Merge branch 'plugins-expl-amt' into plugins 2022-05-18 08:21:09 +02:00
Dennis Reimann
77932f6e20 LNbank: Allow explicit amount for zero amount invoices
Fixes btcpayserver/btcpayserver-plugins#23
2022-05-18 08:20:49 +02:00
Dennis Reimann
2d67e0e75c Merge branch 'master' into plugins 2022-05-18 08:12:00 +02:00
Dennis Reimann
db8b7a4621 PodServer: Public pages 2022-05-12 09:18:01 +02:00
Dennis Reimann
a6ac322246 LNbank: Public wallet LNURL page for sharing 2022-05-11 16:47:39 +02:00
Dennis Reimann
8b5ea9fd56 Merge branch 'master' into plugins 2022-05-11 14:15:13 +02:00
Dennis Reimann
d9aa8f7dbc Merge branch 'master' into plugins 2022-05-04 14:57:23 +02:00
Dennis Reimann
5341b4eb08 LNbank v1.2.1 2022-04-30 20:52:51 +02:00
Dennis Reimann
935577de71 LNbank: Update changelog 2022-04-30 20:51:13 +02:00
Dennis Reimann
3d15ff31f5 LNbank: Fix test 2022-04-30 20:48:33 +02:00
Dennis Reimann
e68942056d LNbank: More hold invoice updates 2022-04-30 20:27:54 +02:00
Dennis Reimann
eff872148c LNbank: Nullify properties when cancelling transactions 2022-04-30 20:27:38 +02:00
Dennis Reimann
3692602b15 LNbank: Trim payment requests 2022-04-30 20:26:44 +02:00
Dennis Reimann
3de38298b6 LNbank: Autofocus input fields 2022-04-30 20:06:26 +02:00
Dennis Reimann
eb7d8694f5 Merge branch 'master' into plugins 2022-04-30 19:00:50 +02:00
Dennis Reimann
8e53b3c9f0 Merge branch 'master' into plugins 2022-04-29 16:05:49 +02:00
Dennis Reimann
6a714e6d9c LNbank: Hold invoice handling improvements 2022-04-28 22:13:17 +02:00
Dennis Reimann
f227b9aec5 Merge branch 'master' into plugins 2022-04-28 22:13:03 +02:00
Dennis Reimann
a741ad446c LNbank: Refresh transactions list on update 2022-04-27 12:57:14 +02:00
Dennis Reimann
e4d45798f1 PodServer: View Refactoring 2022-04-27 12:56:55 +02:00
Dennis Reimann
e5b4f2a399 Merge branch 'master' into plugins 2022-04-26 21:00:03 +02:00
Dennis Reimann
55fb4ec233 LNbank: Handle hold invoices 2022-04-26 20:58:56 +02:00
Dennis Reimann
c5b4b1b9e6 Merge branch 'plugins-hodlinvoice' into plugins 2022-04-26 14:25:13 +02:00
Dennis Reimann
ad6effa3bb PodServer: Introduce Editor 2022-04-26 14:24:05 +02:00
Dennis Reimann
c5e48eb975 Add and pass cancellation tokens 2022-04-26 11:04:59 +02:00
Dennis Reimann
675bb63d14 Set PodServer version 2022-04-26 11:04:35 +02:00
Dennis Reimann
5c64a4ac40 Use Safe.Json to output values 2022-04-26 11:03:37 +02:00
Dennis Reimann
0adb2cf233 Merge branch 'master' into plugins 2022-04-26 06:59:22 +02:00
Dennis Reimann
316ed2a9bb PodServer: Add medium 2022-04-25 17:38:12 +02:00
Dennis Reimann
cea2a3f513 PodServer: Add player basics 2022-04-25 17:13:31 +02:00
Dennis Reimann
5d01e07e2d Separate plugin views strictly 2022-04-25 16:53:54 +02:00
Dennis Reimann
ee0547448e Merge branch 'master' into plugins 2022-04-25 10:44:11 +02:00
Dennis Reimann
08580eb244 Update changelog 2022-04-22 17:08:05 +02:00
Dennis Reimann
e127478c2e Handle cancelled invoices in watcher 2022-04-22 17:04:29 +02:00
Dennis Reimann
9b7bd57cb1 Merge branch 'master' into plugins 2022-04-22 14:08:33 +02:00
Dennis Reimann
f771b6dd70 LNbank: Add methods to get payment info 2022-04-21 10:24:45 +02:00
Dennis Reimann
f4ed031f99 Allow for empty description when creating invoices 2022-04-20 22:12:06 +02:00
Dennis Reimann
b7d8077467 LNbank: Log send and receive exceptions 2022-04-20 22:04:58 +02:00
Dennis Reimann
8197375845 Merge branch 'master' into plugins 2022-04-20 08:38:29 +02:00
Dennis Reimann
74a3c6739c PodServer: UI updates 2022-04-19 17:34:04 +02:00
Dennis Reimann
392023219b Merge branch 'master' into plugins 2022-04-19 15:21:21 +02:00
Dennis Reimann
97420dfd3e Add Buchhalter plugin basics 2022-04-16 21:53:10 +02:00
Dennis Reimann
30d1bcfa4d Merge branch 'master' into plugins 2022-04-15 20:20:34 +02:00
Dennis Reimann
36b5a13d1c Merge branch 'master' into plugins 2022-04-08 14:39:47 +02:00
Dennis Reimann
0dadac914e LNbank v1.2.0 2022-03-31 20:46:47 +02:00
Dennis Reimann
3a76bebcbc Prepare v1.2.0 2022-03-31 20:45:04 +02:00
Dennis Reimann
53f46d4b8d Simplify Swagger provider 2022-03-31 20:44:38 +02:00
Dennis Reimann
5911b998b5 Export for accounting
Closes #2.
2022-03-31 20:41:06 +02:00
Dennis Reimann
45885c5137 Display LNURL on Receive page 2022-03-31 17:34:30 +02:00
Dennis Reimann
1b5a7ed1e1 Use existing AddFile method 2022-03-31 14:19:47 +02:00
Dennis Reimann
9be0810fb7 Merge branch 'master' into plugins 2022-03-31 14:17:17 +02:00
Dennis Reimann
a3efae4cc5 Add LNbank Greenfield API docs 2022-03-31 09:36:50 +02:00
Dennis Reimann
2141eafa37 Importer 2022-03-30 18:28:37 +02:00
Dennis Reimann
b403f6f1e8 Merge branch 'master' into plugins 2022-03-30 11:27:45 +02:00
Dennis Reimann
0055746be6 Import service 2022-03-24 17:44:29 +01:00
Dennis Reimann
2885335780 Form updates 2022-03-21 21:16:54 +01:00
Dennis Reimann
d1524a5e5d Add import jobs 2022-03-21 21:02:23 +01:00
Dennis Reimann
775101a31f Merge branch 'master' into plugins 2022-03-21 14:02:00 +01:00
Dennis Reimann
48a0ed7b98 Update wallets list 2022-03-19 07:46:20 +01:00
Dennis Reimann
7843b6173c Update plugin navigations 2022-03-19 07:45:59 +01:00
Dennis Reimann
4446d506e9 Update LNbank nav icon 2022-03-18 20:16:15 +01:00
Dennis Reimann
7b824d5ec0 LNbank: Support LNURL Pay for wallets
Closes dennisreimann/btcpayserver#5.
2022-03-18 17:00:36 +01:00
Dennis Reimann
967c91f711 Merge branch 'master' into plugins 2022-03-18 15:41:52 +01:00
Dennis Reimann
f7271f6ffb Merge branch 'podserver' into plugins 2022-03-18 15:41:28 +01:00
Dennis Reimann
0b83d2b859 Add feed importer 2022-03-18 15:41:06 +01:00
Dennis Reimann
fc4a7a26fe Add people and seasons management 2022-03-18 12:56:18 +01:00
Dennis Reimann
f6e3ca32fb Improve syntax in wallet model 2022-03-17 14:48:13 +01:00
Dennis Reimann
0a3b4f5d61 Add enclosures 2022-03-14 22:57:39 +01:00
Dennis Reimann
60d8dd81a4 Add richtext editor tofor episode description 2022-03-14 15:05:08 +01:00
Dennis Reimann
0e2a7b5efd LNbank: API for accessing, updating and deleting wallets 2022-03-14 13:46:26 +01:00
Dennis Reimann
a664937526 Merge branch 'master' into plugins 2022-03-14 10:22:10 +01:00
Dennis Reimann
00354de289 Merge branch 'master' into plugins 2022-03-11 10:23:16 +01:00
Dennis Reimann
c70f58fd70 LNbank v1.1.1 2022-03-09 15:52:49 +01:00
Dennis Reimann
21c08acfd5 Update changelog and release script 2022-03-09 15:51:57 +01:00
Dennis Reimann
f38432e15e Handle paid but unsettled payments 2022-03-09 15:44:53 +01:00
Dennis Reimann
58309dd7aa Fix redirects
Fixes btcpayserver/btcpayserver-plugins#15
2022-03-09 15:44:53 +01:00
Dennis Reimann
59017e77eb Update Lightning test settings 2022-03-09 13:15:53 +01:00
Dennis Reimann
be323ba147 Merge branch 'master' into plugins 2022-03-08 13:30:06 +01:00
Dennis Reimann
f3350bcdbf Merge branch 'master' into plugins 2022-03-08 09:28:02 +01:00
Dennis Reimann
79df9a027a Remove old wallet deletion code 2022-03-07 18:13:46 +01:00
Dennis Reimann
3fe981d6f5 Handle errors when checking pending transactions 2022-03-07 18:13:12 +01:00
Dennis Reimann
80265b56b8 API updates 2022-03-07 10:58:56 +01:00
Dennis Reimann
90ce5acf99 Fix transaction hub IDs 2022-03-04 08:43:12 +01:00
Dennis Reimann
eef2780e70 Fix redirect path after creating an invoice 2022-03-03 17:40:15 +01:00
Dennis Reimann
cedb04cc42 Use store invoice expiry time 2022-03-03 17:39:23 +01:00
Dennis Reimann
1fd8f48bda PodServer: File upload 2022-03-03 15:17:36 +01:00
Dennis Reimann
4f63ca4af4 Refactoring: Extract extensions
Refactoring: Extract HttpRequest extensions

Refactoring: Extract ITempDataDictionary extensions


Fixes


Try test fix
2022-03-03 15:17:36 +01:00
Dennis Reimann
6d72d7f6de Update issue template 2022-03-02 15:44:19 +01:00
Dennis Reimann
78e4cb868d Merge branch 'master' into plugins 2022-03-02 12:44:08 +01:00
Dennis Reimann
560117fe59 Merge branch 'master' into plugins 2022-03-01 18:32:27 +01:00
Dennis Reimann
ee0e199add LNbank wording and message updates 2022-02-28 18:32:07 +01:00
Dennis Reimann
fb48b9fa52 PodServer UI basics 2022-02-28 18:31:50 +01:00
Dennis Reimann
c888a845ab Clean up project files 2022-02-25 11:56:15 +01:00
Dennis Reimann
c3e43cb5b3 Move PodServer and add data model 2022-02-25 11:44:53 +01:00
Dennis Reimann
9a855deca4 Add LNbank API for creating wallets
Closes dennisreimann/btcpayserver#1
2022-02-24 09:02:00 +01:00
Dennis Reimann
41bdbd784d Refactoring: Allow GreenfieldExtensions to be used by plugins 2022-02-24 09:00:44 +01:00
Dennis Reimann
e2e87652e1 Soft delete wallets 2022-02-23 18:35:51 +01:00
Dennis Reimann
c29b1be070 Add PodServer basics 2022-02-21 23:03:57 +01:00
Dennis Reimann
82fc59cc76 LNbank refactorings 2022-02-21 23:03:38 +01:00
Dennis Reimann
1f1f2ca819 Improve release script 2022-02-21 18:49:59 +01:00
Dennis Reimann
d43119e4ac Prepare release 2022-02-21 18:41:03 +01:00
Dennis Reimann
2b4c3e68b1 Prevent deletion of wallet with balance; refactor messages.
Closes dennisreimann/btcpayserver#8
2022-02-21 18:15:34 +01:00
Dennis Reimann
a35e8fa69a Merge branch 'master' into plugins 2022-02-21 16:41:11 +01:00
Dennis Reimann
e855441455 Common wallet header 2022-02-21 16:32:15 +01:00
Dennis Reimann
62f426fea8 Cleanups 2022-02-21 14:20:34 +01:00
Dennis Reimann
094db3dab9 Remove transaction details page 2022-02-21 14:20:19 +01:00
Dennis Reimann
14770d7a6b Separate wallets list and wallet detail views 2022-02-21 13:12:33 +01:00
Dennis Reimann
ac0722246b Merge branch 'master' into plugins 2022-02-21 10:32:44 +01:00
Dennis Reimann
14785278ec Improve E2E test 2022-02-18 21:59:24 +01:00
Dennis Reimann
359247542e Proper redirects on homepage 2022-02-18 21:04:06 +01:00
Dennis Reimann
e028f5d0c1 Toggle for attaching description to pay request when receiving 2022-02-18 20:44:13 +01:00
Dennis Reimann
66c90ae5f7 Customize description when sending 2022-02-18 20:07:24 +01:00
Dennis Reimann
72c876b62b Lightning payment info and fee handling 2022-02-18 19:46:53 +01:00
Dennis Reimann
89204f2256 Merge branch 'master' into plugins 2022-02-18 12:23:43 +01:00
Dennis Reimann
0580e5bf9b Add helper for sats values 2022-02-15 13:21:44 +01:00
Dennis Reimann
6bfcb02a8c Merge branch 'master' into plugins 2022-02-14 18:22:50 +01:00
Dennis Reimann
b9d73415a4 Prevent paying requests multiple times 2022-02-11 15:36:00 +01:00
Dennis Reimann
beaac40222 Improve wallet headings and title 2022-02-11 10:13:19 +01:00
Dennis Reimann
17bd4a3d9c Allow for empty description
Closes btcpayserver/btcpayserver-plugins#10
2022-02-11 10:11:59 +01:00
Dennis Reimann
ce61a07111 Update CHANGELOG and release script 2022-02-10 16:19:51 +01:00
Dennis Reimann
cadd197dd9 LNbank v1.0.4 2022-02-10 15:54:50 +01:00
Dennis Reimann
f97275ae16 Add CHANGELOG and update release script 2022-02-10 15:51:05 +01:00
Dennis Reimann
6845c511c6 Merge branch 'master' into lnbank 2022-02-10 12:26:41 +01:00
Dennis Reimann
34c482a991 Lowercase page paths 2022-02-09 16:27:20 +01:00
Dennis Reimann
250762c758 UI updates
Remove button icons, improve wallet view
2022-02-09 16:20:26 +01:00
Dennis Reimann
06df50c5d0 Add support for private route hints
Will be enabled if the connected store has the required setting or if the toggle on the receive page is activated.

Closes btcpayserver/btcpayserver#3423
2022-02-09 16:08:44 +01:00
Dennis Reimann
240cb72d24 Improve Lightning test scripts 2022-02-09 15:24:17 +01:00
Dennis Reimann
22678d2b50 Share page fixes 2022-02-09 15:23:52 +01:00
Dennis Reimann
1f593d0710 Merge branch 'master' into lnbank 2022-02-07 11:21:38 +01:00
Dennis Reimann
ec41e806dd Add release script 2022-02-01 15:15:33 +01:00
Dennis Reimann
bac5ad4bbc LNbank v1.0.3 2022-02-01 12:47:05 +01:00
Dennis Reimann
28ae60faf3 Add Selenium test 2022-02-01 12:42:36 +01:00
Dennis Reimann
c9544b22d1 Improve form validation 2022-02-01 12:02:25 +01:00
Dennis Reimann
01d7ff2525 Omit userId when using the local API client
Otherwise non-admins cannot send and receive when using the internal node. Thanks @kukks.

Fixes btcpayserver/btcpayserver-plugins#6.
Fixes btcpayserver/btcpayserver-plugins#7.
Fixes btcpayserver/btcpayserver-plugins#8.
2022-02-01 10:15:53 +01:00
Dennis Reimann
4f67a443c5 Improve create wallet for LN node connection case 2022-01-31 13:51:57 +01:00
Dennis Reimann
1f333058c9 Merge branch 'master' into lnbank 2022-01-31 12:10:15 +01:00
Dennis Reimann
6ef90503df Merge branch 'master' into lnbank 2022-01-27 15:57:12 +01:00
Dennis Reimann
cece43a921 LNbank v1.0.2 2022-01-27 11:01:46 +01:00
Dennis Reimann
8aae72f63e Improve layout 2022-01-27 10:47:14 +01:00
Dennis Reimann
d3df78e71b Update headlines 2022-01-27 09:58:50 +01:00
Dennis Reimann
4f6bd1a523 Remove connection string display 2022-01-27 09:34:00 +01:00
Dennis Reimann
4b2d70e3fa Add policy (and store context); use file-scoped namespaces 2022-01-27 09:31:14 +01:00
Dennis Reimann
ab729b0f7c LNbank v1.0.1
Integrate existing LNbank app


Fix db column types

Refactor copy to clipboard

General updates


Set plugin category active

More updates


Remove custom QR controller, reuse BTCPay one


Make transaction hub work


Cleanup WalletService


Configure network properly


Hide connection string info for now


Show first wallet by default


Add LNbank icon sprite


Fix payment request code styles


Remove BOLT11 string and fix QR code display


Upgrade SignalR client


Allow unauthenticated connection to hub (for share page)


Re-add initial API version


Remove custom authorization

Leftover from standalone app

add packer script

Support descriptionhash for lnurl

Refactor Auth

fix conn string display

add cancel invoice endpoint

deep integration

Improve date/time display


UI improvements


Improve LN setup integration


Add bash version of pack script


Add plugin description


Declare BTCPayServer version dependency


Updates for new layout


Update project info


Update active page function


Fix log warning


Upgrade LNbank to net6.0
2022-01-27 08:48:57 +01:00
805 changed files with 10916 additions and 24526 deletions

View File

@@ -11,14 +11,10 @@ insert_final_newline = true
indent_style = space
indent_size = 4
charset = utf-8
space_before_self_closing = true
[*.json]
indent_size = 2
[swagger*.json]
indent_size = 4
# C# files
[*.cs]
# New line preferences
@@ -71,7 +67,7 @@ dotnet_naming_symbols.private_internal_fields.applicable_kinds = field
dotnet_naming_symbols.private_internal_fields.applicable_accessibilities = private, internal
dotnet_naming_style.camel_case_underscore_style.required_prefix = _
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
dotnet_naming_style.camel_case_underscore_style.capitalization = camel_case
# Code style defaults
dotnet_sort_system_directives_first = true

58
.github/ISSUE_TEMPLATE/bug-report.md vendored Normal file
View File

@@ -0,0 +1,58 @@
---
name: "\U0001F41B Bug report"
about: Report a bug or a technical issue
---
<!--
Thank you for reporting a technical issue with one of my BTCPay Server plugins, like LNbank or PodServer.
For general issues with BTCPay Server please visit https://github.com/btcpayserver/btcpayserver/issues
General support is available on our community chat chat.btcpayserver.org
Please fill in as much of the template below as you're able.
-->
**Plugin**
Name and version of the plugin. <!--[available on the Server Settings > Plugins page] -->
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce the bug**
Steps to reproduce the reported bug:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
<!--
A clear and concise description of what you expected to happen.
-->
**Screenshots**
<!--
If applicable, add screenshots to help explain your problem.
-->
**Your BTCPay Environment (please complete the following information):**
- BTCPay Server Version: <!--[available in the right bottom corner of footer] -->
- Lightning implementation <!--[e.g. LND, Core Lightning] -->
- Deployment Method: <!--[e.g. Docker, Manual, Third-Party-host]-->
- Browser: <!--[e.g. Chrome, Safari]-->
**Logs (if applicable)**
<!--
If you are using the Docker setup, please post the output of the following command:
docker logs generated_btcpayserver_1
Otherwise, basic logs can be found in Server Settings > Logs.
More logs https://docs.btcpayserver.org/Troubleshooting/#2-looking-through-the-logs
-->

View File

@@ -1,68 +0,0 @@
name: 🐛 Bug Report
description: File a bug report
title: "[Bug]: "
labels: ["bug"]
body:
- type: markdown
attributes:
value: |
Thanks for taking the time to fill out this bug report! Please provide as much information as you can. It helps us better understand the problem and fix it faster.
- type: textarea
id: version
attributes:
label: What is your BTCPay version?
description: You can see the version in the footer's bottom right corner
placeholder: I'm running BTCPay v1.X.X.X
validations:
required: true
- type: textarea
id: deployment
attributes:
label: How did you deploy BTCPay Server?
description: Docker, manual, third-party host? Read more on deployment methods [here](https://docs.btcpayserver.org/Deployment/)
placeholder: I'm running BTCPay Server on a...
validations:
required: true
- type: textarea
id: what-happened
attributes:
label: What happened?
description: A clear and concise description of what the bug is.
placeholder: Tell us what you see!
validations:
required: true
- type: textarea
id: reproduce
attributes:
label: How did you encounter this bug?
description: Step by step describe how did you encounter the bug?
placeholder: 1. I clicked X 2. Then I clicked Y 3. See error
validations:
required: true
- type: textarea
id: logoutput
attributes:
label: Relevant log output
description: Please copy and paste any relevant log output. This will be automatically formatted into code, so no need for backticks. Logs can be found in Server Settings > Logs. Here's how you can [troubleshoot an issue](https://docs.btcpayserver.org/Troubleshooting/)
render: shell
- type: textarea
id: browser
attributes:
label: What browser do you use?
description: Provide your browser and it's version. If you replicated issues on multiple browsers, let us know which ones.
placeholder: For example Safari 15.00, Chrome 10.0, Tor, Edge, etc
validations:
required: false
- type: textarea
id: additonal
attributes:
label: Additional information
description: Feel free to provide additional information. Screenshots are always helpful.
- type: checkboxes
id: terms
attributes:
label: Are you sure this is a bug report?
description: By submitting this report, you agree that this is not a support or a feature request. For general questions please read our [documentation](https://docs.btcpayserver.org). You can ask questions in [discussions](https://github.com/btcpayserver/btcpayserver/discussions) and [on our community chat](https://chat.btcpayserver.org)
options:
- label: I confirm this is a bug report
required: true

View File

@@ -1,14 +1,8 @@
blank_issues_enabled: true
contact_links:
- name: 💡 Request a feature
url: https://github.com/btcpayserver/btcpayserver/discussions/categories/ideas-feature-requests
about: Submit a feature request or vote on ideas posted by others. Features with most upvotes become roadmap candidates
- name: 🧑‍💻 Ask a technical question
url: https://github.com/btcpayserver/btcpayserver/discussions/new?category=technical-support
about: If you're experiencing a technical problem post it to our community support forum
- name: 🔌 Report a problem with a plugin
url: https://github.com/btcpayserver/btcpayserver/discussions/new?category=plugins-integrations
about: Experiencing a problem with a third-party plugin? Post it here and we will tag their developers to assist
- name: 🚀 Discussions
url: https://github.com/btcpayserver/btcpayserver/discussions
about: Technical discussions, questions and feature requests
- name: 📝 Official Documentation
url: https://docs.btcpayserver.org
about: Check our documentation for answers to common questions

1
.gitignore vendored
View File

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

6
.gitmodules vendored Normal file
View File

@@ -0,0 +1,6 @@
[submodule "LNbank"]
path = Plugins/BTCPayServer.Plugins.LNbank
url = git@github.com:dennisreimann/btcpayserver-plugin-lnbank.git
[submodule "PodServer"]
path = Plugins/BTCPayServer.Plugins.PodServer
url = git@github.com:dennisreimann/btcpayserver-plugin-podserver.git

View File

@@ -0,0 +1,21 @@
<component name="ProjectRunConfigurationManager">
<configuration default="false" name="Pack Test Plugin" type="DotNetProject" factoryName=".NET Project" singleton="false">
<option name="EXE_PATH" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/bin/Debug/netcoreapp3.1/BTCPayServer.PluginPacker.dll" />
<option name="PROGRAM_PARAMETERS" value="../../../../BTCPayServer.Plugins.Test\bin\Debug\netcoreapp3.1 BTCPayServer.Plugins.Test &quot;../../../../Packed Plugins&quot;" />
<option name="WORKING_DIRECTORY" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/bin/Debug/netcoreapp3.1" />
<option name="PASS_PARENT_ENVS" value="1" />
<option name="USE_EXTERNAL_CONSOLE" value="0" />
<option name="USE_MONO" value="0" />
<option name="RUNTIME_ARGUMENTS" value="" />
<option name="PROJECT_PATH" value="$PROJECT_DIR$/BTCPayServer.PluginPacker/BTCPayServer.PluginPacker.csproj" />
<option name="PROJECT_EXE_PATH_TRACKING" value="1" />
<option name="PROJECT_ARGUMENTS_TRACKING" value="1" />
<option name="PROJECT_WORKING_DIRECTORY_TRACKING" value="1" />
<option name="PROJECT_KIND" value="DotNetCore" />
<option name="PROJECT_TFM" value=".NETCoreApp,Version=v3.1" />
<method v="2">
<option name="Build" default="false" projectName="BTCPayServer.Plugins.Test" projectPath="C:\Git\btcpayserver\BTCPayServer.Plugins.Test\BTCPayServer.Plugins.Test.csproj" />
<option name="Build" />
</method>
</configuration>
</component>

View File

@@ -1,5 +1,3 @@
using System.IO;
namespace BTCPayServer.Configuration
{
public class DataDirectories
@@ -9,12 +7,5 @@ namespace BTCPayServer.Configuration
public string TempStorageDir { get; set; }
public string StorageDir { get; set; }
public string TempDir { get; set; }
public string ToDatadirFullPath(string path)
{
if (Path.IsPathRooted(path))
return path;
return Path.Combine(DataDir, path);
}
}
}

View File

@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
using System;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Http;

View File

@@ -19,8 +19,6 @@ namespace BTCPayServer.Abstractions.Contracts
public class NotificationViewModel
{
public string Id { get; set; }
public string Identifier { get; set; }
public string Type { get; set; }
public DateTimeOffset Created { get; set; }
public string Body { get; set; }
public string ActionLink { get; set; }

View File

@@ -1,4 +1,4 @@
#nullable enable
#nullable enable
namespace BTCPayServer.Abstractions.Contracts;
public interface IScopeProvider

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace BTCPayServer.Abstractions.Contracts;

View File

@@ -1,4 +1,4 @@
using System.Collections.Generic;
using System.Collections.Generic;
using System.Threading.Tasks;
using NBitcoin;

View File

@@ -9,7 +9,7 @@ public class AssetQuoteResult
public AssetQuoteResult() { }
public AssetQuoteResult(string fromAsset, string toAsset, decimal bid, decimal ask)
public AssetQuoteResult(string fromAsset, string toAsset,decimal bid, decimal ask)
{
FromAsset = fromAsset;
ToAsset = toAsset;

View File

@@ -2,11 +2,10 @@ namespace BTCPayServer.Abstractions.Custodians;
public class AssetBalancesUnavailableException : CustodianApiException
{
public AssetBalancesUnavailableException(System.Exception e) : base(500, "asset-balances-unavailable", $"Cannot fetch the asset balances: {e.Message}", e)
{
}
public AssetBalancesUnavailableException(string errorMsg) : base(500, "asset-balances-unavailable", $"Cannot fetch the asset balances: {errorMsg}")
{
}
}

View File

@@ -1,7 +1,6 @@
using System;
namespace BTCPayServer.Abstractions.Custodians;
public class CustodianApiException : Exception
{
public class CustodianApiException: Exception {
public int HttpStatus { get; }
public string Code { get; }
@@ -10,8 +9,7 @@ public class CustodianApiException : Exception
HttpStatus = httpStatus;
Code = code;
}
public CustodianApiException(int httpStatus, string code, string message) : this(httpStatus, code, message, null)
public CustodianApiException( int httpStatus, string code, string message) : this(httpStatus, code, message, null)
{
}
}

View File

@@ -1,8 +1,9 @@
namespace BTCPayServer.Abstractions.Custodians;
public class CustodianFeatureNotImplementedException : CustodianApiException
public class CustodianFeatureNotImplementedException: CustodianApiException
{
public CustodianFeatureNotImplementedException(string message) : base(400, "not-implemented", message)
{
}
}

View File

@@ -1,8 +1,9 @@
namespace BTCPayServer.Abstractions.Custodians;
public class InsufficientFundsException : CustodianApiException
{
{
public InsufficientFundsException(string message) : base(400, "insufficient-funds", message)
{
}
}

View File

@@ -4,7 +4,7 @@ public class TradeNotFoundException : CustodianApiException
{
private string tradeId { get; }
public TradeNotFoundException(string tradeId) : base(404, "trade-not-found", "Could not find trade ID " + tradeId)
public TradeNotFoundException(string tradeId) : base(404,"trade-not-found","Could not find trade ID " + tradeId)
{
this.tradeId = tradeId;
}

View File

@@ -1,6 +1,6 @@
namespace BTCPayServer.Abstractions.Custodians;
public class WrongTradingPairException : CustodianApiException
public class WrongTradingPairException: CustodianApiException
{
public const int HttpCode = 404;
public WrongTradingPairException(string fromAsset, string toAsset) : base(HttpCode, "wrong-trading-pair", $"Cannot find a trading pair for converting {fromAsset} into {toAsset}.")

View File

@@ -1,28 +0,0 @@
using System.Collections.Generic;
using BTCPayServer.Client.Models;
using BTCPayServer.JsonConverters;
namespace BTCPayServer.Abstractions.Custodians.Client;
public class SimulateWithdrawalResult
{
public string PaymentMethod { get; }
public string Asset { get; }
public decimal MinQty { get; }
public decimal MaxQty { get; }
public List<LedgerEntryData> LedgerEntries { get; }
// Fee can be NULL if unknown.
public decimal? Fee { get; }
public SimulateWithdrawalResult(string paymentMethod, string asset, List<LedgerEntryData> ledgerEntries,
decimal minQty, decimal maxQty)
{
PaymentMethod = paymentMethod;
Asset = asset;
LedgerEntries = ledgerEntries;
MinQty = minQty;
MaxQty = maxQty;
}
}

View File

@@ -9,16 +9,18 @@ namespace BTCPayServer.Abstractions.Custodians;
public interface ICanTrade
{
/**
* A list of tradable asset pairs, or NULL if the custodian cannot trade/convert assets. if thr asset pair contains fiat, fiat is always put last. If both assets are a cyrptocode or both are fiat, the pair is written alphabetically. Always in uppercase. Example: ["BTC/EUR","BTC/USD", "EUR/USD", "BTC/ETH",...]
*/
public List<AssetPairData> GetTradableAssetPairs();
/**
* Execute a market order right now.
*/
public Task<MarketTradeResult> TradeMarketAsync(string fromAsset, string toAsset, decimal qty, JObject config, CancellationToken cancellationToken);
/**
* Get the details about a previous market trade.
*/

View File

@@ -5,14 +5,9 @@ using Newtonsoft.Json.Linq;
namespace BTCPayServer.Abstractions.Custodians;
/// <summary>
/// Interface for custodians that can move funds to the store wallet.
/// </summary>
public interface ICanWithdraw
{
public Task<WithdrawResult> WithdrawToStoreWalletAsync(string paymentMethod, decimal amount, JObject config, CancellationToken cancellationToken);
public Task<SimulateWithdrawalResult> SimulateWithdrawalAsync(string paymentMethod, decimal qty, JObject config, CancellationToken cancellationToken);
public Task<WithdrawResult> WithdrawAsync(string paymentMethod, decimal amount, JObject config, CancellationToken cancellationToken);
public Task<WithdrawResult> GetWithdrawalInfoAsync(string paymentMethod, string withdrawalId, JObject config, CancellationToken cancellationToken);

View File

@@ -1,4 +1,3 @@
#nullable enable
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@@ -13,7 +12,7 @@ public interface ICustodian
* Get the unique code that identifies this custodian.
*/
string Code { get; }
string Name { get; }
/**
@@ -21,6 +20,7 @@ public interface ICustodian
*/
Task<Dictionary<string, decimal>> GetAssetBalancesAsync(JObject config, CancellationToken cancellationToken);
public Task<Form.Form> GetConfigForm(JObject config, CancellationToken cancellationToken = default);
public Task<Form.Form> GetConfigForm(JObject config, string locale,
CancellationToken cancellationToken = default);
}

View File

@@ -7,10 +7,6 @@ namespace BTCPayServer.Abstractions.Extensions;
public static class GreenfieldExtensions
{
public static IActionResult UserNotFound(this ControllerBase ctrl)
{
return ctrl.CreateAPIError(404, "user-not-found", "The user was not found");
}
public static IActionResult CreateValidationError(this ControllerBase controller, ModelStateDictionary modelState)
{
return controller.UnprocessableEntity(modelState.ToGreenfieldValidationError());
@@ -34,12 +30,12 @@ public static class GreenfieldExtensions
{
return controller.BadRequest(new GreenfieldAPIError(errorCode, errorMessage));
}
public static IActionResult CreateAPIError(this ControllerBase controller, int httpCode, string errorCode, string errorMessage)
{
return controller.StatusCode(httpCode, new GreenfieldAPIError(errorCode, errorMessage));
}
public static IActionResult CreateAPIPermissionError(this ControllerBase controller, string missingPermission, string message = null)
{
return controller.StatusCode(403, new GreenfieldPermissionAPIError(missingPermission, message));

View File

@@ -11,7 +11,7 @@ public static class HttpRequestExtensions
return false;
return request.Host.Host.EndsWith(".onion", StringComparison.OrdinalIgnoreCase);
}
public static string GetAbsoluteRoot(this HttpRequest request)
{
return string.Concat(

View File

@@ -6,6 +6,7 @@ namespace BTCPayServer.Abstractions.Extensions;
public static class StringExtensions
{
public static bool IsValidFileName(this string fileName)
{
return !fileName.ToCharArray().Any(c => Path.GetInvalidFileNameChars().Contains(c)
@@ -40,4 +41,5 @@ public static class StringExtensions
return str.Substring(0, str.Length - 1);
return str;
}
}

View File

@@ -50,7 +50,7 @@ namespace BTCPayServer.Abstractions.Extensions
{
return IsActiveCategory(viewData, category.ToString(), id);
}
public static string IsActiveCategory(this ViewDataDictionary viewData, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_CATEGORY_KEY))
@@ -77,7 +77,7 @@ namespace BTCPayServer.Abstractions.Extensions
? ActivePageClass
: null;
}
public static string IsActivePage(this ViewDataDictionary viewData, string page, string category, object id = null)
{
if (!viewData.ContainsKey(ACTIVE_PAGE_KEY))
@@ -126,7 +126,7 @@ namespace BTCPayServer.Abstractions.Extensions
{
return $"{(int)timeSpan.TotalMinutes} minute{Plural((int)timeSpan.TotalMinutes)}";
}
return timeSpan.Days < 1
return timeSpan.Days < 1
? $"{(int)timeSpan.TotalHours} hour{Plural((int)timeSpan.TotalHours)}"
: $"{(int)timeSpan.TotalDays} day{Plural((int)timeSpan.TotalDays)}";
}

View File

@@ -17,16 +17,16 @@ public class AlertMessage
Danger,
Info
}
[JsonConverter(typeof(StringEnumConverter))]
public AlertMessageType Type;
// The translated message to be shown to the user
public string Message;
public AlertMessage()
{
}
public AlertMessage(AlertMessageType type, string message)

View File

@@ -12,12 +12,12 @@ public class Field
{
public static Field Create(string label, string name, string value, bool required, string helpText, string type = "text")
{
return new Field
return new Field()
{
Label = label,
Name = name,
Value = value,
OriginalValue = value,
OriginalValue = value,
Required = required,
HelpText = helpText,
Type = type
@@ -26,14 +26,14 @@ public class Field
// The name of the HTML5 node. Should be used as the key for the posted data.
public string Name;
public bool Constant;
public bool Hidden;
// HTML5 compatible type string like "text", "textarea", "email", "password", etc.
// HTML5 compatible type string like "text", "textarea", "email", "password", etc. Each type is a class and may contain more fields (i.e. "select" would have options).
public string Type;
public static Field CreateFieldset()
{
return new Field { Type = "fieldset" };
return new Field() { Type = "fieldset" };
}
// The value field is what is currently in the DB or what the user entered, but possibly not saved yet due to validation errors.
@@ -55,7 +55,7 @@ public class Field
public List<Field> Fields { get; set; } = new();
// The field is considered "valid" if there are no validation errors
public List<string> ValidationErrors = new();
public List<string> ValidationErrors = new List<string>();
public virtual bool IsValid()
{

View File

@@ -1,11 +1,9 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Primitives;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Newtonsoft.Json.Linq;
using Npgsql.Internal.TypeHandlers.GeometricHandlers;
namespace BTCPayServer.Abstractions.Form;
@@ -22,120 +20,137 @@ public class Form
return JObject.FromObject(this, CamelCaseSerializerSettings.Serializer).ToString(Newtonsoft.Json.Formatting.Indented);
}
#nullable restore
// Messages to be shown at the top of the form indicating user feedback like "Saved successfully" or "Please change X because of Y." or a warning, etc...
public List<AlertMessage> TopMessages { get; set; } = new();
// Groups of fields in the form
public List<Field> Fields { get; set; } = new();
// Are all the fields valid in the form?
public bool IsValid()
{
if (TopMessages?.Any(t => t.Type == AlertMessage.AlertMessageType.Danger) is true)
return false;
return Fields.Select(f => f.IsValid()).All(o => o);
}
public Field GetFieldByFullName(string fullName)
public Field GetFieldByName(string name)
{
foreach (var f in GetAllFields())
return GetFieldByName(name, Fields, null);
}
private static Field GetFieldByName(string name, List<Field> fields, string prefix)
{
prefix ??= string.Empty;
foreach (var field in fields)
{
if (f.FullName == fullName)
return f.Field;
var currentPrefix = prefix;
if (!string.IsNullOrEmpty(field.Name))
{
currentPrefix = $"{prefix}{field.Name}";
if (currentPrefix.Equals(name, StringComparison.InvariantCultureIgnoreCase))
{
return field;
}
currentPrefix += "_";
}
var subFieldResult = GetFieldByName(name, field.Fields, currentPrefix);
if (subFieldResult is not null)
{
return subFieldResult;
}
}
return null;
}
public IEnumerable<(string FullName, List<string> Path, Field Field)> GetAllFields()
public List<string> GetAllNames()
{
HashSet<string> nameReturned = new();
foreach (var f in GetAllFieldsCore(new List<string>(), Fields))
{
var fullName = string.Join('_', f.Path.Where(s => !string.IsNullOrEmpty(s)));
if (!nameReturned.Add(fullName))
continue;
yield return (fullName, f.Path, f.Field);
}
return GetAllNames(Fields);
}
public bool ValidateFieldNames(out List<string> errors)
{
errors = new List<string>();
HashSet<string> nameReturned = new();
foreach (var f in GetAllFieldsCore(new List<string>(), Fields))
{
var fullName = string.Join('_', f.Path.Where(s => !string.IsNullOrEmpty(s)));
if (!nameReturned.Add(fullName))
{
errors.Add($"Form contains duplicate field names '{fullName}'");
continue;
}
}
return errors.Count == 0;
}
IEnumerable<(List<string> Path, Field Field)> GetAllFieldsCore(List<string> path, List<Field> fields)
private static List<string> GetAllNames(List<Field> fields)
{
var names = new List<string>();
foreach (var field in fields)
{
List<string> thisPath = new(path.Count + 1);
thisPath.AddRange(path);
string prefix = string.Empty;
if (!string.IsNullOrEmpty(field.Name))
{
thisPath.Add(field.Name);
yield return (thisPath, field);
names.Add(field.Name);
prefix = $"{field.Name}_";
}
foreach (var child in field.Fields)
if (field.Fields.Any())
{
if (field.Constant)
child.Constant = true;
foreach (var descendant in GetAllFieldsCore(thisPath, field.Fields))
names.AddRange(GetAllNames(field.Fields).Select(s => $"{prefix}{s}" ));
}
}
return names;
}
public void ApplyValuesFromOtherForm(Form form)
{
foreach (var fieldset in Fields)
{
foreach (var field in fieldset.Fields)
{
field.Value = form
.GetFieldByName(
$"{(string.IsNullOrEmpty(fieldset.Name) ? string.Empty : fieldset.Name + "_")}{field.Name}")
?.Value;
}
}
}
public void ApplyValuesFromForm(IFormCollection form)
{
var names = GetAllNames();
foreach (var name in names)
{
var field = GetFieldByName(name);
if (field is null || !form.TryGetValue(name, out var val))
{
continue;
}
field.Value = val;
}
}
public Dictionary<string, object> GetValues()
{
return GetValues(Fields);
}
private static Dictionary<string, object> GetValues(List<Field> fields)
{
var result = new Dictionary<string, object>();
foreach (Field field in fields)
{
var name = field.Name ?? string.Empty;
if (field.Fields.Any())
{
var values = GetValues(fields);
values.Remove(string.Empty, out var keylessValue);
result.TryAdd(name, values);
if (keylessValue is not Dictionary<string, object> dict) continue;
foreach (KeyValuePair<string,object> keyValuePair in dict)
{
yield return descendant;
result.TryAdd(keyValuePair.Key, keyValuePair.Value);
}
}
}
}
public void ApplyValuesFromForm(IEnumerable<KeyValuePair<string, StringValues>> form)
{
var values = form.GroupBy(f => f.Key, f => f.Value).ToDictionary(g => g.Key, g => g.First());
foreach (var f in GetAllFields())
{
if (f.Field.Constant || !values.TryGetValue(f.FullName, out var val))
continue;
f.Field.Value = val;
}
}
public void SetValues(JObject values)
{
var fields = GetAllFields().ToDictionary(k => k.FullName, k => k.Field);
SetValues(fields, new List<string>(), values);
}
private void SetValues(Dictionary<string, Field> fields, List<string> path, JObject values)
{
foreach (var prop in values.Properties())
{
List<string> propPath = new List<string>(path.Count + 1);
propPath.AddRange(path);
propPath.Add(prop.Name);
if (prop.Value.Type == JTokenType.Object)
else
{
SetValues(fields, propPath, (JObject)prop.Value);
}
else if (prop.Value.Type == JTokenType.String)
{
var fullName = string.Join('_', propPath.Where(s => !string.IsNullOrEmpty(s)));
if (fields.TryGetValue(fullName, out var f) && !f.Constant)
f.Value = prop.Value.Value<string>();
result.TryAdd(name, field.Value);
}
}
return result;
}
}

View File

@@ -8,52 +8,18 @@ namespace BTCPayServer.Abstractions.Models
{
public abstract class BaseBTCPayServerPlugin : IBTCPayServerPlugin
{
public virtual string Identifier
{
get
{
return GetType().GetTypeInfo().Assembly.GetName().Name;
}
}
public virtual string Name
{
get
{
return GetType().GetTypeInfo().Assembly
.GetCustomAttribute<AssemblyProductAttribute>()?
.Product ?? "???";
}
}
public abstract string Identifier { get; }
public abstract string Name { get; }
public virtual Version Version
{
get
{
return GetVersion(GetType().GetTypeInfo().Assembly
.GetCustomAttribute<AssemblyInformationalVersionAttribute>()?
.InformationalVersion) ??
Assembly.GetAssembly(GetType())?.GetName()?.Version ??
new Version(1, 0, 0, 0);
return Assembly.GetAssembly(GetType())?.GetName().Version ?? new Version(1, 0, 0, 0);
}
}
private static Version GetVersion(string informationalVersion)
{
if (informationalVersion is null)
return null;
Version.TryParse(informationalVersion, out var r);
return r;
}
public virtual string Description
{
get
{
return GetType().GetTypeInfo().Assembly
.GetCustomAttribute<AssemblyDescriptionAttribute>()?
.Description ?? string.Empty;
}
}
public abstract string Description { get; }
public bool SystemPlugin { get; set; }
public virtual IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } = Array.Empty<IBTCPayServerPlugin.PluginDependency>();

View File

@@ -8,7 +8,7 @@ public class AuthorizationFilterHandle
public AuthorizationHandlerContext Context { get; }
public PolicyRequirement Requirement { get; }
public HttpContext HttpContext { get; }
public bool Success { get; private set; }
public bool Success { get; private set; }
public AuthorizationFilterHandle(
AuthorizationHandlerContext context,

View File

@@ -114,11 +114,6 @@ namespace BTCPayServer.Security
_Policies.Add(policy);
}
public void UnsafeEval()
{
Add("script-src", "'unsafe-eval'");
}
public IEnumerable<ConsentSecurityPolicy> Rules => _Policies;
public bool HasRules => _Policies.Count != 0;

View File

@@ -23,20 +23,11 @@ public class SVGUse : UrlResolutionTagHelper2
{
_fileVersionProvider = fileVersionProvider;
}
public override void Process(TagHelperContext context, TagHelperOutput output)
{
var attr = output.Attributes["href"].Value.ToString();
var symbolIndex = attr!.IndexOf("#", StringComparison.InvariantCulture);
var start = attr.IndexOf("~", StringComparison.InvariantCulture) + 1;
var length = (symbolIndex != -1 ? symbolIndex : attr.Length) - start;
var filePath = attr.Substring(start, length);
if (!string.IsNullOrEmpty(filePath))
{
var versioned = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, filePath);
attr = attr.Replace(filePath, versioned);
}
attr = _fileVersionProvider.AddFileVersionToPath(ViewContext.HttpContext.Request.PathBase, attr);
output.Attributes.SetAttribute("href", attr);
base.Process(context, output);
}
}
}

View File

@@ -14,7 +14,7 @@
<RepositoryType>git</RepositoryType>
</PropertyGroup>
<PropertyGroup>
<Version Condition=" '$(Version)' == '' ">1.7.2</Version>
<Version Condition=" '$(Version)' == '' ">1.7.1</Version>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PublishRepositoryUrl>true</PublishRepositoryUrl>
@@ -28,8 +28,8 @@
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.21" />
<PackageReference Include="NBitcoin" Version="7.0.24" />
<PackageReference Include="BTCPayServer.Lightning.Common" Version="1.3.16" />
<PackageReference Include="NBitcoin" Version="7.0.20" />
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
<ItemGroup>

View File

@@ -1,5 +1,4 @@
using System;
using System.Collections.Generic;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
@@ -23,15 +22,6 @@ namespace BTCPayServer.Client
return await HandleResponse<ApiKeyData>(response);
}
public virtual async Task<ApiKeyData> CreateAPIKey(string userId, CreateApiKeyRequest request, CancellationToken token = default)
{
if (request == null)
throw new ArgumentNullException(nameof(request));
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{userId}/api-keys",
bodyPayload: request, method: HttpMethod.Post), token);
return await HandleResponse<ApiKeyData>(response);
}
public virtual async Task RevokeCurrentAPIKeyInfo(CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/api-keys/current", null, HttpMethod.Delete), token);
@@ -45,14 +35,5 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/api-keys/{apikey}", null, HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task RevokeAPIKey(string userId, string apikey, CancellationToken token = default)
{
if (apikey == null)
throw new ArgumentNullException(nameof(apikey));
if (userId is null)
throw new ArgumentNullException(nameof(userId));
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{userId}/api-keys/{apikey}", null, HttpMethod.Delete), token);
await HandleResponse(response);
}
}
}

View File

@@ -19,7 +19,7 @@ namespace BTCPayServer.Client
method: HttpMethod.Post), token);
return await HandleResponse<PointOfSaleAppData>(response);
}
public virtual async Task<CrowdfundAppData> CreateCrowdfundApp(string storeId,
CreateCrowdfundAppRequest request, CancellationToken token = default)
{
@@ -52,44 +52,6 @@ namespace BTCPayServer.Client
return await HandleResponse<AppDataBase>(response);
}
public virtual async Task<AppDataBase[]> GetAllApps(string storeId, CancellationToken token = default)
{
if (storeId == null)
throw new ArgumentNullException(nameof(storeId));
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/apps",
method: HttpMethod.Get), token);
return await HandleResponse<AppDataBase[]>(response);
}
public virtual async Task<AppDataBase[]> GetAllApps(CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/apps",
method: HttpMethod.Get), token);
return await HandleResponse<AppDataBase[]>(response);
}
public virtual async Task<PointOfSaleAppData> GetPosApp(string appId, CancellationToken token = default)
{
if (appId == null)
throw new ArgumentNullException(nameof(appId));
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/apps/pos/{appId}",
method: HttpMethod.Get), token);
return await HandleResponse<PointOfSaleAppData>(response);
}
public virtual async Task<CrowdfundAppData> GetCrowdfundApp(string appId, CancellationToken token = default)
{
if (appId == null)
throw new ArgumentNullException(nameof(appId));
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/apps/crowdfund/{appId}",
method: HttpMethod.Get), token);
return await HandleResponse<CrowdfundAppData>(response);
}
public virtual async Task DeleteApp(string appId, CancellationToken token = default)
{
if (appId == null)

View File

@@ -50,7 +50,7 @@ namespace BTCPayServer.Client
await HandleResponse(response);
}
public virtual async Task<DepositAddressData> GetCustodianAccountDepositAddress(string storeId, string accountId, string paymentMethod, CancellationToken token = default)
public virtual async Task<DepositAddressData> GetDepositAddress(string storeId, string accountId, string paymentMethod, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/addresses/{paymentMethod}"), token);
return await HandleResponse<DepositAddressData>(response);
@@ -58,6 +58,7 @@ namespace BTCPayServer.Client
public virtual async Task<MarketTradeResponseData> MarketTradeCustodianAccountAsset(string storeId, string accountId, TradeRequestData request, CancellationToken token = default)
{
//var response = await _httpClient.SendAsync(CreateHttpRequest("api/v1/users", null, request, HttpMethod.Post), token);
//return await HandleResponse<ApplicationUserData>(response);
var internalRequest = CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/market", null,
@@ -66,13 +67,13 @@ namespace BTCPayServer.Client
return await HandleResponse<MarketTradeResponseData>(response);
}
public virtual async Task<MarketTradeResponseData> GetCustodianAccountTradeInfo(string storeId, string accountId, string tradeId, CancellationToken token = default)
public virtual async Task<MarketTradeResponseData> GetTradeInfo(string storeId, string accountId, string tradeId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/{tradeId}", method: HttpMethod.Get), token);
return await HandleResponse<MarketTradeResponseData>(response);
}
public virtual async Task<TradeQuoteResponseData> GetCustodianAccountTradeQuote(string storeId, string accountId, string fromAsset, string toAsset, CancellationToken token = default)
public virtual async Task<TradeQuoteResponseData> GetTradeQuote(string storeId, string accountId, string fromAsset, string toAsset, CancellationToken token = default)
{
var queryPayload = new Dictionary<string, object>();
queryPayload.Add("fromAsset", fromAsset);
@@ -80,20 +81,14 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/trades/quote", queryPayload), token);
return await HandleResponse<TradeQuoteResponseData>(response);
}
public virtual async Task<WithdrawalResponseData> CreateCustodianAccountWithdrawal(string storeId, string accountId, WithdrawRequestData request, CancellationToken token = default)
public virtual async Task<WithdrawalResponseData> CreateWithdrawal(string storeId, string accountId, WithdrawRequestData request, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals", bodyPayload: request, method: HttpMethod.Post), token);
return await HandleResponse<WithdrawalResponseData>(response);
}
public virtual async Task<WithdrawalSimulationResponseData> SimulateCustodianAccountWithdrawal(string storeId, string accountId, WithdrawRequestData request, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals/simulation", bodyPayload: request, method: HttpMethod.Post), token);
return await HandleResponse<WithdrawalSimulationResponseData>(response);
}
public virtual async Task<WithdrawalResponseData> GetCustodianAccountWithdrawalInfo(string storeId, string accountId, string paymentMethod, string withdrawalId, CancellationToken token = default)
public virtual async Task<WithdrawalResponseData> GetWithdrawalInfo(string storeId, string accountId, string paymentMethod, string withdrawalId, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/custodian-accounts/{accountId}/withdrawals/{paymentMethod}/{withdrawalId}", method: HttpMethod.Get), token);
return await HandleResponse<WithdrawalResponseData>(response);

View File

@@ -17,7 +17,7 @@ namespace BTCPayServer.Client
method: HttpMethod.Get), token);
return await HandleResponse<LightningNodeInformationData>(response);
}
public virtual async Task<LightningNodeBalanceData> GetLightningNodeBalance(string cryptoCode,
CancellationToken token = default)
{
@@ -95,7 +95,7 @@ namespace BTCPayServer.Client
method: HttpMethod.Get), token);
return await HandleResponse<LightningInvoiceData>(response);
}
public virtual async Task<LightningInvoiceData[]> GetLightningInvoices(string cryptoCode,
bool? pendingOnly = null, long? offsetIndex = null, CancellationToken token = default)
{
@@ -114,24 +114,6 @@ namespace BTCPayServer.Client
return await HandleResponse<LightningInvoiceData[]>(response);
}
public virtual async Task<LightningPaymentData[]> GetLightningPayments(string cryptoCode,
bool? includePending = null, long? offsetIndex = null, CancellationToken token = default)
{
var queryPayload = new Dictionary<string, object>();
if (includePending is bool v)
{
queryPayload.Add("includePending", v.ToString());
}
if (offsetIndex is > 0)
{
queryPayload.Add("offsetIndex", offsetIndex);
}
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/server/lightning/{cryptoCode}/payments", queryPayload), token);
return await HandleResponse<LightningPaymentData[]>(response);
}
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string cryptoCode, CreateLightningInvoiceRequest request,
CancellationToken token = default)
{

View File

@@ -17,7 +17,7 @@ namespace BTCPayServer.Client
method: HttpMethod.Get), token);
return await HandleResponse<LightningNodeInformationData>(response);
}
public virtual async Task<LightningNodeBalanceData> GetLightningNodeBalance(string storeId, string cryptoCode,
CancellationToken token = default)
{
@@ -97,7 +97,7 @@ namespace BTCPayServer.Client
method: HttpMethod.Get), token);
return await HandleResponse<LightningInvoiceData>(response);
}
public virtual async Task<LightningInvoiceData[]> GetLightningInvoices(string storeId, string cryptoCode,
bool? pendingOnly = null, long? offsetIndex = null, CancellationToken token = default)
{
@@ -116,24 +116,6 @@ namespace BTCPayServer.Client
return await HandleResponse<LightningInvoiceData[]>(response);
}
public virtual async Task<LightningPaymentData[]> GetLightningPayments(string storeId, string cryptoCode,
bool? includePending = null, long? offsetIndex = null, CancellationToken token = default)
{
var queryPayload = new Dictionary<string, object>();
if (includePending is bool v)
{
queryPayload.Add("includePending", v.ToString());
}
if (offsetIndex is > 0)
{
queryPayload.Add("offsetIndex", offsetIndex);
}
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning/{cryptoCode}/payments", queryPayload), token);
return await HandleResponse<LightningPaymentData[]>(response);
}
public virtual async Task<LightningInvoiceData> CreateLightningInvoice(string storeId, string cryptoCode,
CreateLightningInvoiceRequest request, CancellationToken token = default)
{

View File

@@ -1,48 +0,0 @@
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using BTCPayServer.Client.Models;
namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<LightningAddressData[]> GetStoreLightningAddresses(string storeId,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses",
method: HttpMethod.Get), token);
return await HandleResponse<LightningAddressData[]>(response);
}
public virtual async Task<LightningAddressData> GetStoreLightningAddress(string storeId, string username,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses/{username}",
method: HttpMethod.Get), token);
return await HandleResponse<LightningAddressData>(response);
}
public virtual async Task RemoveStoreLightningAddress(string storeId, string username,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses/{username}",
method: HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<LightningAddressData> AddOrUpdateStoreLightningAddress(string storeId,
string username, LightningAddressData data,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/lightning-addresses/{username}",
method: HttpMethod.Post, bodyPayload: data), token);
return await HandleResponse<LightningAddressData>(response);
}
}
}

View File

@@ -39,7 +39,7 @@ namespace BTCPayServer.Client
parameters.Add("includeNeighbourData", v);
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", parameters, method: HttpMethod.Get), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", parameters, method:HttpMethod.Get), token);
return await HandleResponse<OnChainWalletObjectData[]>(response);
}
public virtual async Task RemoveOnChainWalletObject(string storeId, string cryptoCode, OnChainWalletObjectId objectId,
@@ -47,7 +47,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}", method: HttpMethod.Delete), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}", method:HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<OnChainWalletObjectData> AddOrUpdateOnChainWalletObject(string storeId, string cryptoCode, AddOnChainWalletObjectRequest request,
@@ -55,7 +55,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", method: HttpMethod.Post, bodyPayload: request), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects", method:HttpMethod.Post, bodyPayload: request), token);
return await HandleResponse<OnChainWalletObjectData>(response);
}
public virtual async Task AddOrUpdateOnChainWalletLink(string storeId, string cryptoCode,
@@ -65,7 +65,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links", method: HttpMethod.Post, bodyPayload: request), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links", method:HttpMethod.Post, bodyPayload: request), token);
await HandleResponse(response);
}
public virtual async Task RemoveOnChainWalletLinks(string storeId, string cryptoCode,
@@ -75,7 +75,7 @@ namespace BTCPayServer.Client
{
var response =
await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links/{link.Type}/{link.Id}", method: HttpMethod.Delete), token);
CreateHttpRequest($"api/v1/stores/{storeId}/payment-methods/onchain/{cryptoCode}/wallet/objects/{objectId.Type}/{objectId.Id}/links/{link.Type}/{link.Id}", method:HttpMethod.Delete), token);
await HandleResponse(response);
}
}

View File

@@ -63,8 +63,7 @@ namespace BTCPayServer.Client
{
query.Add(nameof(statusFilter), statusFilter);
}
if (labelFilter != null)
{
if (labelFilter != null) {
query.Add(nameof(labelFilter), labelFilter);
}
var response =

View File

@@ -52,17 +52,17 @@ namespace BTCPayServer.Client
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}/payouts", bodyPayload: payoutRequest, method: HttpMethod.Post), cancellationToken);
return await HandleResponse<PayoutData>(response);
}
}
public virtual async Task<PayoutData> GetPullPaymentPayout(string pullPaymentId, string payoutId, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/pull-payments/{HttpUtility.UrlEncode(pullPaymentId)}/payouts/{payoutId}", method: HttpMethod.Get), cancellationToken);
return await HandleResponse<PayoutData>(response);
}
}
public virtual async Task<PayoutData> GetStorePayout(string storeId, string payoutId, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payouts/{payoutId}", method: HttpMethod.Get), cancellationToken);
return await HandleResponse<PayoutData>(response);
}
}
public virtual async Task<PayoutData> CreatePayout(string storeId, CreatePayoutThroughStoreRequest payoutRequest, CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payouts", bodyPayload: payoutRequest, method: HttpMethod.Post), cancellationToken);
@@ -97,15 +97,5 @@ namespace BTCPayServer.Client
method: HttpMethod.Post, bodyPayload: request), cancellationToken);
await HandleResponse(response);
}
public virtual async Task<PullPaymentLNURL> GetPullPaymentLNURL(string pullPaymentId,
CancellationToken cancellationToken = default)
{
var response = await _httpClient.SendAsync(
CreateHttpRequest(
$"/api/v1/pull-payments/{pullPaymentId}/lnurl",
method: HttpMethod.Get), cancellationToken);
return await HandleResponse<PullPaymentLNURL>(response);
}
}
}

View File

@@ -9,7 +9,7 @@ namespace BTCPayServer.Client
{
public partial class BTCPayServerClient
{
public virtual async Task<IEnumerable<PayoutProcessorData>> GetPayoutProcessors(string storeId,
public virtual async Task<IEnumerable<PayoutProcessorData>> GetPayoutProcessors(string storeId,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors"), token);
@@ -20,28 +20,28 @@ namespace BTCPayServer.Client
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/{processor}/{paymentMethod}", null, HttpMethod.Delete), token);
await HandleResponse(response);
}
public virtual async Task<IEnumerable<LightningAutomatedPayoutSettings>> GetStoreLightningAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory{(paymentMethod is null ? string.Empty : $"/{paymentMethod}")}"), token);
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory{(paymentMethod is null? string.Empty: $"/{paymentMethod}")}"), token);
return await HandleResponse<IEnumerable<LightningAutomatedPayoutSettings>>(response);
}
public virtual async Task<LightningAutomatedPayoutSettings> UpdateStoreLightningAutomatedPayoutProcessors(string storeId, string paymentMethod, LightningAutomatedPayoutSettings request, CancellationToken token = default)
public virtual async Task<LightningAutomatedPayoutSettings> UpdateStoreLightningAutomatedPayoutProcessors(string storeId, string paymentMethod,LightningAutomatedPayoutSettings request, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory/{paymentMethod}", null, request, HttpMethod.Put), token);
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/LightningAutomatedPayoutSenderFactory/{paymentMethod}",null, request, HttpMethod.Put ), token);
return await HandleResponse<LightningAutomatedPayoutSettings>(response);
}
public virtual async Task<OnChainAutomatedPayoutSettings> UpdateStoreOnChainAutomatedPayoutProcessors(string storeId, string paymentMethod, OnChainAutomatedPayoutSettings request, CancellationToken token = default)
public virtual async Task<OnChainAutomatedPayoutSettings> UpdateStoreOnChainAutomatedPayoutProcessors(string storeId, string paymentMethod,OnChainAutomatedPayoutSettings request, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory/{paymentMethod}", null, request, HttpMethod.Put), token);
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory/{paymentMethod}",null, request, HttpMethod.Put ), token);
return await HandleResponse<OnChainAutomatedPayoutSettings>(response);
}
public virtual async Task<IEnumerable<OnChainAutomatedPayoutSettings>> GetStoreOnChainAutomatedPayoutProcessors(string storeId, string? paymentMethod = null,
CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory{(paymentMethod is null ? string.Empty : $"/{paymentMethod}")}"), token);
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/stores/{storeId}/payout-processors/OnChainAutomatedPayoutSenderFactory{(paymentMethod is null? string.Empty: $"/{paymentMethod}")}"), token);
return await HandleResponse<IEnumerable<OnChainAutomatedPayoutSettings>>(response);
}
}

View File

@@ -37,28 +37,17 @@ namespace BTCPayServer.Client
return await HandleResponse<StoreRateConfiguration>(response);
}
public virtual async Task<List<StoreRateResult>> PreviewUpdateStoreRateConfiguration(string storeId,
public virtual async Task<List<StoreRatePreviewResult>> PreviewUpdateStoreRateConfiguration(string storeId,
StoreRateConfiguration request,
string[] currencyPair,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/rates/configuration/preview", bodyPayload: request,
queryPayload: new Dictionary<string, object>() { { "currencyPair", currencyPair } },
queryPayload: new Dictionary<string, object>() {{"currencyPair", currencyPair}},
method: HttpMethod.Post),
token);
return await HandleResponse<List<StoreRateResult>>(response);
}
public virtual async Task<List<StoreRateResult>> GetStoreRates(string storeId, string[] currencyPair,
CancellationToken token = default)
{
using var response = await _httpClient.SendAsync(
CreateHttpRequest($"api/v1/stores/{storeId}/rates",
queryPayload: new Dictionary<string, object>() { { "currencyPair", currencyPair } },
method: HttpMethod.Get),
token);
return await HandleResponse<List<StoreRateResult>>(response);
return await HandleResponse<List<StoreRatePreviewResult>>(response);
}
}
}

View File

@@ -33,15 +33,14 @@ namespace BTCPayServer.Client
return await HandleResponse<ApplicationUserData>(response);
}
public virtual async Task<bool> LockUser(string idOrEmail, bool locked, CancellationToken token = default)
public virtual async Task LockUser(string idOrEmail, bool locked, CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/{idOrEmail}/lock", null,
new LockUserRequest { Locked = locked }, HttpMethod.Post), token);
new LockUserRequest() {Locked = locked}, HttpMethod.Post), token);
await HandleResponse(response);
return response.IsSuccessStatusCode;
}
public virtual async Task<ApplicationUserData[]> GetUsers(CancellationToken token = default)
public virtual async Task<ApplicationUserData[]> GetUsers( CancellationToken token = default)
{
var response = await _httpClient.SendAsync(CreateHttpRequest($"api/v1/users/", null, HttpMethod.Get), token);
return await HandleResponse<ApplicationUserData[]>(response);

View File

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

View File

@@ -1,36 +0,0 @@
using System;
using System.Globalization;
using BTCPayServer.Client.Models;
using BTCPayServer.Lightning;
using NBitcoin.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Client.JsonConverters
{
public class TradeQuantityJsonConverter : JsonConverter<TradeQuantity>
{
public override TradeQuantity ReadJson(JsonReader reader, Type objectType, TradeQuantity existingValue, bool hasExistingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
switch (token.Type)
{
case JTokenType.Float:
case JTokenType.Integer:
case JTokenType.String:
if (TradeQuantity.TryParse(token.ToString(), out var q))
return q;
break;
case JTokenType.Null:
return null;
}
throw new JsonObjectException("Invalid TradeQuantity, expected string. Expected: \"1.50\" or \"50%\"", reader);
}
public override void WriteJson(JsonWriter writer, TradeQuantity value, JsonSerializer serializer)
{
if (value is not null)
writer.WriteValue(value.ToString());
}
}
}

View File

@@ -8,7 +8,7 @@ public class AssetPairData
public AssetPairData()
{
}
public AssetPairData(string assetBought, string assetSold, decimal minimumTradeQty)
{
AssetBought = assetBought;
@@ -25,7 +25,7 @@ public class AssetPairData
[JsonProperty]
public decimal MinimumTradeQty { set; get; }
public override string ToString()
{
return AssetBought + "/" + AssetSold;

View File

@@ -11,18 +11,19 @@ namespace BTCPayServer.Client.Models
{
}
public CreateLightningInvoiceRequest(LightMoney amount, string description, TimeSpan expiry)
{
Amount = amount;
Description = description;
Expiry = expiry;
}
[JsonConverter(typeof(JsonConverters.LightMoneyJsonConverter))]
public LightMoney Amount { get; set; }
public string Description { get; set; }
public bool DescriptionHashOnly { 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; }

View File

@@ -5,11 +5,11 @@ namespace BTCPayServer.Client.Models
public abstract class CustodianAccountBaseData
{
public string CustodianCode { get; set; }
public string Name { get; set; }
public string StoreId { get; set; }
public JObject Config { get; set; }
}

View File

@@ -2,13 +2,13 @@ using System.Collections.Generic;
namespace BTCPayServer.Client.Models;
public class CustodianAccountResponse : CustodianAccountData
public class CustodianAccountResponse: CustodianAccountData
{
public IDictionary<string, decimal> AssetBalances { get; set; }
public CustodianAccountResponse()
{
}
}

View File

@@ -9,5 +9,5 @@ public class CustodianData
public Dictionary<string, AssetPairData> TradableAssetPairs { get; set; }
public string[] WithdrawablePaymentMethods { get; set; }
public string[] DepositablePaymentMethods { get; set; }
}

View File

@@ -6,10 +6,10 @@ public class DepositAddressData
// * Example: P2PKH, P2SH, P2WPKH, P2TR, BOLT11, ...
// */
// public string Type { get; set; }
/**
* Format depends hugely on the type.
*/
public string Address { get; set; }
}

View File

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

View File

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

View File

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

View File

@@ -1,4 +1,3 @@
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
@@ -7,7 +6,6 @@ namespace BTCPayServer.Client.Models;
public class LedgerEntryData
{
public string Asset { get; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Qty { get; }
[JsonConverter(typeof(StringEnumConverter))]

View File

@@ -1,10 +0,0 @@
namespace BTCPayServer.Client.Models;
public class LightningAddressData
{
public string Username { get; set; }
public string CurrencyCode { get; set; }
public decimal? Min { get; set; }
public decimal? Max { get; set; }
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using BTCPayServer.Client.JsonConverters;
using Newtonsoft.Json;
@@ -7,7 +7,7 @@ namespace BTCPayServer.Client.Models;
public class LightningAutomatedPayoutSettings
{
public string PaymentMethod { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan IntervalSeconds { get; set; }
}

View File

@@ -17,14 +17,8 @@ namespace BTCPayServer.Client.Models
[JsonProperty("BOLT11")]
public string BOLT11 { get; set; }
public string PaymentHash { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public string Preimage { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? PaidAt { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset ExpiresAt { get; set; }

View File

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

View File

@@ -16,12 +16,13 @@ namespace BTCPayServer.Client.Models
{
}
public LightningNetworkPaymentMethodData(string cryptoCode, string connectionString, bool enabled, string paymentMethod)
public LightningNetworkPaymentMethodData(string cryptoCode, string connectionString, bool enabled, string paymentMethod, bool disableBOLT11PaymentOption)
{
Enabled = enabled;
CryptoCode = cryptoCode;
ConnectionString = connectionString;
PaymentMethod = paymentMethod;
DisableBOLT11PaymentOption = disableBOLT11PaymentOption;
}
public string PaymentMethod { get; set; }

View File

@@ -9,10 +9,10 @@ namespace BTCPayServer.Client.Models
{
[JsonProperty("onchain")]
public OnchainBalanceData OnchainBalance { get; set; }
[JsonProperty("offchain")]
public OffchainBalanceData OffchainBalance { get; set; }
public LightningNodeBalanceData()
{
}
@@ -31,7 +31,7 @@ namespace BTCPayServer.Client.Models
[JsonConverter(typeof(JsonConverters.MoneyJsonConverter))]
public Money Unconfirmed { get; set; }
[JsonConverter(typeof(JsonConverters.MoneyJsonConverter))]
public Money Reserved { get; set; }
}
@@ -40,13 +40,13 @@ namespace BTCPayServer.Client.Models
{
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Opening { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Local { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Remote { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Closing { get; set; }
}

View File

@@ -17,12 +17,12 @@ namespace BTCPayServer.Client.Models
[JsonProperty("BOLT11")]
public string BOLT11 { get; set; }
public string Preimage { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? CreatedAt { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney TotalAmount { get; set; }

View File

@@ -1,4 +1,4 @@
namespace BTCPayServer.Client;
namespace BTCPayServer.Client;
public class LockUserRequest
{

View File

@@ -16,7 +16,7 @@ public class MarketTradeResponseData
public string TradeId { get; }
public string AccountId { get; }
public string CustodianCode { get; }
public MarketTradeResponseData(string fromAsset, string toAsset, List<LedgerEntryData> ledgerEntries, string tradeId, string accountId, string custodianCode)

View File

@@ -6,8 +6,6 @@ namespace BTCPayServer.Client.Models
public class NotificationData
{
public string Id { get; set; }
public string Identifier { get; set; }
public string Type { get; set; }
public string Body { get; set; }
public bool Seen { get; set; }
public Uri Link { get; set; }

View File

@@ -1,4 +1,4 @@
using System;
using System;
using BTCPayServer.Client.JsonConverters;
using Newtonsoft.Json;
@@ -7,9 +7,9 @@ namespace BTCPayServer.Client.Models;
public class OnChainAutomatedPayoutSettings
{
public string PaymentMethod { get; set; }
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
public TimeSpan IntervalSeconds { get; set; }
public int? FeeBlockTarget { get; set; }
public int? FeeBlockTarget { get; set; }
}

View File

@@ -11,7 +11,7 @@ namespace BTCPayServer.Client.Models
{
[JsonConverter(typeof(NodeUriJsonConverter))]
[JsonProperty("nodeURI")]
public BTCPayServer.Lightning.NodeInfo NodeURI { get; set; }
public NodeInfo NodeURI { get; set; }
[JsonConverter(typeof(MoneyJsonConverter))]
public Money ChannelAmount { get; set; }

View File

@@ -11,13 +11,13 @@ namespace BTCPayServer.Client.Models
{
[JsonProperty("BOLT11")]
public string BOLT11 { get; set; }
[JsonProperty(ItemConverterType = typeof(NumericStringJsonConverter))]
public float? MaxFeePercent { get; set; }
[JsonConverter(typeof(MoneyJsonConverter))]
public Money MaxFeeFlat { get; set; }
[JsonConverter(typeof(LightMoneyJsonConverter))]
public LightMoney Amount { get; set; }

View File

@@ -1,13 +0,0 @@
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models;
public class PaymentMethodCriteriaData
{
public string PaymentMethod { get; set; }
public string CurrencyCode { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Amount { get; set; }
public bool Above { get; set; }
}

View File

@@ -12,56 +12,14 @@ namespace BTCPayServer.Client.Models
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset Created { get; set; }
}
public class PointOfSaleAppData : AppDataBase
{
public string Title { get; set; }
public string DefaultView { get; set; }
public bool ShowCustomAmount { get; set; }
public bool ShowDiscount { get; set; }
public bool EnableTips { get; set; }
public string Currency { get; set; }
public object Items { get; set; }
public string FixedAmountPayButtonText { get; set; }
public string CustomAmountPayButtonText { get; set; }
public string TipText { get; set; }
public string CustomCSSLink { get; set; }
public string NotificationUrl { get; set; }
public string RedirectUrl { get; set; }
public string Description { get; set; }
public string EmbeddedCSS { get; set; }
public bool? RedirectAutomatically { get; set; }
public bool? RequiresRefundEmail { get; set; }
// We can add POS specific things here later
}
public class CrowdfundAppData : AppDataBase
{
public string Title { get; set; }
public bool Enabled { get; set; }
public bool EnforceTargetAmount { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? StartDate { get; set; }
public string TargetCurrency { get; set; }
public string Description { get; set; }
[JsonConverter(typeof(NBitcoin.JsonConverters.DateTimeToUnixTimeConverter))]
public DateTimeOffset? EndDate { get; set; }
public decimal? TargetAmount { get; set; }
public string CustomCSSLink { get; set; }
public string MainImageUrl { get; set; }
public string EmbeddedCSS { get; set; }
public string NotificationUrl { get; set; }
public string Tagline { get; set; }
public object Perks { get; set; }
public bool DisqusEnabled { get; set; }
public string DisqusShortname { get; set; }
public bool SoundsEnabled { get; set; }
public bool AnimationsEnabled { get; set; }
public int ResetEveryAmount { get; set; }
public string ResetEvery { get; set; }
public bool DisplayPerksValue { get; set; }
public bool DisplayPerksRanking { get; set; }
public bool SortPerksByPopularity { get; set; }
public string[] Sounds { get; set; }
public string[] AnimationColors { get; set; }
// We can add Crowdfund specific things here later
}
}

View File

@@ -1,8 +0,0 @@
namespace BTCPayServer.Client.Models
{
public class PullPaymentLNURL
{
public string LNURLBech32 { get; set; }
public string LNURLUri { get; set; }
}
}

View File

@@ -1,7 +1,7 @@
namespace BTCPayServer.Client.Models;
namespace BTCPayServer.Client.Models;
public class RateSource
{
public string Id { get; set; }
public string Name { get; set; }
}
}

View File

@@ -20,10 +20,6 @@ namespace BTCPayServer.Client.Models
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public TimeSpan InvoiceExpiration { get; set; } = TimeSpan.FromMinutes(15);
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public TimeSpan DisplayExpirationTimer { get; set; } = TimeSpan.FromMinutes(5);
[JsonConverter(typeof(TimeSpanJsonConverter.Seconds))]
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public TimeSpan MonitoringExpiration { get; set; } = TimeSpan.FromMinutes(60);
@@ -63,11 +59,8 @@ namespace BTCPayServer.Client.Models
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public NetworkFeeMode NetworkFeeMode { get; set; } = NetworkFeeMode.Never;
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<PaymentMethodCriteriaData> PaymentMethodCriteria { get; set; }
public bool PayJoinEnabled { get; set; }
public InvoiceData.ReceiptOptions Receipt { get; set; }

View File

@@ -7,7 +7,7 @@ namespace BTCPayServer.Client.Models
/// </summary>
public string Id { get; set; }
}
public class StoreUserData
{
/// <summary>

View File

@@ -0,0 +1,10 @@
using System.Collections.Generic;
namespace BTCPayServer.Client.Models;
public class StoreRatePreviewResult
{
public string CurrencyPair { get; set; }
public decimal? Rate { get; set; }
public List<string> Errors { get; set; }
}

View File

@@ -1,13 +1,7 @@
using System.Collections.Generic;
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models;
namespace BTCPayServer.Client.Models;
public class StoreRateResult
{
public string CurrencyPair { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? Rate { get; set; }
public List<string> Errors { get; set; }
}
public decimal Rate { get; set; }
}

View File

@@ -1,13 +1,8 @@
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models;
public class TradeQuoteResponseData
{
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Bid { get; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal Ask { get; }
public string ToAsset { get; }
public string FromAsset { get; }

View File

@@ -1,11 +1,8 @@
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models;
public class TradeRequestData
{
public string FromAsset { set; get; }
public string ToAsset { set; get; }
[JsonConverter(typeof(JsonConverters.TradeQuantityJsonConverter))]
public TradeQuantity Qty { set; get; }
public string Qty { set; get; }
}

View File

@@ -1,85 +1,13 @@
using System;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Net.Http.Headers;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models;
public class WithdrawRequestData
{
public string PaymentMethod { set; get; }
[JsonConverter(typeof(JsonConverters.TradeQuantityJsonConverter))]
public TradeQuantity Qty { set; get; }
public decimal Qty { set; get; }
public WithdrawRequestData()
{
}
public WithdrawRequestData(string paymentMethod, TradeQuantity qty)
public WithdrawRequestData(string paymentMethod, decimal qty)
{
PaymentMethod = paymentMethod;
Qty = qty;
}
}
#nullable enable
public record TradeQuantity
{
public TradeQuantity(decimal value, ValueType type)
{
Type = type;
Value = value;
}
public enum ValueType
{
Exact,
Percent
}
public ValueType Type { get; }
public decimal Value { get; set; }
public override string ToString()
{
if (Type == ValueType.Exact)
return Value.ToString(CultureInfo.InvariantCulture);
else
return Value.ToString(CultureInfo.InvariantCulture) + "%";
}
public static TradeQuantity Parse(string str)
{
if (!TryParse(str, out var r))
throw new FormatException("Invalid TradeQuantity");
return r;
}
public static bool TryParse(string str, [MaybeNullWhen(false)] out TradeQuantity quantity)
{
if (str is null)
throw new ArgumentNullException(nameof(str));
quantity = null;
str = str.Trim();
str = str.Replace(" ", "");
if (str.Length == 0)
return false;
if (str[^1] == '%')
{
if (!decimal.TryParse(str[..^1], NumberStyles.Any, CultureInfo.InvariantCulture, out var r))
return false;
if (r < 0.0m)
return false;
quantity = new TradeQuantity(r, TradeQuantity.ValueType.Percent);
}
else
{
if (!decimal.TryParse(str, NumberStyles.Any, CultureInfo.InvariantCulture, out var r))
return false;
if (r < 0.0m)
return false;
quantity = new TradeQuantity(r, TradeQuantity.ValueType.Exact);
}
return true;
}
}

View File

@@ -1,22 +0,0 @@
using System.Collections.Generic;
namespace BTCPayServer.Client.Models;
public abstract class WithdrawalBaseResponseData
{
public string Asset { get; }
public string PaymentMethod { get; }
public List<LedgerEntryData> LedgerEntries { get; }
public string AccountId { get; }
public string CustodianCode { get; }
public WithdrawalBaseResponseData(string paymentMethod, string asset, List<LedgerEntryData> ledgerEntries, string accountId,
string custodianCode)
{
PaymentMethod = paymentMethod;
Asset = asset;
LedgerEntries = ledgerEntries;
AccountId = accountId;
CustodianCode = custodianCode;
}
}

View File

@@ -5,13 +5,18 @@ using Newtonsoft.Json.Converters;
namespace BTCPayServer.Client.Models;
public class WithdrawalResponseData : WithdrawalBaseResponseData
public class WithdrawalResponseData
{
public string Asset { get; }
public string PaymentMethod { get; }
public List<LedgerEntryData> LedgerEntries { get; }
public string WithdrawalId { get; }
public string AccountId { get; }
public string CustodianCode { get; }
[JsonConverter(typeof(StringEnumConverter))]
public WithdrawalStatus Status { get; }
public string WithdrawalId { get; }
public DateTimeOffset CreatedTime { get; }
public string TransactionId { get; }
@@ -19,10 +24,14 @@ public class WithdrawalResponseData : WithdrawalBaseResponseData
public string TargetAddress { get; }
public WithdrawalResponseData(string paymentMethod, string asset, List<LedgerEntryData> ledgerEntries, string withdrawalId, string accountId,
string custodianCode, WithdrawalStatus status, DateTimeOffset createdTime, string targetAddress, string transactionId) : base(paymentMethod, asset, ledgerEntries, accountId,
custodianCode)
string custodianCode, WithdrawalStatus status, DateTimeOffset createdTime, string targetAddress, string transactionId)
{
PaymentMethod = paymentMethod;
Asset = asset;
LedgerEntries = ledgerEntries;
WithdrawalId = withdrawalId;
AccountId = accountId;
CustodianCode = custodianCode;
TargetAddress = targetAddress;
TransactionId = transactionId;
Status = status;

View File

@@ -1,21 +0,0 @@
using System.Collections.Generic;
using BTCPayServer.JsonConverters;
using Newtonsoft.Json;
namespace BTCPayServer.Client.Models;
public class WithdrawalSimulationResponseData : WithdrawalBaseResponseData
{
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? MinQty { get; set; }
[JsonConverter(typeof(NumericStringJsonConverter))]
public decimal? MaxQty { get; set; }
public WithdrawalSimulationResponseData(string paymentMethod, string asset, string accountId,
string custodianCode, List<LedgerEntryData> ledgerEntries, decimal? minQty, decimal? maxQty) : base(paymentMethod,
asset, ledgerEntries, accountId, custodianCode)
{
MinQty = minQty;
MaxQty = maxQty;
}
}

View File

@@ -6,9 +6,7 @@ namespace BTCPayServer.Client
{
public class Policies
{
public const string CanViewLightningInvoiceInternalNode = "btcpay.server.canviewlightninginvoiceinternalnode";
public const string CanCreateLightningInvoiceInternalNode = "btcpay.server.cancreatelightninginvoiceinternalnode";
public const string CanViewLightningInvoiceInStore = "btcpay.store.canviewlightninginvoice";
public const string CanCreateLightningInvoiceInStore = "btcpay.store.cancreatelightninginvoice";
public const string CanUseInternalLightningNode = "btcpay.server.canuseinternallightningnode";
public const string CanUseLightningNodeInStore = "btcpay.store.canuselightningnode";
@@ -28,11 +26,8 @@ namespace BTCPayServer.Client
public const string CanViewNotificationsForUser = "btcpay.user.canviewnotificationsforuser";
public const string CanViewUsers = "btcpay.server.canviewusers";
public const string CanCreateUser = "btcpay.server.cancreateuser";
public const string CanManageUsers = "btcpay.server.canmanageusers";
public const string CanDeleteUser = "btcpay.user.candeleteuser";
public const string CanManagePullPayments = "btcpay.store.canmanagepullpayments";
public const string CanCreatePullPayments = "btcpay.store.cancreatepullpayments";
public const string CanCreateNonApprovedPullPayments = "btcpay.store.cancreatenonapprovedpullpayments";
public const string CanViewCustodianAccounts = "btcpay.store.canviewcustodianaccounts";
public const string CanManageCustodianAccounts = "btcpay.store.canmanagecustodianaccounts";
public const string CanDepositToCustodianAccounts = "btcpay.store.candeposittocustodianaccount";
@@ -61,20 +56,15 @@ namespace BTCPayServer.Client
yield return CanViewNotificationsForUser;
yield return Unrestricted;
yield return CanUseInternalLightningNode;
yield return CanViewLightningInvoiceInternalNode;
yield return CanCreateLightningInvoiceInternalNode;
yield return CanUseLightningNodeInStore;
yield return CanViewLightningInvoiceInStore;
yield return CanCreateLightningInvoiceInStore;
yield return CanManagePullPayments;
yield return CanCreatePullPayments;
yield return CanCreateNonApprovedPullPayments;
yield return CanViewCustodianAccounts;
yield return CanManageCustodianAccounts;
yield return CanDepositToCustodianAccounts;
yield return CanWithdrawFromCustodianAccounts;
yield return CanTradeCustodianAccount;
yield return CanManageUsers;
}
}
public static bool IsValidPolicy(string policy)
@@ -98,45 +88,9 @@ namespace BTCPayServer.Client
{
return policy.StartsWith("btcpay.plugin", StringComparison.OrdinalIgnoreCase);
}
public static bool IsUserPolicy(string policy)
{
return policy.StartsWith("btcpay.user", StringComparison.OrdinalIgnoreCase);
}
}
public class PermissionSet
{
public PermissionSet() : this(Array.Empty<Permission>())
{
}
public PermissionSet(Permission[] permissions)
{
Permissions = permissions;
}
public Permission[] Permissions { get; }
public bool Contains(Permission requestedPermission)
{
return Permissions.Any(p => p.Contains(requestedPermission));
}
public bool Contains(string permission, string store)
{
if (permission is null)
throw new ArgumentNullException(nameof(permission));
if (store is null)
throw new ArgumentNullException(nameof(store));
return Contains(Permission.Create(permission, store));
}
}
public class Permission
{
static Permission()
{
Init();
}
public static Permission Create(string policy, string scope = null)
{
if (TryCreatePermission(policy, scope, out var r))
@@ -152,7 +106,7 @@ namespace BTCPayServer.Client
policy = policy.Trim().ToLowerInvariant();
if (!Policies.IsValidPolicy(policy))
return false;
if (!string.IsNullOrEmpty(scope) && !Policies.IsStorePolicy(policy))
if (scope != null && !Policies.IsStorePolicy(policy))
return false;
permission = new Permission(policy, scope);
return true;
@@ -205,7 +159,7 @@ namespace BTCPayServer.Client
}
if (!Policies.IsStorePolicy(subpermission.Policy))
return true;
return Scope == null || subpermission.Scope == Scope;
return Scope == null || subpermission.Scope == this.Scope;
}
public static IEnumerable<Permission> ToPermissions(string[] permissions)
@@ -221,61 +175,35 @@ namespace BTCPayServer.Client
private bool ContainsPolicy(string subpolicy)
{
return ContainsPolicy(Policy, subpolicy);
}
private static bool ContainsPolicy(string policy, string subpolicy)
{
if (policy == Policies.Unrestricted)
if (this.Policy == Policies.Unrestricted)
return true;
if (policy == subpolicy)
if (this.Policy == subpolicy)
return true;
if (!PolicyMap.TryGetValue(policy, out var subPolicies))
return false;
return subPolicies.Contains(subpolicy) || subPolicies.Any(s => ContainsPolicy(s, subpolicy));
}
private static Dictionary<string, HashSet<string>> PolicyMap = new();
private static void Init()
{
PolicyHasChild(Policies.CanModifyStoreSettings,
Policies.CanManageCustodianAccounts,
Policies.CanManagePullPayments,
Policies.CanModifyInvoices,
Policies.CanViewStoreSettings,
Policies.CanModifyStoreWebhooks,
Policies.CanModifyPaymentRequests,
Policies.CanUseLightningNodeInStore);
PolicyHasChild(Policies.CanManageUsers, Policies.CanCreateUser);
PolicyHasChild(Policies.CanManagePullPayments, Policies.CanCreatePullPayments);
PolicyHasChild(Policies.CanCreatePullPayments, Policies.CanCreateNonApprovedPullPayments);
PolicyHasChild(Policies.CanModifyPaymentRequests, Policies.CanViewPaymentRequests);
PolicyHasChild(Policies.CanModifyProfile, Policies.CanViewProfile);
PolicyHasChild(Policies.CanUseLightningNodeInStore, Policies.CanViewLightningInvoiceInStore, Policies.CanCreateLightningInvoiceInStore);
PolicyHasChild(Policies.CanManageNotificationsForUser, Policies.CanViewNotificationsForUser);
PolicyHasChild(Policies.CanModifyServerSettings,
Policies.CanUseInternalLightningNode,
Policies.CanManageUsers);
PolicyHasChild(Policies.CanUseInternalLightningNode, Policies.CanCreateLightningInvoiceInternalNode, Policies.CanViewLightningInvoiceInternalNode);
PolicyHasChild(Policies.CanManageCustodianAccounts, Policies.CanViewCustodianAccounts);
PolicyHasChild(Policies.CanModifyInvoices, Policies.CanViewInvoices, Policies.CanCreateInvoice, Policies.CanCreateLightningInvoiceInStore);
PolicyHasChild(Policies.CanViewStoreSettings, Policies.CanViewInvoices, Policies.CanViewPaymentRequests);
}
private static void PolicyHasChild(string policy, params string[] subPolicies)
{
if (PolicyMap.TryGetValue(policy, out var existingSubPolicies))
switch (subpolicy)
{
foreach (string subPolicy in subPolicies)
{
existingSubPolicies.Add(subPolicy);
}
}
else
{
PolicyMap.Add(policy, subPolicies.ToHashSet());
case Policies.CanViewInvoices when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewInvoices when this.Policy == Policies.CanModifyInvoices:
case Policies.CanModifyStoreWebhooks when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewInvoices when this.Policy == Policies.CanViewStoreSettings:
case Policies.CanViewStoreSettings when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanCreateInvoice when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanModifyInvoices when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewProfile when this.Policy == Policies.CanModifyProfile:
case Policies.CanModifyPaymentRequests when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanManagePullPayments when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanViewStoreSettings:
case Policies.CanViewPaymentRequests when this.Policy == Policies.CanModifyPaymentRequests:
case Policies.CanCreateLightningInvoiceInternalNode when this.Policy == Policies.CanUseInternalLightningNode:
case Policies.CanCreateLightningInvoiceInStore when this.Policy == Policies.CanUseLightningNodeInStore:
case Policies.CanViewNotificationsForUser when this.Policy == Policies.CanManageNotificationsForUser:
case Policies.CanUseInternalLightningNode when this.Policy == Policies.CanModifyServerSettings:
case Policies.CanViewCustodianAccounts when this.Policy == Policies.CanManageCustodianAccounts:
case Policies.CanViewCustodianAccounts when this.Policy == Policies.CanModifyStoreSettings:
case Policies.CanManageCustodianAccounts when this.Policy == Policies.CanModifyStoreSettings:
return true;
default:
return false;
}
}
@@ -284,17 +212,23 @@ namespace BTCPayServer.Client
public override string ToString()
{
return Scope != null ? $"{Policy}:{Scope}" : Policy;
if (Scope != null)
{
return $"{Policy}:{Scope}";
}
return Policy;
}
public override bool Equals(object obj)
{
Permission item = obj as Permission;
return item != null && ToString().Equals(item.ToString());
if (item == null)
return false;
return ToString().Equals(item.ToString());
}
public static bool operator ==(Permission a, Permission b)
{
if (ReferenceEquals(a, b))
if (System.Object.ReferenceEquals(a, b))
return true;
if (((object)a == null) || ((object)b == null))
return false;

View File

@@ -4,8 +4,8 @@
<ItemGroup>
<FrameworkReference Include="Microsoft.AspNetCore.App" />
<PackageReference Include="NBXplorer.Client" Version="4.2.3" />
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="2.0.1" />
<PackageReference Include="NBXplorer.Client" Version="4.2.1" />
<PackageReference Include="NicolasDorier.StandardConfiguration" Version="1.0.0.18" />
</ItemGroup>
<ItemGroup Condition="'$(Altcoins)' != 'true'">
<Compile Remove="Altcoins\**\*.cs"></Compile>

View File

@@ -23,7 +23,7 @@ namespace BTCPayServer
internal Task ProcessTask;
public async Task Process(CancellationToken cancellationToken)
{
retry:
retry:
while (Chan.Reader.TryRead(out var item))
{
await item(cancellationToken);
@@ -52,7 +52,7 @@ retry:
{
lock (_Queues)
{
retry:
retry:
if (stopped)
return;
Cleanup();

View File

@@ -1,6 +1,6 @@
using System;
using System.Linq;
using System.Threading.Tasks;
using BTCPayServer.Data.Data;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;
@@ -30,12 +30,7 @@ namespace BTCPayServer.Data
{
_designTime = designTime;
}
#nullable enable
public async Task<string?> GetMigrationState()
{
return (await Settings.FromSqlRaw("SELECT \"Id\", \"Value\" FROM \"Settings\" WHERE \"Id\"='MigrationData'").AsNoTracking().FirstOrDefaultAsync())?.Value;
}
#nullable restore
public DbSet<AddressInvoiceData> AddressInvoices { get; set; }
public DbSet<APIKeyData> ApiKeys { get; set; }
public DbSet<AppData> Apps { get; set; }
@@ -72,9 +67,8 @@ namespace BTCPayServer.Data
public DbSet<WalletTransactionData> WalletTransactions { get; set; }
public DbSet<WebhookDeliveryData> WebhookDeliveries { get; set; }
public DbSet<WebhookData> Webhooks { get; set; }
public DbSet<LightningAddressData> LightningAddresses { get; set; }
public DbSet<LightningAddressData> LightningAddresses{ get; set; }
public DbSet<PayoutProcessorData> PayoutProcessors { get; set; }
public DbSet<FormData> Forms { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
{
@@ -89,23 +83,23 @@ namespace BTCPayServer.Data
// some of the data models don't have OnModelCreating for now, commenting them
ApplicationUser.OnModelCreating(builder, Database);
ApplicationUser.OnModelCreating(builder);
AddressInvoiceData.OnModelCreating(builder);
APIKeyData.OnModelCreating(builder, Database);
APIKeyData.OnModelCreating(builder);
AppData.OnModelCreating(builder);
CustodianAccountData.OnModelCreating(builder, Database);
CustodianAccountData.OnModelCreating(builder);
//StoredFile.OnModelCreating(builder);
InvoiceEventData.OnModelCreating(builder);
InvoiceSearchData.OnModelCreating(builder);
InvoiceWebhookDeliveryData.OnModelCreating(builder);
InvoiceData.OnModelCreating(builder, Database);
NotificationData.OnModelCreating(builder, Database);
InvoiceData.OnModelCreating(builder);
NotificationData.OnModelCreating(builder);
//OffchainTransactionData.OnModelCreating(builder);
BTCPayServer.Data.PairedSINData.OnModelCreating(builder);
PairingCodeData.OnModelCreating(builder);
//PayjoinLock.OnModelCreating(builder);
PaymentRequestData.OnModelCreating(builder, Database);
PaymentData.OnModelCreating(builder, Database);
PaymentRequestData.OnModelCreating(builder);
PaymentData.OnModelCreating(builder);
PayoutData.OnModelCreating(builder);
PendingInvoiceData.OnModelCreating(builder);
//PlannedTransaction.OnModelCreating(builder);
@@ -116,7 +110,7 @@ namespace BTCPayServer.Data
StoreWebhookData.OnModelCreating(builder);
StoreData.OnModelCreating(builder, Database);
U2FDevice.OnModelCreating(builder);
Fido2Credential.OnModelCreating(builder, Database);
Fido2Credential.OnModelCreating(builder);
BTCPayServer.Data.UserStore.OnModelCreating(builder);
//WalletData.OnModelCreating(builder);
WalletObjectData.OnModelCreating(builder, Database);
@@ -124,11 +118,10 @@ namespace BTCPayServer.Data
#pragma warning disable CS0612 // Type or member is obsolete
WalletTransactionData.OnModelCreating(builder);
#pragma warning restore CS0612 // Type or member is obsolete
WebhookDeliveryData.OnModelCreating(builder, Database);
LightningAddressData.OnModelCreating(builder, Database);
PayoutProcessorData.OnModelCreating(builder, Database);
WebhookData.OnModelCreating(builder, Database);
FormData.OnModelCreating(builder, Database);
WebhookDeliveryData.OnModelCreating(builder);
LightningAddressData.OnModelCreating(builder);
PayoutProcessorData.OnModelCreating(builder);
//WebhookData.OnModelCreating(builder);
if (Database.IsSqlite() && !_designTime)

View File

@@ -1,11 +1,9 @@
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace BTCPayServer.Data
{
public class APIKeyData : IHasBlob<APIKeyBlob>
public class APIKeyData
{
[MaxLength(50)]
public string Id { get; set; }
@@ -18,15 +16,13 @@ namespace BTCPayServer.Data
public APIKeyType Type { get; set; } = APIKeyType.Legacy;
[Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }
public string Blob2 { get; set; }
public StoreData StoreData { get; set; }
public ApplicationUser User { get; set; }
public string Label { get; set; }
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
internal static void OnModelCreating(ModelBuilder builder)
{
builder.Entity<APIKeyData>()
.HasOne(o => o.StoreData)
@@ -40,13 +36,6 @@ namespace BTCPayServer.Data
builder.Entity<APIKeyData>()
.HasIndex(o => o.StoreId);
if (databaseFacade.IsNpgsql())
{
builder.Entity<APIKeyData>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
}
}
}

View File

@@ -2,13 +2,11 @@ using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Data
{
// Add profile data for application users by adding properties to the ApplicationUser class
public class ApplicationUser : IdentityUser, IHasBlob<UserBlob>
public class ApplicationUser : IdentityUser
{
public bool RequiresEmailConfirmation { get; set; }
public List<StoredFile> StoredFiles { get; set; }
@@ -22,28 +20,15 @@ namespace BTCPayServer.Data
public List<UserStore> UserStores { get; set; }
public List<Fido2Credential> Fido2Credentials { get; set; }
[Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }
public string Blob2 { get; set; }
public List<IdentityUserRole<string>> UserRoles { get; set; }
public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
public static void OnModelCreating(ModelBuilder builder)
{
builder.Entity<ApplicationUser>()
.HasMany<IdentityUserRole<string>>(user => user.UserRoles)
.WithOne().HasForeignKey(role => role.UserId);
if (databaseFacade.IsNpgsql())
{
builder.Entity<ApplicationUser>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
}
}
}
public class UserBlob
{
public bool ShowInvoiceStatusChangeHint { get; set; }
}
}

View File

@@ -1,13 +1,11 @@
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
namespace BTCPayServer.Data;
public class CustodianAccountData : IHasBlob<JObject>
public class CustodianAccountData
{
[Required]
[MaxLength(50)]
@@ -16,39 +14,29 @@ public class CustodianAccountData : IHasBlob<JObject>
[Required]
[MaxLength(50)]
public string StoreId { get; set; }
[Required]
[MaxLength(50)]
public string CustodianCode { get; set; }
[Required]
[MaxLength(50)]
public string Name { get; set; }
[JsonIgnore]
[Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }
[JsonIgnore]
public string Blob2 { get; set; }
[JsonIgnore]
public StoreData StoreData { get; set; }
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
internal static void OnModelCreating(ModelBuilder builder)
{
builder.Entity<CustodianAccountData>()
.HasOne(o => o.StoreData)
.WithMany(i => i.CustodianAccounts)
.HasForeignKey(i => i.StoreId).OnDelete(DeleteBehavior.Cascade);
builder.Entity<CustodianAccountData>()
builder.Entity<APIKeyData>()
.HasIndex(o => o.StoreId);
if (databaseFacade.IsNpgsql())
{
builder.Entity<CustodianAccountData>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
}
}
}

View File

@@ -2,11 +2,10 @@ using System;
using System.ComponentModel.DataAnnotations;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace BTCPayServer.Data
{
public class Fido2Credential : IHasBlobUntyped
public class Fido2Credential
{
public string Name { get; set; }
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
@@ -15,7 +14,6 @@ namespace BTCPayServer.Data
public string ApplicationUserId { get; set; }
public byte[] Blob { get; set; }
public string Blob2 { get; set; }
public CredentialType Type { get; set; }
public enum CredentialType
{
@@ -24,18 +22,12 @@ namespace BTCPayServer.Data
[Display(Name = "Lightning node (LNURL Auth)")]
LNURLAuth
}
public static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
public static void OnModelCreating(ModelBuilder builder)
{
builder.Entity<Fido2Credential>()
.HasOne(o => o.ApplicationUser)
.WithMany(i => i.Fido2Credentials)
.HasForeignKey(i => i.ApplicationUserId).OnDelete(DeleteBehavior.Cascade);
if (databaseFacade.IsNpgsql())
{
builder.Entity<Fido2Credential>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
}
}
public ApplicationUser ApplicationUser { get; set; }

View File

@@ -2,30 +2,11 @@ using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace BTCPayServer.Data;
namespace BTCPayServer.Data.Data;
public class FormData
{
[DatabaseGenerated(DatabaseGeneratedOption.Identity)]
public string Id { get; set; }
public string Name { get; set; }
public string StoreId { get; set; }
public StoreData Store { get; set; }
public string Config { get; set; }
public bool Public { get; set; }
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
{
builder.Entity<FormData>()
.HasOne(o => o.Store)
.WithMany(o => o.Forms).OnDelete(DeleteBehavior.Cascade);
builder.Entity<FormData>().HasIndex(o => o.StoreId);
if (databaseFacade.IsNpgsql())
{
builder.Entity<FormData>()
.Property(o => o.Config)
.HasColumnType("JSONB");
}
}
}

View File

@@ -1,28 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace BTCPayServer.Data
{
public interface IHasBlob<T>
{
[Obsolete("Use Blob2 instead")]
byte[] Blob { get; set; }
string Blob2 { get; set; }
}
public interface IHasBlob
{
[Obsolete("Use Blob2 instead")]
byte[] Blob { get; set; }
string Blob2 { get; set; }
public Type Type { get; set; }
}
public interface IHasBlobUntyped
{
[Obsolete("Use Blob2 instead")]
byte[] Blob { get; set; }
string Blob2 { get; set; }
}
}

View File

@@ -2,11 +2,10 @@ using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations.Schema;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
namespace BTCPayServer.Data
{
public class InvoiceData : IHasBlobUntyped
public class InvoiceData
{
public string Id { get; set; }
@@ -17,9 +16,7 @@ namespace BTCPayServer.Data
public List<PaymentData> Payments { get; set; }
public List<InvoiceEventData> Events { get; set; }
[Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }
public string Blob2 { get; set; }
public string ItemCode { get; set; }
public string OrderId { get; set; }
public string Status { get; set; }
@@ -35,7 +32,7 @@ namespace BTCPayServer.Data
public RefundData CurrentRefund { get; set; }
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
internal static void OnModelCreating(ModelBuilder builder)
{
builder.Entity<InvoiceData>()
.HasOne(o => o.StoreData)
@@ -45,13 +42,6 @@ namespace BTCPayServer.Data
builder.Entity<InvoiceData>()
.HasOne(o => o.CurrentRefund);
builder.Entity<InvoiceData>().HasIndex(o => o.Created);
if (databaseFacade.IsNpgsql())
{
builder.Entity<InvoiceData>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
}
}
}
}

View File

@@ -1,22 +1,17 @@
using System;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Newtonsoft.Json.Linq;
using Microsoft.EntityFrameworkCore;
namespace BTCPayServer.Data;
public class LightningAddressData : IHasBlob<LightningAddressDataBlob>
public class LightningAddressData
{
public string Username { get; set; }
public string StoreDataId { get; set; }
[Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }
public string Blob2 { get; set; }
public StoreData Store { get; set; }
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
internal static void OnModelCreating(ModelBuilder builder)
{
builder.Entity<LightningAddressData>()
.HasOne(o => o.Store)
@@ -25,12 +20,6 @@ public class LightningAddressData : IHasBlob<LightningAddressDataBlob>
.IsRequired()
.OnDelete(DeleteBehavior.Cascade);
builder.Entity<LightningAddressData>().HasKey(o => o.Username);
if (databaseFacade.IsNpgsql())
{
builder.Entity<LightningAddressData>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
}
}
}
@@ -39,6 +28,4 @@ public class LightningAddressDataBlob
public string CurrencyCode { get; set; }
public decimal? Min { get; set; }
public decimal? Max { get; set; }
public JObject InvoiceMetadata { get; set; }
}

View File

@@ -1,12 +1,10 @@
using System;
using System.ComponentModel.DataAnnotations;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Infrastructure;
using Microsoft.EntityFrameworkCore.Storage;
namespace BTCPayServer.Data
{
public class NotificationData : IHasBlobUntyped
public class NotificationData
{
[MaxLength(36)]
public string Id { get; set; }
@@ -19,23 +17,15 @@ namespace BTCPayServer.Data
[Required]
public string NotificationType { get; set; }
public bool Seen { get; set; }
[Obsolete("Use Blob2 instead")]
public byte[] Blob { get; set; }
public string Blob2 { get; set; }
internal static void OnModelCreating(ModelBuilder builder, DatabaseFacade databaseFacade)
internal static void OnModelCreating(ModelBuilder builder)
{
builder.Entity<NotificationData>()
.HasOne(o => o.ApplicationUser)
.WithMany(n => n.Notifications)
.HasForeignKey(k => k.ApplicationUserId).OnDelete(DeleteBehavior.Cascade);
if (databaseFacade.IsNpgsql())
{
builder.Entity<NotificationData>()
.Property(o => o.Blob2)
.HasColumnType("JSONB");
}
}
}
}

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