mirror of
https://github.com/aljazceru/BTCPayServerPlugins.git
synced 2025-12-17 07:34:24 +01:00
wip
This commit is contained in:
@@ -83,8 +83,8 @@ Global
|
|||||||
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{B19C9F52-DC47-466D-8B5C-2D202B7B003F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AD9635BB-C70E-4676-BB04-900D51B01666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{AD9635BB-C70E-4676-BB04-900D51B01666}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{AD9635BB-C70E-4676-BB04-900D51B01666}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{AD9635BB-C70E-4676-BB04-900D51B01666}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{AD9635BB-C70E-4676-BB04-900D51B01666}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{AD9635BB-C70E-4676-BB04-900D51B01666}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -99,48 +99,48 @@ Global
|
|||||||
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{8F158B88-0FEE-44FF-8552-7C0F17D5C508}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Release|Any CPU.Build.0 = Release|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{DF85EFA4-0EF5-4A99-853F-E6F9C88E3F8C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Release|Any CPU.Build.0 = Release|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{2C5C4DF9-BA1F-4671-9F24-B22D7C9C3D21}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{D7E7309D-C4F4-496A-B2C8-BC5D3991B9C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Release|Any CPU.Build.0 = Release|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{3F2E0BA0-9EA7-490F-894D-F9703F35B174}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{6295533A-F941-40CA-B889-FE6C0432ED53}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{58863D86-3C78-4BEC-ACB6-2F82CC141210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{58863D86-3C78-4BEC-ACB6-2F82CC141210}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{58863D86-3C78-4BEC-ACB6-2F82CC141210}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{58863D86-3C78-4BEC-ACB6-2F82CC141210}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{58863D86-3C78-4BEC-ACB6-2F82CC141210}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{58863D86-3C78-4BEC-ACB6-2F82CC141210}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
@@ -155,8 +155,8 @@ Global
|
|||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.ActiveCfg = Altcoins-Release|Any CPU
|
||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Altcoins-Release|Any CPU.Build.0 = Altcoins-Release|Any CPU
|
||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Debug|Any CPU.ActiveCfg = Altcoins-Debug|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Debug|Any CPU.Build.0 = Altcoins-Debug|Any CPU
|
{B4E2ED08-4AD3-4648-8BDB-3107200460B9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{5E1BAA06-7828-47BC-89D6-19C2A78EA427}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
|||||||
@@ -1,7 +1,21 @@
|
|||||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=0D438B7D_002DF996_002D4BF3_002D8F54_002D02CB9DF120D8_002Ff_003ABTCPayCoinjoinCoinSelector_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=0D438B7D_002DF996_002D4BF3_002D8F54_002D02CB9DF120D8_002Ff_003ABTCPayCoinjoinCoinSelector_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=0D438B7D_002DF996_002D4BF3_002D8F54_002D02CB9DF120D8_002Ff_003ABTCPayWallet_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=0D438B7D_002DF996_002D4BF3_002D8F54_002D02CB9DF120D8_002Ff_003ABTCPayWallet_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABreezEvent_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F19b2ba64aa6844efb3312f86dbfe1b9652000_003F63_003F83f9cdbb_003FBreezEvent_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABreezSdkLiquidMethods_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4dbc7b5c57d04ec8a063235af9eb203a3fc00_003F7e_003F6a527844_003FBreezSdkLiquidMethods_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABreez_002ESdk_002ELiquid_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fmetadata_003F4dbc7b5c57d04ec8a063235af9eb203a3fc00_003F58_003F0584d9dc_003FBreez_002ESdk_002ELiquid_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ABreez_002ESdk_002ELiquid_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fmetadata_003F4dbc7b5c57d04ec8a063235af9eb203a3fc00_003F58_003F0584d9dc_003FBreez_002ESdk_002ELiquid_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ACallSiteFactory_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Ff7e838f3c047ee76488fa4c2b9b1bffb2b33b04a2780de4664de937e024e97_003FCallSiteFactory_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ADbSet_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F4b21fc3f8a3abb5d25f06c622276fbec0fd3932f169cc6af520bf5abc6a46b4_003FDbSet_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FLocal_003FSymbols_003Fsrc_003Fdotnet_003Fruntime_003F08338fcaa5c9b9a8190abb99222fed12aaba956c_003Fsrc_003Flibraries_003FSystem_002EPrivate_002ECoreLib_003Fsrc_003FSystem_003FRuntime_003FExceptionServices_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AExceptionDispatchInfo_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fbd1d5c50194fea68ff3559c160230b0ab50f5acf4ce3061bffd6d62958e2182_003FExceptionDispatchInfo_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANostrClientPool_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F758d2546736f41ac5ee3998f9abad1f58b82254824f2532c89ddf667ed74_003FNostrClientPool_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANostrEventTag_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Ff2e2e45db36b5d75d466cd5c6134e5ce566eface233da2ec472ac018f2eb16_003FNostrEventTag_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANullable_00601_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F2a3105e7355248488912e34f9ff5cbebca718_003F8b_003Fd6fc9706_003FNullable_00601_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003ANullReferenceException_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fc092928882a17a51a62a367685d90a0a613eb91fb453b9f50147e19c1f3ff40_003FNullReferenceException_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APaymentDetails_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4dbc7b5c57d04ec8a063235af9eb203a3fc00_003Fc6_003Fb76207e1_003FPaymentDetails_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003APayment_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FDecompilerCache_003Fdecompiler_003F4dbc7b5c57d04ec8a063235af9eb203a3fc00_003F5b_003F56fb0a4a_003FPayment_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AToCollection_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003Fbd47ee1ab214a7674f381fb716d273cc4bb64441375b47417e9dcd5ec96f89_003FToCollection_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=7020124F_002D9FFC_002D4AC3_002D8F3D_002DAAB8E0240759_002Ff_003AWhere_002Ecs_002Fl_003A_002E_002E_003F_002E_002E_003FUsers_003Fevilk_003FAppData_003FRoaming_003FJetBrains_003FRider2024_002E2_003Fresharper_002Dhost_003FSourcesCache_003F767db1e17d404f86c3c73c54c6b20b5ff9ec43b79ef47681ae34b40a6852cf9_003FWhere_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D1D1116C_002D38F9_002D4EA3_002DAC65_002DA75FEA82E5C8_002Fd_003ABlockchain_002Fd_003ATransactionOutputs_002Ff_003ACoinsView_002Ecs/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D1D1116C_002D38F9_002D4EA3_002DAC65_002DA75FEA82E5C8_002Fd_003ABlockchain_002Fd_003ATransactionOutputs_002Ff_003ACoinsView_002Ecs/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D1D1116C_002D38F9_002D4EA3_002DAC65_002DA75FEA82E5C8_002Fd_003ABlockchain_002Fd_003ATransactionOutputs_002Ff_003ASmartCoin_002Ecs/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D1D1116C_002D38F9_002D4EA3_002DAC65_002DA75FEA82E5C8_002Fd_003ABlockchain_002Fd_003ATransactionOutputs_002Ff_003ASmartCoin_002Ecs/@EntryIndexedValue">ExplicitlyExcluded</s:String>
|
||||||
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D1D1116C_002D38F9_002D4EA3_002DAC65_002DA75FEA82E5C8_002Fd_003AWabiSabi_002Fd_003AClient_002Ff_003ACoinJoinClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
<s:String x:Key="/Default/CodeInspection/ExcludedFiles/FilesAndFoldersToSkip2/=D1D1116C_002D38F9_002D4EA3_002DAC65_002DA75FEA82E5C8_002Fd_003AWabiSabi_002Fd_003AClient_002Ff_003ACoinJoinClient_002Ecs/@EntryIndexedValue">ForceIncluded</s:String>
|
||||||
@@ -50,6 +64,7 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nostr/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Nostr/@EntryIndexedValue">True</s:Boolean></wpf:ResourceDictionary>
|
||||||
@@ -10,7 +10,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Bitcoin Whitepaper</Product>
|
<Product>Bitcoin Whitepaper</Product>
|
||||||
<Description>This makes the Bitcoin whitepaper available on your BTCPay Server.</Description>
|
<Description>This makes the Bitcoin whitepaper available on your BTCPay Server.</Description>
|
||||||
<Version>1.0.4</Version>
|
<Version>1.0.5</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ namespace BTCPayServer.Plugins.BitcoinWhitepaper
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.12.0" }
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Blink</Product>
|
<Product>Blink</Product>
|
||||||
<Description>Blink Lightning support</Description>
|
<Description>Blink Lightning support</Description>
|
||||||
<Version>1.0.8</Version>
|
<Version>1.0.9</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
<RootNamespace>BTCPayServer.Plugins.Blink</RootNamespace>
|
<RootNamespace>BTCPayServer.Plugins.Blink</RootNamespace>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace BTCPayServer.Plugins.Blink
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.12.0"}
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Breez / Greenlight</Product>
|
<Product>Breez / Greenlight</Product>
|
||||||
<Description>Lightweight lightning baby!</Description>
|
<Description>Lightweight lightning baby!</Description>
|
||||||
<Version>1.0.8</Version>
|
<Version>1.0.9</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
@@ -34,7 +34,7 @@
|
|||||||
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Breez.Sdk" Version="0.5.2" />
|
<PackageReference Include="Breez.Sdk" Version="0.6.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.IO.Compression;
|
using System.IO.Compression;
|
||||||
using System.Linq;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Breez.Sdk;
|
using Breez.Sdk;
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
@@ -12,13 +11,13 @@ using BTCPayServer.Lightning;
|
|||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBitcoin.DataEncoders;
|
using NBitcoin.DataEncoders;
|
||||||
using NBXplorer.DerivationStrategy;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Breez;
|
namespace BTCPayServer.Plugins.Breez;
|
||||||
|
|
||||||
@@ -26,15 +25,19 @@ namespace BTCPayServer.Plugins.Breez;
|
|||||||
[Route("plugins/{storeId}/Breez")]
|
[Route("plugins/{storeId}/Breez")]
|
||||||
public class BreezController : Controller
|
public class BreezController : Controller
|
||||||
{
|
{
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
private readonly BreezService _breezService;
|
private readonly BreezService _breezService;
|
||||||
private readonly BTCPayWalletProvider _btcWalletProvider;
|
private readonly BTCPayWalletProvider _btcWalletProvider;
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
|
|
||||||
public BreezController(BTCPayNetworkProvider btcPayNetworkProvider,
|
public BreezController(
|
||||||
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
BreezService breezService,
|
BreezService breezService,
|
||||||
BTCPayWalletProvider btcWalletProvider, StoreRepository storeRepository)
|
BTCPayWalletProvider btcWalletProvider, StoreRepository storeRepository)
|
||||||
{
|
{
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
_breezService = breezService;
|
_breezService = breezService;
|
||||||
_btcWalletProvider = btcWalletProvider;
|
_btcWalletProvider = btcWalletProvider;
|
||||||
@@ -113,7 +116,7 @@ public class BreezController : Controller
|
|||||||
if (address.Equals("store", StringComparison.InvariantCultureIgnoreCase))
|
if (address.Equals("store", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
var store = ControllerContext.HttpContext.GetStoreData()
|
var store = ControllerContext.HttpContext.GetStoreData()
|
||||||
.GetDerivationSchemeSettings(_btcPayNetworkProvider, "BTC");
|
.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, "BTC");
|
||||||
var res = await _btcWalletProvider.GetWallet(storeId)
|
var res = await _btcWalletProvider.GetWallet(storeId)
|
||||||
.ReserveAddressAsync(storeId, store.AccountDerivation, "Breez");
|
.ReserveAddressAsync(storeId, store.AccountDerivation, "Breez");
|
||||||
address = res.Address.ToString();
|
address = res.Address.ToString();
|
||||||
@@ -264,7 +267,7 @@ public class BreezController : Controller
|
|||||||
if (address.Equals("store", StringComparison.InvariantCultureIgnoreCase))
|
if (address.Equals("store", StringComparison.InvariantCultureIgnoreCase))
|
||||||
{
|
{
|
||||||
var store = ControllerContext.HttpContext.GetStoreData()
|
var store = ControllerContext.HttpContext.GetStoreData()
|
||||||
.GetDerivationSchemeSettings(_btcPayNetworkProvider, "BTC");
|
.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, "BTC");
|
||||||
var res = await _btcWalletProvider.GetWallet(storeId)
|
var res = await _btcWalletProvider.GetWallet(storeId)
|
||||||
.ReserveAddressAsync(storeId, store.AccountDerivation, "Breez");
|
.ReserveAddressAsync(storeId, store.AccountDerivation, "Breez");
|
||||||
address = res.Address.ToString();
|
address = res.Address.ToString();
|
||||||
@@ -342,10 +345,8 @@ public class BreezController : Controller
|
|||||||
public async Task<IActionResult> Configure(string storeId, string command, BreezSettings settings)
|
public async Task<IActionResult> Configure(string storeId, string command, BreezSettings settings)
|
||||||
{
|
{
|
||||||
var store = HttpContext.GetStoreData();
|
var store = HttpContext.GetStoreData();
|
||||||
var existing = store.GetSupportedPaymentMethods(_btcPayNetworkProvider).OfType<LightningSupportedPaymentMethod>()
|
var pmi = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||||
.FirstOrDefault(method =>
|
var existing = store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary);
|
||||||
method.PaymentId.PaymentType == LightningPaymentType.Instance &&
|
|
||||||
method.PaymentId.CryptoCode == "BTC");
|
|
||||||
|
|
||||||
if (command == "clear")
|
if (command == "clear")
|
||||||
{
|
{
|
||||||
@@ -355,7 +356,7 @@ public class BreezController : Controller
|
|||||||
var isStoreSetToThisMicro = existing?.GetExternalLightningUrl() == client?.ToString();
|
var isStoreSetToThisMicro = existing?.GetExternalLightningUrl() == client?.ToString();
|
||||||
if (client is not null && isStoreSetToThisMicro)
|
if (client is not null && isStoreSetToThisMicro)
|
||||||
{
|
{
|
||||||
store.SetSupportedPaymentMethod(existing.PaymentId, null);
|
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], null);
|
||||||
await _storeRepository.UpdateStore(store);
|
await _storeRepository.UpdateStore(store);
|
||||||
}
|
}
|
||||||
return RedirectToAction(nameof(Configure), new {storeId});
|
return RedirectToAction(nameof(Configure), new {storeId});
|
||||||
@@ -422,18 +423,13 @@ public class BreezController : Controller
|
|||||||
|
|
||||||
if(existing is null)
|
if(existing is null)
|
||||||
{
|
{
|
||||||
existing = new LightningSupportedPaymentMethod()
|
|
||||||
{
|
existing = new LightningPaymentMethodConfig();
|
||||||
CryptoCode = "BTC"
|
|
||||||
};
|
|
||||||
var client = _breezService.GetClient(storeId);
|
var client = _breezService.GetClient(storeId);
|
||||||
existing.SetLightningUrl(client);
|
existing.SetLightningUrl(client);
|
||||||
store.SetSupportedPaymentMethod(existing);
|
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], existing);
|
||||||
var lnurl = new LNURLPaySupportedPaymentMethod()
|
var lnurlPMI = PaymentTypes.LNURL.GetPaymentMethodId("BTC");
|
||||||
{
|
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[lnurlPMI], new LNURLPaymentMethodConfig());
|
||||||
CryptoCode = "BTC",
|
|
||||||
};
|
|
||||||
store.SetSupportedPaymentMethod(lnurl);
|
|
||||||
await _storeRepository.UpdateStore(store);
|
await _storeRepository.UpdateStore(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -252,7 +252,7 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
OffchainBalance = new OffchainBalance()
|
OffchainBalance = new OffchainBalance()
|
||||||
{
|
{
|
||||||
Local = LightMoney.MilliSatoshis(ni.channelsBalanceMsat),
|
Local = LightMoney.MilliSatoshis(ni.channelsBalanceMsat),
|
||||||
Remote = LightMoney.MilliSatoshis(ni.inboundLiquidityMsats),
|
Remote = LightMoney.MilliSatoshis(ni.totalInboundLiquidityMsats),
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,7 @@ public class BreezLightningClient : ILightningClient, IDisposable, EventListener
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
result = Sdk.SendPayment(new SendPaymentRequest(bolt11, (ulong?) payParams.Amount?.MilliSatoshi));
|
result = Sdk.SendPayment(new SendPaymentRequest(bolt11,false, (ulong?) payParams.Amount?.MilliSatoshi));
|
||||||
}
|
}
|
||||||
|
|
||||||
var details = result.payment.details as PaymentDetails.Ln;
|
var details = result.payment.details as PaymentDetails.Ln;
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace BTCPayServer.Plugins.Breez
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.13.2" }
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ using BTCPayServer.Events;
|
|||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
@@ -22,7 +24,8 @@ public class BreezService:EventHostedServiceBase
|
|||||||
{
|
{
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
private readonly IOptions<DataDirectories> _dataDirectories;
|
private readonly IOptions<DataDirectories> _dataDirectories;
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly IServiceProvider _serviceProvider;
|
||||||
|
private PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary => _serviceProvider.GetRequiredService<PaymentMethodHandlerDictionary>();
|
||||||
private readonly ILogger _logger;
|
private readonly ILogger _logger;
|
||||||
private Dictionary<string, BreezSettings> _settings;
|
private Dictionary<string, BreezSettings> _settings;
|
||||||
private Dictionary<string, BreezLightningClient> _clients = new();
|
private Dictionary<string, BreezLightningClient> _clients = new();
|
||||||
@@ -31,12 +34,12 @@ public class BreezService:EventHostedServiceBase
|
|||||||
EventAggregator eventAggregator,
|
EventAggregator eventAggregator,
|
||||||
StoreRepository storeRepository,
|
StoreRepository storeRepository,
|
||||||
IOptions<DataDirectories> dataDirectories,
|
IOptions<DataDirectories> dataDirectories,
|
||||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
IServiceProvider serviceProvider,
|
||||||
ILogger<BreezService> logger) : base(eventAggregator, logger)
|
ILogger<BreezService> logger) : base(eventAggregator, logger)
|
||||||
{
|
{
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
_dataDirectories = dataDirectories;
|
_dataDirectories = dataDirectories;
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
_serviceProvider = serviceProvider;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,13 +136,13 @@ public class BreezService:EventHostedServiceBase
|
|||||||
{
|
{
|
||||||
_settings.Remove(storeId, out var oldSettings );
|
_settings.Remove(storeId, out var oldSettings );
|
||||||
var data = await _storeRepository.FindStore(storeId);
|
var data = await _storeRepository.FindStore(storeId);
|
||||||
var existing = data?.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
var pmi = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||||
.OfType<LightningSupportedPaymentMethod>().FirstOrDefault(method =>
|
var existing =
|
||||||
method.CryptoCode == "BTC" && method.PaymentId.PaymentType == LightningPaymentType.Instance);
|
data?.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary);
|
||||||
var isBreez = existing?.GetExternalLightningUrl() == $"type=breez;key={oldSettings.PaymentKey}";
|
var isBreez = existing?.GetExternalLightningUrl() == $"type=breez;key={oldSettings.PaymentKey}";
|
||||||
if (isBreez)
|
if (isBreez)
|
||||||
{
|
{
|
||||||
data.SetSupportedPaymentMethod(new PaymentMethodId("BTC", LightningPaymentType.Instance), null );
|
data.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], null );
|
||||||
await _storeRepository.UpdateStore(data);
|
await _storeRepository.UpdateStore(data);
|
||||||
}
|
}
|
||||||
Directory.Delete(GetWorkDir(storeId), true);
|
Directory.Delete(GetWorkDir(storeId), true);
|
||||||
|
|||||||
@@ -1,7 +1,5 @@
|
|||||||
@using Breez.Sdk
|
@using Breez.Sdk
|
||||||
@using BTCPayServer
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
|
||||||
@using BTCPayServer.Abstractions.Contracts
|
|
||||||
@using BTCPayServer.Client
|
@using BTCPayServer.Client
|
||||||
@using BTCPayServer.Components.QRCode
|
@using BTCPayServer.Components.QRCode
|
||||||
@using BTCPayServer.Components.TruncateCenter
|
@using BTCPayServer.Components.TruncateCenter
|
||||||
@@ -10,13 +8,15 @@
|
|||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
@using BTCPayServer.Services
|
@using BTCPayServer.Services
|
||||||
|
@using BTCPayServer.Services.Invoices
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@using NBitcoin
|
@using NBitcoin
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
|
||||||
@inject TransactionLinkProviders TransactionLinkProviders
|
@inject TransactionLinkProviders TransactionLinkProviders
|
||||||
|
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||||
@{
|
@{
|
||||||
ViewData.SetActivePage("Breez", "Swap In", "SwapIn");
|
ViewData.SetActivePage("Breez", "Swap In", "SwapIn");
|
||||||
|
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("BTC");
|
||||||
string storeId = Model switch
|
string storeId = Model switch
|
||||||
{
|
{
|
||||||
string s => s,
|
string s => s,
|
||||||
@@ -38,10 +38,9 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
var refundables = sdk.ListRefundables();
|
var refundables = sdk.ListRefundables();
|
||||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(PaymentMethodHandlerDictionary, "BTC");
|
||||||
var ni = sdk.NodeInfo();
|
var ni = sdk.NodeInfo();
|
||||||
var f = sdk.RecommendedFees();
|
var f = sdk.RecommendedFees();
|
||||||
var pmi = new PaymentMethodId("BTC", PaymentTypes.BTCLike);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
<datalist id="fees">
|
<datalist id="fees">
|
||||||
|
|||||||
@@ -1,18 +1,18 @@
|
|||||||
@using BTCPayServer
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
|
||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
|
@using BTCPayServer.Services.Invoices
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@using Microsoft.AspNetCore.Routing
|
@using Microsoft.AspNetCore.Routing
|
||||||
@model string
|
@model string
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||||
@{
|
@{
|
||||||
var storeId = Context.GetImplicitStoreId();
|
var storeId = Context.GetImplicitStoreId();
|
||||||
var address = Context.GetRouteValue("address").ToString();
|
var address = Context.GetRouteValue("address").ToString();
|
||||||
ViewData.SetActivePage("Breez", "Create Swapin Refund", "SwapIn");
|
ViewData.SetActivePage("Breez", "Create Swapin Refund", "SwapIn");
|
||||||
|
|
||||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(PaymentMethodHandlerDictionary, "BTC");
|
||||||
var sdk = BreezService.GetClient(storeId)?.Sdk;
|
var sdk = BreezService.GetClient(storeId)?.Sdk;
|
||||||
var f = sdk.RecommendedFees();
|
var f = sdk.RecommendedFees();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
@using Breez.Sdk
|
@using Breez.Sdk
|
||||||
@using BTCPayServer
|
@using BTCPayServer
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
|
||||||
@using BTCPayServer.Models.StoreViewModels
|
@using BTCPayServer.Models.StoreViewModels
|
||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
|
@using BTCPayServer.Services.Invoices
|
||||||
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||||
|
|
||||||
|
|
||||||
@{
|
@{
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
if (sdk is null)
|
if (sdk is null)
|
||||||
return;
|
return;
|
||||||
var inProgressSwaps = sdk.InProgressReverseSwaps();
|
var inProgressSwaps = sdk.InProgressReverseSwaps();
|
||||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(PaymentMethodHandlerDictionary, "BTC");
|
||||||
var f = sdk.RecommendedFees();
|
var f = sdk.RecommendedFees();
|
||||||
var swapOutRec = sdk.FetchReverseSwapFees(new ReverseSwapFeesRequest());
|
var swapOutRec = sdk.FetchReverseSwapFees(new ReverseSwapFeesRequest());
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,9 +2,10 @@
|
|||||||
@using BTCPayServer.Models.StoreViewModels
|
@using BTCPayServer.Models.StoreViewModels
|
||||||
@using BTCPayServer.Plugins.Breez
|
@using BTCPayServer.Plugins.Breez
|
||||||
@using BTCPayServer.Security
|
@using BTCPayServer.Security
|
||||||
|
@using BTCPayServer.Services.Invoices
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@inject BreezService BreezService
|
@inject BreezService BreezService
|
||||||
@inject BTCPayNetworkProvider BtcPayNetworkProvider
|
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||||
@{
|
@{
|
||||||
Layout = "_Layout";
|
Layout = "_Layout";
|
||||||
ViewData.SetActivePage("Breez", "Sweep", "Sweep");
|
ViewData.SetActivePage("Breez", "Sweep", "Sweep");
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
var sdk = BreezService.GetClient(storeId)?.Sdk;
|
var sdk = BreezService.GetClient(storeId)?.Sdk;
|
||||||
if (sdk is null)
|
if (sdk is null)
|
||||||
return;
|
return;
|
||||||
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(BtcPayNetworkProvider, "BTC");
|
var deriv = Context.GetStoreData().GetDerivationSchemeSettings(PaymentMethodHandlerDictionary, "BTC");
|
||||||
var f = sdk.RecommendedFees();
|
var f = sdk.RecommendedFees();
|
||||||
}
|
}
|
||||||
<datalist id="fees">
|
<datalist id="fees">
|
||||||
|
|||||||
@@ -1,10 +0,0 @@
|
|||||||
@{
|
|
||||||
Layout = "../Shared/_NavLayout.cshtml";
|
|
||||||
ViewData["NavPartialName"] = "_Nav";
|
|
||||||
}
|
|
||||||
<style>
|
|
||||||
#mainContent > section {
|
|
||||||
padding: 3rem !important;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@RenderBody()
|
|
||||||
@@ -1,41 +0,0 @@
|
|||||||
@using BTCPayServer.Abstractions.Extensions
|
|
||||||
@using BTCPayServer.Client
|
|
||||||
@using BTCPayServer.Models.StoreViewModels
|
|
||||||
@using BTCPayServer.Plugins.Breez
|
|
||||||
@using BTCPayServer.Security
|
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
||||||
|
|
||||||
@inject BreezService BreezService
|
|
||||||
@{
|
|
||||||
var storeId = Model switch
|
|
||||||
{
|
|
||||||
string s => s,
|
|
||||||
StoreDashboardViewModel dashboardModel => dashboardModel.StoreId,
|
|
||||||
_ => Context.GetImplicitStoreId()
|
|
||||||
};
|
|
||||||
var client = BreezService.GetClient(storeId);
|
|
||||||
var sdk = client?.Sdk;
|
|
||||||
}
|
|
||||||
|
|
||||||
<div class="sticky-header-setup"></div>
|
|
||||||
<div class="sticky-header mb-l">
|
|
||||||
<h2 class="mt-1 mb-2 mb-lg-4">Breez / Greenlight</h2>
|
|
||||||
@if (sdk is not null)
|
|
||||||
{
|
|
||||||
<nav id="SectionNav">
|
|
||||||
<div class="nav">
|
|
||||||
|
|
||||||
<a permission="@Policies.CanViewStoreSettings" asp-action="Info" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Info")">Info</a>
|
|
||||||
<a permission="@Policies.CanViewStoreSettings" asp-action="Payments" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Payments")">Payments</a>
|
|
||||||
<a permission="@Policies.CanCreateInvoice" asp-action="SwapIn" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapIn")">Swap In</a>
|
|
||||||
<a permission="@Policies.CanModifyStoreSettings" asp-action="SwapOut" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapOut")">Swap Out</a>
|
|
||||||
|
|
||||||
<a permission="@Policies.CanModifyStoreSettings" asp-action="Configure" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Configure")">Configuration</a>
|
|
||||||
@if (client.Events.Any())
|
|
||||||
{
|
|
||||||
<a permission="@Policies.CanViewStoreSettings" asp-action="Logs" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Logs")">Logs</a>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
</nav>
|
|
||||||
}
|
|
||||||
</div>
|
|
||||||
@@ -1,15 +1,28 @@
|
|||||||
|
@using Breez.Sdk
|
||||||
@using BTCPayServer.Abstractions.Contracts
|
@using BTCPayServer.Abstractions.Contracts
|
||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
@using BTCPayServer.Client
|
@using BTCPayServer.Client
|
||||||
|
@using BTCPayServer.Models.StoreViewModels
|
||||||
|
@using BTCPayServer.Plugins.Breez
|
||||||
|
@using BTCPayServer.Security
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@inject IScopeProvider ScopeProvider
|
@inject IScopeProvider ScopeProvider
|
||||||
|
@inject BreezService BreezService
|
||||||
@{
|
@{
|
||||||
var storeId = ScopeProvider.GetCurrentStoreId();
|
var storeId = Model switch
|
||||||
|
{
|
||||||
|
string s => s,
|
||||||
|
StoreDashboardViewModel dashboardModel => dashboardModel.StoreId,
|
||||||
|
_ => Context.GetImplicitStoreId()
|
||||||
|
};
|
||||||
|
var active = @ViewData.IsActivePage("Breez");
|
||||||
|
var client = string.IsNullOrEmpty(active) ? null : BreezService.GetClient(storeId);
|
||||||
|
var sdk = client?.Sdk;
|
||||||
}
|
}
|
||||||
@if (!string.IsNullOrEmpty(storeId))
|
@if (!string.IsNullOrEmpty(storeId))
|
||||||
{
|
{
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a permission="@Policies.CanViewStoreSettings" asp-controller="Breez" asp-action="Index" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez")" id="Nav-Breez">
|
<a permission="@Policies.CanViewStoreSettings" asp-controller="Breez" asp-action="Index" asp-route-storeId="@storeId" class="nav-link @active" id="Nav-Breez">
|
||||||
|
|
||||||
<svg style="width: 15px; margin-left: 3px; margin-right: 7px;" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
<svg style="width: 15px; margin-left: 3px; margin-right: 7px;" viewBox="0 0 64 64" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
<g id="favicon-64-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
<g id="favicon-64-2" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd">
|
||||||
@@ -24,4 +37,31 @@
|
|||||||
<span>Breez</span>
|
<span>Breez</span>
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
|
||||||
|
@if (sdk is not null)
|
||||||
|
{
|
||||||
|
<li class="nav-item nav-item-sub">
|
||||||
|
|
||||||
|
<a permission="@Policies.CanViewStoreSettings" asp-action="Info" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Info")">Info</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item nav-item-sub">
|
||||||
|
<a permission="@Policies.CanViewStoreSettings" asp-action="Payments" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Payments")">Payments</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item nav-item-sub">
|
||||||
|
<a permission="@Policies.CanCreateInvoice" asp-action="SwapIn" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapIn")">Swap In</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item nav-item-sub">
|
||||||
|
<a permission="@Policies.CanModifyStoreSettings" asp-action="SwapOut" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "SwapOut")">Swap Out</a>
|
||||||
|
</li>
|
||||||
|
<li class="nav-item nav-item-sub">
|
||||||
|
|
||||||
|
<a permission="@Policies.CanModifyStoreSettings" asp-action="Configure" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Configure")">Configuration</a>
|
||||||
|
</li>
|
||||||
|
@if (client.Events.Any())
|
||||||
|
{
|
||||||
|
<li class="nav-item nav-item-sub">
|
||||||
|
<a permission="@Policies.CanViewStoreSettings" asp-action="Logs" asp-route-storeId="@storeId" class="nav-link @ViewData.IsActivePage("Breez", null, "Logs")">Logs</a>
|
||||||
|
</li>
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -103,7 +103,7 @@
|
|||||||
<span class="text-secondary fw-semibold currency">BTC receivable</span>
|
<span class="text-secondary fw-semibold currency">BTC receivable</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="balance d-flex align-items-baseline gap-1">
|
<div class="balance d-flex align-items-baseline gap-1">
|
||||||
<h3 class="d-inline-block me-1" data-balance="@LightMoney.MilliSatoshis(nodeState.inboundLiquidityMsats).ToUnit(LightMoneyUnit.BTC)" data-sensitive>@LightMoney.MilliSatoshis(nodeState.inboundLiquidityMsats).ToUnit(LightMoneyUnit.BTC)</h3>
|
<h3 class="d-inline-block me-1" data-balance="@LightMoney.MilliSatoshis(nodeState.totalInboundLiquidityMsats).ToUnit(LightMoneyUnit.BTC)" data-sensitive>@LightMoney.MilliSatoshis(nodeState.totalInboundLiquidityMsats).ToUnit(LightMoneyUnit.BTC)</h3>
|
||||||
<span class="text-secondary fw-semibold currency">BTC inbound liquidity</span>
|
<span class="text-secondary fw-semibold currency">BTC inbound liquidity</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="balance d-flex align-items-baseline gap-1">
|
<div class="balance d-flex align-items-baseline gap-1">
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Bringin</Product>
|
<Product>Bringin</Product>
|
||||||
<Description>Euro Offramp</Description>
|
<Description>Euro Offramp</Description>
|
||||||
<Version>1.0.1</Version>
|
<Version>1.0.2</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
@@ -41,6 +41,6 @@
|
|||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AsyncKeyedLock" Version="6.3.4" />
|
<PackageReference Include="AsyncKeyedLock" Version="7.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -11,7 +11,10 @@ public class BringinPlugin : BaseBTCPayServerPlugin
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.12.0"}
|
new()
|
||||||
|
{
|
||||||
|
Identifier = nameof(BTCPayServer), Condition = ">=2.0.0"
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ using BTCPayServer.Events;
|
|||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -139,13 +140,15 @@ public class BringinService : EventHostedServiceBase
|
|||||||
invoiceEvent when bringinStoreSettings.Enabled:
|
invoiceEvent when bringinStoreSettings.Enabled:
|
||||||
|
|
||||||
var pmPayments = invoiceEvent.Invoice.GetPayments("BTC", true)
|
var pmPayments = invoiceEvent.Invoice.GetPayments("BTC", true)
|
||||||
.GroupBy(payment => payment.GetPaymentMethodId());
|
.GroupBy(payment => payment.PaymentMethodId);
|
||||||
var update = false;
|
var update = false;
|
||||||
foreach (var pmPayment in pmPayments)
|
foreach (var pmPayment in pmPayments)
|
||||||
{
|
{
|
||||||
var methodId = pmPayment.Key;
|
var methodId = pmPayment.Key;
|
||||||
if (methodId.PaymentType == PaymentTypes.LNURLPay)
|
if (methodId == PaymentTypes.LNURL.GetPaymentMethodId("BTC"))
|
||||||
methodId = new PaymentMethodId(methodId.CryptoCode, PaymentTypes.LightningLike);
|
{
|
||||||
|
methodId = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||||
|
}
|
||||||
if (!bringinStoreSettings.MethodSettings.TryGetValue(methodId.ToString(),
|
if (!bringinStoreSettings.MethodSettings.TryGetValue(methodId.ToString(),
|
||||||
out var methodSettings))
|
out var methodSettings))
|
||||||
{
|
{
|
||||||
@@ -153,7 +156,7 @@ public class BringinService : EventHostedServiceBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
methodSettings.CurrentBalance +=
|
methodSettings.CurrentBalance +=
|
||||||
pmPayment.Sum(payment => payment.GetCryptoPaymentData().GetValue());
|
pmPayment.Sum(payment => payment.Value);
|
||||||
update = true;
|
update = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,14 +193,14 @@ public class BringinService : EventHostedServiceBase
|
|||||||
|
|
||||||
foreach (var methodSetting in bringinStoreSetting.MethodSettings)
|
foreach (var methodSetting in bringinStoreSetting.MethodSettings)
|
||||||
{
|
{
|
||||||
var pmi = PaymentMethodId.TryParse(methodSetting.Key);
|
var pmi = PayoutMethodId.TryParse(methodSetting.Key);
|
||||||
if (pmi is null)
|
if (pmi is null)
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
var isOnChain = PayoutTypes.CHAIN.GetPayoutMethodId("BTC") == pmi;
|
||||||
// if there is a pending payout, try and cancel it if this is onchain as we want to save needless tx fees
|
// if there is a pending payout, try and cancel it if this is onchain as we want to save needless tx fees
|
||||||
if (methodSetting.Value.PendingPayouts.Count > 0 && pmi.PaymentType == BitcoinPaymentType.Instance)
|
if (methodSetting.Value.PendingPayouts.Count > 0 && isOnChain)
|
||||||
{
|
{
|
||||||
var cancelResult = await _pullPaymentHostedService.Cancel(
|
var cancelResult = await _pullPaymentHostedService.Cancel(
|
||||||
new PullPaymentHostedService.CancelRequest(methodSetting.Value.PendingPayouts.ToArray(),
|
new PullPaymentHostedService.CancelRequest(methodSetting.Value.PendingPayouts.ToArray(),
|
||||||
@@ -252,16 +255,16 @@ public class BringinService : EventHostedServiceBase
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<string?> CreateOrder(string storeId, PaymentMethodId paymentMethodId, Money amountBtc, bool payout)
|
public async Task<string?> CreateOrder(string storeId, PayoutMethodId paymentMethodId, Money amountBtc, bool payout)
|
||||||
{
|
{
|
||||||
if (SupportedMethods.All(supportedMethod => supportedMethod.PaymentMethod != paymentMethodId))
|
if (SupportedMethods.All(supportedMethod => supportedMethod.PayoutMethod != paymentMethodId))
|
||||||
{
|
{
|
||||||
throw new NotSupportedException($"{paymentMethodId.ToPrettyString()} Payment method not supported");
|
throw new NotSupportedException($"{paymentMethodId} Payment method not supported");
|
||||||
|
|
||||||
}
|
}
|
||||||
var settings = _settings[storeId];
|
var settings = _settings[storeId];
|
||||||
|
|
||||||
var bringinClient = settings.CreateClient(_httpClientFactory, _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode).NBitcoinNetwork);
|
var bringinClient = settings.CreateClient(_httpClientFactory, _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>("BTC").NBitcoinNetwork);
|
||||||
|
|
||||||
|
|
||||||
var host = await Dns.GetHostEntryAsync(Dns.GetHostName(), CancellationToken.None);
|
var host = await Dns.GetHostEntryAsync(Dns.GetHostName(), CancellationToken.None);
|
||||||
@@ -270,7 +273,7 @@ public class BringinService : EventHostedServiceBase
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
var supportedMethod = SupportedMethods.First(supportedMethod => supportedMethod.PaymentMethod == paymentMethodId);
|
var supportedMethod = SupportedMethods.First(supportedMethod => supportedMethod.PayoutMethod == paymentMethodId);
|
||||||
//check if amount is enough
|
//check if amount is enough
|
||||||
if (supportedMethod.FiatMinimumAmount > 0)
|
if (supportedMethod.FiatMinimumAmount > 0)
|
||||||
{
|
{
|
||||||
@@ -297,13 +300,13 @@ public class BringinService : EventHostedServiceBase
|
|||||||
{
|
{
|
||||||
return order.Invoice?? order.DepositAddress;
|
return order.Invoice?? order.DepositAddress;
|
||||||
}
|
}
|
||||||
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>(paymentMethodId.CryptoCode);
|
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>("BTC");
|
||||||
|
|
||||||
var destination = !string.IsNullOrEmpty(order.Invoice)? (IClaimDestination) new BoltInvoiceClaimDestination(order.Invoice, BOLT11PaymentRequest.Parse(order.Invoice, network.NBitcoinNetwork)):
|
var destination = !string.IsNullOrEmpty(order.Invoice)? (IClaimDestination) new BoltInvoiceClaimDestination(order.Invoice, BOLT11PaymentRequest.Parse(order.Invoice, network.NBitcoinNetwork)):
|
||||||
new AddressClaimDestination(BitcoinAddress.Create(order.DepositAddress, network.NBitcoinNetwork));
|
new AddressClaimDestination(BitcoinAddress.Create(order.DepositAddress, network.NBitcoinNetwork));
|
||||||
var claim = await _pullPaymentHostedService.Claim(new ClaimRequest()
|
var claim = await _pullPaymentHostedService.Claim(new ClaimRequest()
|
||||||
{
|
{
|
||||||
PaymentMethodId = paymentMethodId,
|
PayoutMethodId = paymentMethodId,
|
||||||
StoreId = storeId,
|
StoreId = storeId,
|
||||||
Destination = destination,
|
Destination = destination,
|
||||||
Value = orderMoney.ToUnit(MoneyUnit.BTC),
|
Value = orderMoney.ToUnit(MoneyUnit.BTC),
|
||||||
@@ -363,17 +366,17 @@ public class BringinService : EventHostedServiceBase
|
|||||||
{
|
{
|
||||||
case PayoutState.Completed:
|
case PayoutState.Completed:
|
||||||
// remove from pending payouts list in a setting
|
// remove from pending payouts list in a setting
|
||||||
return _settings[payout.StoreDataId].MethodSettings[payout.GetPaymentMethodId().ToString()]
|
return _settings[payout.StoreDataId].MethodSettings[payout.GetPayoutMethodId().ToString()]
|
||||||
.PendingPayouts.Remove(payout.Id);
|
.PendingPayouts.Remove(payout.Id);
|
||||||
case PayoutState.Cancelled:
|
case PayoutState.Cancelled:
|
||||||
// remove from pending payouts list in a setting and add to a balance
|
// remove from pending payouts list in a setting and add to a balance
|
||||||
var result = _settings[payout.StoreDataId].MethodSettings[payout.GetPaymentMethodId().ToString()]
|
var result = _settings[payout.StoreDataId].MethodSettings[payout.GetPayoutMethodId().ToString()]
|
||||||
.PendingPayouts.Remove(payout.Id);
|
.PendingPayouts.Remove(payout.Id);
|
||||||
var pmi = payout.GetPaymentMethodId();
|
var pmi = payout.GetPayoutMethodId();
|
||||||
if (_settings[payout.StoreDataId].MethodSettings
|
if (_settings[payout.StoreDataId].MethodSettings
|
||||||
.TryGetValue(pmi.ToString(), out var methodSettings))
|
.TryGetValue(pmi.ToString(), out var methodSettings))
|
||||||
{
|
{
|
||||||
methodSettings.CurrentBalance += payout.GetBlob(_btcPayNetworkJsonSerializerSettings).Amount;
|
methodSettings.CurrentBalance += payout.Amount ?? payout.OriginalAmount;
|
||||||
result = true;
|
result = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -389,12 +392,12 @@ public class BringinService : EventHostedServiceBase
|
|||||||
return _settings.TryGetValue(storeId, out var bringinStoreSettings) ? bringinStoreSettings : null;
|
return _settings.TryGetValue(storeId, out var bringinStoreSettings) ? bringinStoreSettings : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public record SupportedMethodOptions(PaymentMethodId PaymentMethod, bool FiatMinimum, decimal FiatMinimumAmount, string bringinMethod);
|
public record SupportedMethodOptions(PayoutMethodId PayoutMethod, bool FiatMinimum, decimal FiatMinimumAmount, string bringinMethod);
|
||||||
|
|
||||||
public static readonly SupportedMethodOptions[] SupportedMethods = new[]
|
public static readonly SupportedMethodOptions[] SupportedMethods = new[]
|
||||||
{
|
{
|
||||||
new SupportedMethodOptions(new PaymentMethodId("BTC", LightningPaymentType.Instance), true, 22, "LIGHTNING"),
|
new SupportedMethodOptions(PayoutTypes.LN.GetPayoutMethodId("BTC"), true, 22, "LIGHTNING"),
|
||||||
new SupportedMethodOptions(new PaymentMethodId("BTC", BitcoinPaymentType.Instance), true, 22, "ON_CHAIN"),
|
new SupportedMethodOptions(PayoutTypes.CHAIN.GetPayoutMethodId("BTC"), true, 22, "ON_CHAIN"),
|
||||||
};
|
};
|
||||||
|
|
||||||
private ConcurrentDictionary<string, (IDisposable, BringinStoreSettings, DateTimeOffset Expiry)> _editModes = new();
|
private ConcurrentDictionary<string, (IDisposable, BringinStoreSettings, DateTimeOffset Expiry)> _editModes = new();
|
||||||
@@ -412,9 +415,9 @@ public class BringinService : EventHostedServiceBase
|
|||||||
// add or remove any missing methods in result
|
// add or remove any missing methods in result
|
||||||
foreach (var supportedMethod in SupportedMethods)
|
foreach (var supportedMethod in SupportedMethods)
|
||||||
{
|
{
|
||||||
if (!result.MethodSettings.ContainsKey(supportedMethod.PaymentMethod.ToString()))
|
if (!result.MethodSettings.ContainsKey(supportedMethod.PayoutMethod.ToString()))
|
||||||
{
|
{
|
||||||
result.MethodSettings.Add(supportedMethod.PaymentMethod.ToString(),
|
result.MethodSettings.Add(supportedMethod.PayoutMethod.ToString(),
|
||||||
new BringinStoreSettings.PaymentMethodSettings()
|
new BringinStoreSettings.PaymentMethodSettings()
|
||||||
{
|
{
|
||||||
FiatThreshold = supportedMethod.FiatMinimum,
|
FiatThreshold = supportedMethod.FiatMinimum,
|
||||||
@@ -424,7 +427,7 @@ public class BringinService : EventHostedServiceBase
|
|||||||
}
|
}
|
||||||
|
|
||||||
result.MethodSettings = result.MethodSettings.Where(pair =>
|
result.MethodSettings = result.MethodSettings.Where(pair =>
|
||||||
SupportedMethods.Any(supportedMethod => supportedMethod.PaymentMethod.ToString() == pair.Key))
|
SupportedMethods.Any(supportedMethod => supportedMethod.PayoutMethod.ToString() == pair.Key))
|
||||||
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
.ToDictionary(pair => pair.Key, pair => pair.Value);
|
||||||
isNew = true;
|
isNew = true;
|
||||||
return (storeLock, result, DateTimeOffset.Now.AddMinutes(5));
|
return (storeLock, result, DateTimeOffset.Now.AddMinutes(5));
|
||||||
|
|||||||
@@ -4,7 +4,9 @@
|
|||||||
@using BTCPayServer.Data
|
@using BTCPayServer.Data
|
||||||
@using BTCPayServer.Payments
|
@using BTCPayServer.Payments
|
||||||
@using BTCPayServer.PayoutProcessors
|
@using BTCPayServer.PayoutProcessors
|
||||||
|
@using BTCPayServer.Payouts
|
||||||
@using BTCPayServer.Services
|
@using BTCPayServer.Services
|
||||||
|
@using BTCPayServer.Services.Invoices
|
||||||
@using BTCPayServer.Services.Stores
|
@using BTCPayServer.Services.Stores
|
||||||
@using Microsoft.AspNetCore.Http
|
@using Microsoft.AspNetCore.Http
|
||||||
@using Microsoft.AspNetCore.Routing
|
@using Microsoft.AspNetCore.Routing
|
||||||
@@ -25,6 +27,7 @@
|
|||||||
[Inject] private IHttpClientFactory HttpClientFactory { get; set; }
|
[Inject] private IHttpClientFactory HttpClientFactory { get; set; }
|
||||||
[Inject] private PayoutProcessorService PayoutProcessorService { get; set; }
|
[Inject] private PayoutProcessorService PayoutProcessorService { get; set; }
|
||||||
[Inject] private IAuthorizationService AuthorizationService { get; set; }
|
[Inject] private IAuthorizationService AuthorizationService { get; set; }
|
||||||
|
[Inject] private PayoutMethodHandlerDictionary PayoutMethodHandlerDictionary { get; set; }
|
||||||
[Parameter] public string StoreId { get; set; }
|
[Parameter] public string StoreId { get; set; }
|
||||||
private decimal? LastFiatBalance { get; set; }
|
private decimal? LastFiatBalance { get; set; }
|
||||||
private DateTimeOffset? LastDataFetch { get; set; }
|
private DateTimeOffset? LastDataFetch { get; set; }
|
||||||
@@ -79,12 +82,13 @@
|
|||||||
PmiLink = $"A payout processor has not been configured for this payment method. Payouts generated by Bringin will not be automatically handled. <a href=\"{LinkGenerator.GetUriByAction(HttpContextAccessor.HttpContext, "ConfigureStorePayoutProcessors", "UIPayoutProcessors", new {StoreId})}\">Configure now</a>";
|
PmiLink = $"A payout processor has not been configured for this payment method. Payouts generated by Bringin will not be automatically handled. <a href=\"{LinkGenerator.GetUriByAction(HttpContextAccessor.HttpContext, "ConfigureStorePayoutProcessors", "UIPayoutProcessors", new {StoreId})}\">Configure now</a>";
|
||||||
_callbackLink = LinkGenerator.GetUriByAction(HttpContextAccessor.HttpContext, "Callback", "Bringin", new {StoreId});
|
_callbackLink = LinkGenerator.GetUriByAction(HttpContextAccessor.HttpContext, "Callback", "Bringin", new {StoreId});
|
||||||
_settings = BringinService.IsInEditMode(StoreId) ? await BringinService.Update(StoreId) : await BringinService.Get(StoreId);
|
_settings = BringinService.IsInEditMode(StoreId) ? await BringinService.Update(StoreId) : await BringinService.Get(StoreId);
|
||||||
_pms = (await StoreRepository.FindStore(StoreId)).GetSupportedPaymentMethods(BTCPayNetworkProvider).Select(method => method.PaymentId).Where(id => id.CryptoCode == "BTC").ToArray();
|
var store = await StoreRepository.FindStore(StoreId);
|
||||||
|
_pms = PayoutMethodHandlerDictionary.GetSupportedPayoutMethods(store);
|
||||||
_pps = (await PayoutProcessorService.GetProcessors(new PayoutProcessorService.PayoutProcessorQuery()
|
_pps = (await PayoutProcessorService.GetProcessors(new PayoutProcessorService.PayoutProcessorQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {StoreId},
|
Stores = new[] {StoreId},
|
||||||
PaymentMethods = _pms.Select(p => p.ToString()).ToArray()
|
PayoutMethods = _pms.Select(p => p).ToArray()
|
||||||
})).Select(data => PaymentMethodId.TryParse(data.PaymentMethod)).Where(id => id is not null).ToArray();
|
})).Select(data => PayoutMethodId.TryParse(data.PayoutMethodId)).Where(id => id is not null).ToArray();
|
||||||
EditMode = BringinService.IsInEditMode(StoreId);
|
EditMode = BringinService.IsInEditMode(StoreId);
|
||||||
IsLoaded = true;
|
IsLoaded = true;
|
||||||
_ = FetchBalanceAndRate();
|
_ = FetchBalanceAndRate();
|
||||||
@@ -148,8 +152,8 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
private bool _saving;
|
private bool _saving;
|
||||||
private PaymentMethodId[] _pms;
|
private HashSet<PayoutMethodId> _pms;
|
||||||
private PaymentMethodId[] _pps;
|
private PayoutMethodId[] _pps;
|
||||||
private bool _apiKeyError;
|
private bool _apiKeyError;
|
||||||
|
|
||||||
private async Task Save()
|
private async Task Save()
|
||||||
@@ -269,7 +273,7 @@
|
|||||||
_saving = true;
|
_saving = true;
|
||||||
|
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
var pm = PaymentMethodId.TryParse(ManualOrderPaymentMethod);
|
var pm = PayoutMethodId.TryParse(ManualOrderPaymentMethod);
|
||||||
if (pm is null)
|
if (pm is null)
|
||||||
{
|
{
|
||||||
SaveError = "Invalid payment method";
|
SaveError = "Invalid payment method";
|
||||||
@@ -391,8 +395,8 @@
|
|||||||
}
|
}
|
||||||
else if (_manualOrder)
|
else if (_manualOrder)
|
||||||
{
|
{
|
||||||
var items = new List<PaymentMethodId>();
|
var items = new List<PayoutMethodId>();
|
||||||
items.AddRange(BringinService.SupportedMethods.Where(s => _pms.Contains(s.PaymentMethod)).Select(s => s.PaymentMethod));
|
items.AddRange(BringinService.SupportedMethods.Where(s => _pms.Contains(s.PayoutMethod)).Select(s => s.PayoutMethod));
|
||||||
|
|
||||||
|
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -422,7 +426,7 @@
|
|||||||
<option value="">Select a payment method</option>
|
<option value="">Select a payment method</option>
|
||||||
@foreach (var opt in items)
|
@foreach (var opt in items)
|
||||||
{
|
{
|
||||||
<option value="@opt.ToString()">@opt.ToPrettyString()</option>
|
<option value="@opt.ToString()">@opt</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
@@ -472,7 +476,7 @@
|
|||||||
|
|
||||||
@foreach (var method in _settings.MethodSettings)
|
@foreach (var method in _settings.MethodSettings)
|
||||||
{
|
{
|
||||||
var pmi = PaymentMethodId.TryParse(method.Key);
|
var pmi = PayoutMethodId.TryParse(method.Key);
|
||||||
if (pmi is null)
|
if (pmi is null)
|
||||||
continue;
|
continue;
|
||||||
if (!_pms.Contains(pmi))
|
if (!_pms.Contains(pmi))
|
||||||
@@ -480,7 +484,7 @@
|
|||||||
<hr class=""/>
|
<hr class=""/>
|
||||||
<div class="store-number">
|
<div class="store-number">
|
||||||
<header>
|
<header>
|
||||||
<h6>@pmi.ToPrettyString()</h6>
|
<h6>@pmi</h6>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
@if (LastFiatRate is null || !method.Value.FiatThreshold)
|
@if (LastFiatRate is null || !method.Value.FiatThreshold)
|
||||||
@@ -504,7 +508,7 @@
|
|||||||
<span class="text-secondary"> (@DisplayFormatter.Currency(balanceInFiat.Value, "EUR", DisplayFormatter.CurrencyFormat.Code)) pending to forward once @DisplayFormatter.Currency(thresholdinBtc.Value, "BTC", DisplayFormatter.CurrencyFormat.Code) (@DisplayFormatter.Currency(method.Value.Threshold, "EUR")) is reached.</span>
|
<span class="text-secondary"> (@DisplayFormatter.Currency(balanceInFiat.Value, "EUR", DisplayFormatter.CurrencyFormat.Code)) pending to forward once @DisplayFormatter.Currency(thresholdinBtc.Value, "BTC", DisplayFormatter.CurrencyFormat.Code) (@DisplayFormatter.Currency(method.Value.Threshold, "EUR")) is reached.</span>
|
||||||
@if (method.Value.CurrentBalance > 0)
|
@if (method.Value.CurrentBalance > 0)
|
||||||
{
|
{
|
||||||
<button class="btn btn-link" @onclick="() => ResetBalance(pmi)" disabled="@_saving">Reset balance</button>
|
<button class="btn btn-link" @onclick="() => ResetBalance(PaymentMethodId.Parse(pmi.ToString()))" disabled="@_saving">Reset balance</button>
|
||||||
//Clear balance
|
//Clear balance
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
@@ -579,9 +583,9 @@
|
|||||||
var pmId = PaymentMethodId.TryParse(method.Key);
|
var pmId = PaymentMethodId.TryParse(method.Key);
|
||||||
if (pmId is null)
|
if (pmId is null)
|
||||||
continue;
|
continue;
|
||||||
var supportedMethod = BringinService.SupportedMethods.FirstOrDefault(s => s.PaymentMethod.ToString() == method.Key);
|
var supportedMethod = BringinService.SupportedMethods.FirstOrDefault(s => s.PayoutMethod.ToString() == method.Key);
|
||||||
<div class="col-xxl-constrain col-12 @(_settings.MethodSettings.Count > 1 ? $"col-xl-6 {(i == 0 ? "border-end" : "")}" : "")">
|
<div class="col-xxl-constrain col-12 @(_settings.MethodSettings.Count > 1 ? $"col-xl-6 {(i == 0 ? "border-end" : "")}" : "")">
|
||||||
<h5 class=" border-bottom-0 text-muted mb-4">@pmId.ToPrettyString()</h5>
|
<h5 class=" border-bottom-0 text-muted mb-4">@pmId</h5>
|
||||||
<div class="card-body">
|
<div class="card-body">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Percentage</label>
|
<label class="form-label">Percentage</label>
|
||||||
@@ -644,15 +648,16 @@
|
|||||||
<tr>
|
<tr>
|
||||||
<td>@tx.CreatedAt.ToTimeAgo()</td>
|
<td>@tx.CreatedAt.ToTimeAgo()</td>
|
||||||
<td>@tx.SubType.ToHumanReadable()</td>
|
<td>@tx.SubType.ToHumanReadable()</td>
|
||||||
<td>
|
<td>@tx.Status.ToHumanReadable()</td>
|
||||||
@tx.Status.ToHumanReadable()
|
|
||||||
</td>
|
|
||||||
<td class="amount-col">
|
<td class="amount-col">
|
||||||
<span data-sensitive>@(tx.SourceCurrency == "BTC" ? Money.Satoshis(tx.SourceAmount).ToDecimal(MoneyUnit.BTC): tx.SourceAmount)@tx.SourceCurrency -> @tx.DestinationAmount @tx.DestinationCurrency </span>
|
<span data-sensitive>
|
||||||
|
@(tx.SourceCurrency == "BTC" ? Money.Satoshis(tx.SourceAmount).ToDecimal(MoneyUnit.BTC) : tx.SourceAmount) @tx.SourceCurrency
|
||||||
|
-> @tx.DestinationAmount @tx.DestinationCurrency
|
||||||
|
</span>
|
||||||
</td>
|
</td>
|
||||||
</tr>
|
</tr>
|
||||||
}
|
}
|
||||||
</tbody>
|
</tbody>s
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Data Erasure</Product>
|
<Product>Data Erasure</Product>
|
||||||
<Description>Allows you to erase user data from invoices after a period of time.</Description>
|
<Description>Allows you to erase user data from invoices after a period of time.</Description>
|
||||||
<Version>1.0.2</Version>
|
<Version>1.0.3</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
public class DataErasureController : Controller
|
public class DataErasureController : Controller
|
||||||
{
|
{
|
||||||
private readonly DataErasureService _dataErasureService;
|
private readonly DataErasureService _dataErasureService;
|
||||||
|
|
||||||
public DataErasureController(DataErasureService dataErasureService)
|
public DataErasureController(DataErasureService dataErasureService)
|
||||||
{
|
{
|
||||||
_dataErasureService = dataErasureService;
|
_dataErasureService = dataErasureService;
|
||||||
@@ -31,7 +32,8 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
{
|
{
|
||||||
if (_dataErasureService.IsRunning)
|
if (_dataErasureService.IsRunning)
|
||||||
{
|
{
|
||||||
TempData["ErrorMessage"] = "Data erasure is currently running and cannot be changed. Please try again later.";
|
TempData["ErrorMessage"] =
|
||||||
|
"Data erasure is currently running and cannot be changed. Please try again later.";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +48,11 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
|
|
||||||
switch (command)
|
switch (command)
|
||||||
{
|
{
|
||||||
|
case "cleardate":
|
||||||
|
await _dataErasureService.Set(storeId, vm, true);
|
||||||
|
|
||||||
|
TempData["SuccessMessage"] = "Data erasure settings modified and date cleared";
|
||||||
|
return RedirectToAction(nameof(Update), new {storeId});
|
||||||
case "save":
|
case "save":
|
||||||
await _dataErasureService.Set(storeId, vm);
|
await _dataErasureService.Set(storeId, vm);
|
||||||
TempData["SuccessMessage"] = "Data erasure settings modified";
|
TempData["SuccessMessage"] = "Data erasure settings modified";
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.12.0" }
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
};
|
};
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -14,13 +15,15 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
private readonly IStoreRepository _storeRepository;
|
private readonly IStoreRepository _storeRepository;
|
||||||
private readonly ILogger<DataErasureService> _logger;
|
private readonly ILogger<DataErasureService> _logger;
|
||||||
private readonly InvoiceRepository _invoiceRepository;
|
private readonly InvoiceRepository _invoiceRepository;
|
||||||
|
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||||
|
|
||||||
public DataErasureService(IStoreRepository storeRepository, ILogger<DataErasureService> logger,
|
public DataErasureService(IStoreRepository storeRepository, ILogger<DataErasureService> logger,
|
||||||
InvoiceRepository invoiceRepository)
|
InvoiceRepository invoiceRepository, ApplicationDbContextFactory dbContextFactory)
|
||||||
{
|
{
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_invoiceRepository = invoiceRepository;
|
_invoiceRepository = invoiceRepository;
|
||||||
|
_dbContextFactory = dbContextFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<DataErasureSettings> Get(string storeId)
|
public async Task<DataErasureSettings> Get(string storeId)
|
||||||
@@ -29,13 +32,16 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
nameof(DataErasureSettings));
|
nameof(DataErasureSettings));
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task Set(string storeId, DataErasureSettings settings)
|
public async Task Set(string storeId, DataErasureSettings settings, bool clearDate = false)
|
||||||
{
|
{
|
||||||
|
_cts?.Cancel();
|
||||||
await _runningLock.WaitAsync();
|
await _runningLock.WaitAsync();
|
||||||
var existing = await Get(storeId);
|
var existing = await Get(storeId);
|
||||||
settings.LastRunCutoff = existing?.LastRunCutoff;
|
settings.LastRunCutoff = clearDate? null: existing?.LastRunCutoff;
|
||||||
await SetCore(storeId, settings);
|
await SetCore(storeId, settings);
|
||||||
_runningLock.Release();
|
_runningLock.Release();
|
||||||
|
_cts = new CancellationTokenSource();
|
||||||
|
_ = Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task SetCore(string storeId, DataErasureSettings settings)
|
private async Task SetCore(string storeId, DataErasureSettings settings)
|
||||||
@@ -46,11 +52,11 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
public bool IsRunning { get; private set; }
|
public bool IsRunning { get; private set; }
|
||||||
private readonly SemaphoreSlim _runningLock = new(1, 1);
|
private readonly SemaphoreSlim _runningLock = new(1, 1);
|
||||||
|
|
||||||
private async Task Run(CancellationToken cancellationToken)
|
private async Task Run()
|
||||||
{
|
{
|
||||||
while (!cancellationToken.IsCancellationRequested)
|
while (!_cts.IsCancellationRequested)
|
||||||
{
|
{
|
||||||
await _runningLock.WaitAsync(cancellationToken);
|
await _runningLock.WaitAsync(_cts.Token);
|
||||||
IsRunning = true;
|
IsRunning = true;
|
||||||
|
|
||||||
|
|
||||||
@@ -58,9 +64,20 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
await _storeRepository.GetSettingsAsync<DataErasureSettings>(nameof(DataErasureSettings));
|
await _storeRepository.GetSettingsAsync<DataErasureSettings>(nameof(DataErasureSettings));
|
||||||
foreach (var setting in settings.Where(setting => setting.Value.Enabled))
|
foreach (var setting in settings.Where(setting => setting.Value.Enabled))
|
||||||
{
|
{
|
||||||
var skip = 0;
|
|
||||||
var count = 0;
|
var count = 0;
|
||||||
var cutoffDate = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromDays(setting.Value.DaysToKeep));
|
var cutoffDate = DateTimeOffset.UtcNow.Subtract(TimeSpan.FromDays(setting.Value.DaysToKeep));
|
||||||
|
if (setting.Value.EntirelyEraseInvoice)
|
||||||
|
{
|
||||||
|
await using var db = _dbContextFactory.CreateContext();
|
||||||
|
db.Invoices.RemoveRange(db.Invoices.Where(i => i.StoreDataId == setting.Key && i.Created < cutoffDate && (setting.Value.LastRunCutoff == null || i.Created > setting.Value.LastRunCutoff)));
|
||||||
|
count = await db.SaveChangesAsync(_cts.Token);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
var skip = 0;
|
||||||
while (true)
|
while (true)
|
||||||
{
|
{
|
||||||
var invoices = await _invoiceRepository.GetInvoices(new InvoiceQuery()
|
var invoices = await _invoiceRepository.GetInvoices(new InvoiceQuery()
|
||||||
@@ -70,7 +87,10 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
StoreId = new[] {setting.Key},
|
StoreId = new[] {setting.Key},
|
||||||
Skip = skip,
|
Skip = skip,
|
||||||
Take = 100
|
Take = 100
|
||||||
});
|
}, _cts.Token);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
foreach (var invoice in invoices)
|
foreach (var invoice in invoices)
|
||||||
{
|
{
|
||||||
//replace all buyer info with "erased"
|
//replace all buyer info with "erased"
|
||||||
@@ -104,6 +124,8 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
|
|
||||||
skip += 100;
|
skip += 100;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (count > 0)
|
if (count > 0)
|
||||||
_logger.LogInformation($"Erased {count} invoice data for store {setting.Key}");
|
_logger.LogInformation($"Erased {count} invoice data for store {setting.Key}");
|
||||||
setting.Value.LastRunCutoff = cutoffDate;
|
setting.Value.LastRunCutoff = cutoffDate;
|
||||||
@@ -114,18 +136,30 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
|
|
||||||
|
|
||||||
_runningLock.Release();
|
_runningLock.Release();
|
||||||
await Task.Delay(TimeSpan.FromDays(1), cancellationToken);
|
await Task.Delay(TimeSpan.FromHours(1), _cts.Token);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_runningLock.Release();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private CancellationTokenSource _cts;
|
||||||
|
|
||||||
public Task StartAsync(CancellationToken cancellationToken)
|
public Task StartAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
_ = Run(cancellationToken);
|
_cts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
|
||||||
|
_ = Run();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Task StopAsync(CancellationToken cancellationToken)
|
public Task StopAsync(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
|
_cts?.Cancel();
|
||||||
return Task.CompletedTask;
|
return Task.CompletedTask;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,5 +7,7 @@ namespace BTCPayServer.Plugins.DataErasure
|
|||||||
public bool Enabled { get; set; }
|
public bool Enabled { get; set; }
|
||||||
public int DaysToKeep { get; set; }
|
public int DaysToKeep { get; set; }
|
||||||
public DateTimeOffset? LastRunCutoff { get; set; }
|
public DateTimeOffset? LastRunCutoff { get; set; }
|
||||||
|
|
||||||
|
public bool EntirelyEraseInvoice { get; set; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -36,9 +36,24 @@
|
|||||||
<input asp-for="DaysToKeep" type="number" class="form-control"/>
|
<input asp-for="DaysToKeep" type="number" class="form-control"/>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<div class="d-flex align-items-center">
|
||||||
|
<input asp-for="EntirelyEraseInvoice" type="checkbox" class="btcpay-toggle me-2"/>
|
||||||
|
<label asp-for="EntirelyEraseInvoice" class="form-label mb-0 me-1">Remove entire invoice from records (instead of just buyer data)</label>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
<div class="alert alert-warning">
|
||||||
|
<p>
|
||||||
|
Deleting entire invoices may cause issues with integrations and accounting. Only use this option if you are sure you want to remove the invoice entirely.
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
@if (Model.LastRunCutoff != null)
|
@if (Model.LastRunCutoff != null)
|
||||||
{
|
{
|
||||||
<div>Cleared data up to @Model.LastRunCutoff.Value.ToString("g")</div>
|
<div>Cleared data up to @Model.LastRunCutoff.Value.ToString("g")</div>
|
||||||
|
<div class="form-group">
|
||||||
|
<button name="command" type="submit" value="cleardate" class="btn btn-danger">Start over</button>
|
||||||
|
</div>
|
||||||
}
|
}
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Dynamic Rate Limit</Product>
|
<Product>Dynamic Rate Limit</Product>
|
||||||
<Description>Allows you to override the default rate limiting.</Description>
|
<Description>Allows you to override the default rate limiting.</Description>
|
||||||
<Version>1.0.1</Version>
|
<Version>1.0.2</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class DynamicRateLimitsPlugin : BaseBTCPayServerPlugin
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.12.0" }
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
};
|
};
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,11 +1,6 @@
|
|||||||
@using BTCPayServer.Plugins.DynamicRateLimits
|
@using BTCPayServer.Plugins.DynamicRateLimits
|
||||||
@model DynamicRateLimitSettings
|
@model DynamicRateLimitSettings
|
||||||
|
|
||||||
@{
|
|
||||||
Layout = "../Shared/_NavLayout.cshtml";
|
|
||||||
ViewData["NavPartialName"] = "../UIServer/_Nav";
|
|
||||||
}
|
|
||||||
|
|
||||||
<h2 class="mb-4">Rate limit configuration</h2>
|
<h2 class="mb-4">Rate limit configuration</h2>
|
||||||
|
|
||||||
<form method="post">
|
<form method="post">
|
||||||
|
|||||||
@@ -1,7 +1,13 @@
|
|||||||
|
@using BTCPayServer.Client
|
||||||
@using BTCPayServer.Plugins.DynamicRateLimits
|
@using BTCPayServer.Plugins.DynamicRateLimits
|
||||||
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@{
|
@{
|
||||||
var isActive = ViewContext.RouteData.Values.TryGetValue("Controller", out var controller) && controller is not null &&
|
var isActive = ViewContext.RouteData.Values.TryGetValue("Controller", out var controller) && controller is not null &&
|
||||||
nameof(DynamicRatesLimiterController).StartsWith(controller?.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
nameof(DynamicRatesLimiterController).StartsWith(controller?.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||||
|
|
||||||
<a class="nav-link @(isActive ? "active" : string.Empty)" asp-action="Update" asp-controller="DynamicRatesLimiter">Rate Limits</a>
|
<a class="nav-link @(isActive ? "active" : string.Empty)" asp-action="Update" asp-controller="DynamicRatesLimiter">Rate Limits</a>
|
||||||
|
</li>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Dynamic Reports</Product>
|
<Product>Dynamic Reports</Product>
|
||||||
<Description>Allows you to create custom reports using SQL.</Description>
|
<Description>Allows you to create custom reports using SQL.</Description>
|
||||||
<Version>1.0.1</Version>
|
<Version>1.0.2</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ public class DynamicReportsPlugin : BaseBTCPayServerPlugin
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.13.0" }
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
};
|
};
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -21,19 +21,15 @@ public class PostgresReportProvider : ReportProvider
|
|||||||
public DynamicReportsSettings.DynamicReportSetting Setting { get; set; }
|
public DynamicReportsSettings.DynamicReportSetting Setting { get; set; }
|
||||||
|
|
||||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||||
private readonly IOptions<DatabaseOptions> _options;
|
|
||||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||||
public PostgresReportProvider( ApplicationDbContextFactory dbContextFactory,
|
public PostgresReportProvider( ApplicationDbContextFactory dbContextFactory, IHttpContextAccessor httpContextAccessor)
|
||||||
IOptions<DatabaseOptions> options, IHttpContextAccessor httpContextAccessor)
|
|
||||||
{
|
{
|
||||||
_dbContextFactory = dbContextFactory;
|
_dbContextFactory = dbContextFactory;
|
||||||
_options = options;
|
|
||||||
_httpContextAccessor = httpContextAccessor;
|
_httpContextAccessor = httpContextAccessor;
|
||||||
}
|
}
|
||||||
public override bool IsAvailable()
|
public override bool IsAvailable()
|
||||||
{
|
{
|
||||||
return _options.Value.DatabaseType == DatabaseType.Postgres &&
|
return Setting.AllowForNonAdmins || _httpContextAccessor.HttpContext?.User.IsInRole(Roles.ServerAdmin) is true;
|
||||||
Setting.AllowForNonAdmins || _httpContextAccessor.HttpContext?.User.IsInRole(Roles.ServerAdmin) is true;
|
|
||||||
}
|
}
|
||||||
public override async Task Query(QueryContext queryContext, CancellationToken cancellation)
|
public override async Task Query(QueryContext queryContext, CancellationToken cancellation)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
@inject DynamicReportService DynamicReportService
|
@inject DynamicReportService DynamicReportService
|
||||||
|
|
||||||
@{
|
@{
|
||||||
Layout = "../Shared/_NavLayout.cshtml";
|
|
||||||
ViewData["NavPartialName"] = "../UIServer/_Nav";
|
|
||||||
var storeId = ScopeProvider.GetCurrentStoreId();
|
var storeId = ScopeProvider.GetCurrentStoreId();
|
||||||
var reportName = Context.Request.Query["reportName"].ToString();
|
var reportName = Context.Request.Query["reportName"].ToString();
|
||||||
reportName = string.IsNullOrEmpty(reportName) ? null : reportName;
|
reportName = string.IsNullOrEmpty(reportName) ? null : reportName;
|
||||||
|
|||||||
@@ -1,8 +1,15 @@
|
|||||||
|
@using BTCPayServer.Client
|
||||||
@using BTCPayServer.Plugins.DynamicReports
|
@using BTCPayServer.Plugins.DynamicReports
|
||||||
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
|
|
||||||
@{
|
@{
|
||||||
var isActive = ViewContext.RouteData.Values.TryGetValue("Controller", out var controller) && controller is not null &&
|
var isActive = ViewContext.RouteData.Values.TryGetValue("Controller", out var controller) && controller is not null &&
|
||||||
nameof(DynamicReportsController).StartsWith(controller?.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
nameof(DynamicReportsController).StartsWith(controller?.ToString(), StringComparison.InvariantCultureIgnoreCase);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
<li class="nav-item nav-item-sub" permission="@Policies.CanModifyServerSettings">
|
||||||
|
|
||||||
<a class="nav-link @(isActive ? "active" : string.Empty)" asp-action="Update" asp-controller="DynamicReports">Dynamic Reports</a>
|
<a class="nav-link @(isActive ? "active" : string.Empty)" asp-action="Update" asp-controller="DynamicReports">Dynamic Reports</a>
|
||||||
|
</li>
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>File Seller</Product>
|
<Product>File Seller</Product>
|
||||||
<Description>Allows you to sell files through the point of sale/crowdfund apps.</Description>
|
<Description>Allows you to sell files through the point of sale/crowdfund apps.</Description>
|
||||||
<Version>1.0.4</Version>
|
<Version>1.0.5</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -9,8 +9,9 @@ public class FileSellerPlugin : BaseBTCPayServerPlugin
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.12.0" }
|
new() {Identifier = nameof(BTCPayServer), Condition = ">=2.0.0"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
applicationBuilder.AddHostedService<FileSellerService>();
|
applicationBuilder.AddHostedService<FileSellerService>();
|
||||||
|
|||||||
@@ -6,16 +6,16 @@
|
|||||||
@inject UserManager<ApplicationUser> UserManager
|
@inject UserManager<ApplicationUser> UserManager
|
||||||
@inject UserService UserService
|
@inject UserService UserService
|
||||||
@{
|
@{
|
||||||
var userId = UserManager.GetUserId(User);
|
var user = await UserManager.GetUserAsync(User);
|
||||||
var files = (await StoredFileRepository.GetFiles(new StoredFileRepository.FilesQuery()
|
var files = (await StoredFileRepository.GetFiles(new StoredFileRepository.FilesQuery()
|
||||||
{
|
{
|
||||||
UserIds = await UserService.IsAdminUser(userId) ? Array.Empty<string>() : new[] {userId},
|
UserIds = await UserService.IsAdminUser(user) ? Array.Empty<string>() : new[] {user.Id},
|
||||||
})).Select(file => new SelectListItem(file.FileName, file.Id)).Prepend(new SelectListItem("No file", ""));
|
})).Select(file => new SelectListItem(file.FileName, file.Id)).Prepend(new SelectListItem("No file", ""));
|
||||||
}
|
}
|
||||||
<template v-if="editingItem">
|
<template v-if="editingItem">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<label class="form-label">Downloadable file</label>
|
<label class="form-label">Downloadable file</label>
|
||||||
<select :value="editingItem['file'] || ''" asp-items="files" class="form-select w-auto" v-on:change=" if(event.target.value) editingItem['file']= event.target.value; else delete editingItem['file'];"></select>
|
<select :value="editingItem['file'] || ''" asp-items="files" class="form-select w-auto" v-on:change="if(event.target.value) Vue.set(editingItem, 'file', event.target.value); else Vue.delete(editingItem, 'file');"></select>
|
||||||
<span class="form-text">If a file is selected, when a user buys this item, a download link is generated in the payment receipt once the invoice is settled. <a target="_blank" asp-action="Files" asp-controller="UIServer">Upload files here</a></span>
|
<span class="form-text">If a file is selected, when a user buys this item, a download link is generated in the payment receipt once the invoice is settled. <a target="_blank" asp-action="Files" asp-controller="UIServer">Upload files here</a></span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>FixedFloat</Product>
|
<Product>FixedFloat</Product>
|
||||||
<Description>Allows you to embed a FixedFloat conversion screen to allow customers to pay with altcoins.</Description>
|
<Description>Allows you to embed a FixedFloat conversion screen to allow customers to pay with altcoins.</Description>
|
||||||
<Version>1.1.7</Version>
|
<Version>1.1.8</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -9,29 +9,16 @@ namespace BTCPayServer.Plugins.FixedFloat
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() { Identifier = nameof(BTCPayServer), Condition = ">=1.12.0" }
|
new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
|
|
||||||
};
|
};
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
applicationBuilder.AddSingleton<FixedFloatService>();
|
applicationBuilder.AddSingleton<FixedFloatService>();
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/FixedFloatNav",
|
applicationBuilder.AddUIExtension("store-integrations-nav", "FixedFloat/FixedFloatNav");
|
||||||
"store-integrations-nav"));
|
applicationBuilder.AddUIExtension("checkout-payment-method", "FixedFloat/CheckoutPaymentMethodExtension");
|
||||||
// Checkout v2
|
applicationBuilder.AddUIExtension("checkout-payment", "FixedFloat/CheckoutPaymentExtension");
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/CheckoutPaymentMethodExtension",
|
|
||||||
"checkout-payment-method"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/CheckoutPaymentExtension",
|
|
||||||
"checkout-payment"));
|
|
||||||
// Checkout Classic
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/CheckoutContentExtension",
|
|
||||||
"checkout-bitcoin-post-content"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/CheckoutContentExtension",
|
|
||||||
"checkout-lightning-post-content"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/CheckoutTabExtension",
|
|
||||||
"checkout-bitcoin-post-tabs"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/CheckoutTabExtension",
|
|
||||||
"checkout-lightning-post-tabs"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("FixedFloat/CheckoutEnd",
|
|
||||||
"checkout-end"));
|
|
||||||
base.Execute(applicationBuilder);
|
base.Execute(applicationBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,47 +20,61 @@ namespace BTCPayServer.Plugins.FixedFloat
|
|||||||
{
|
{
|
||||||
{"AAVEETH", "Aave (ERC20)"},
|
{"AAVEETH", "Aave (ERC20)"},
|
||||||
{"ADA", "Cardano"},
|
{"ADA", "Cardano"},
|
||||||
|
{"ADABSC", "Cardano (BEP20)"},
|
||||||
|
{"APT", "Aptos"},
|
||||||
{"ATOM", "Cosmos"},
|
{"ATOM", "Cosmos"},
|
||||||
{"AVAX", "Avalanche (C-Chain)"},
|
{"AVAX", "Avalanche (C-Chain)"},
|
||||||
{"BAT", "Basic Attention (ERC20)"},
|
{"BAT", "Basic Attention (ERC20)"},
|
||||||
{"BCH", "Bitcoin Cash"},
|
|
||||||
{"BNB", "BNB Beacon Chain (BEP2)"},
|
|
||||||
{"BSC", "BNB Smart Chain (BEP20)"},
|
{"BSC", "BNB Smart Chain (BEP20)"},
|
||||||
|
{"WBNBBSC", "Wrapped BNB (BEP20)"},
|
||||||
{"BTC", "Bitcoin"},
|
{"BTC", "Bitcoin"},
|
||||||
|
{"BTCBSC", "Bitcoin (BEP20)"},
|
||||||
{"BTCLN", "Bitcoin (Lightning)"},
|
{"BTCLN", "Bitcoin (Lightning)"},
|
||||||
{"BTT", "BitTorrent"},
|
{"BTT", "BitTorrent"},
|
||||||
{"BUSD", "Binance USD (BEP2)"},
|
|
||||||
{"BUSDBSC", "Binance USD (BEP20)"},
|
|
||||||
{"BUSDETH", "Binance USD (ERC20)"},
|
|
||||||
{"CAKE", "PancakeSwap (BEP20)"},
|
{"CAKE", "PancakeSwap (BEP20)"},
|
||||||
|
{"DAIBSC", "DAI (BEP20)"},
|
||||||
{"DAIETH", "DAI (ERC20)"},
|
{"DAIETH", "DAI (ERC20)"},
|
||||||
|
{"DAIMATIC", "DAI (Polygon)"},
|
||||||
|
{"DASH", "Dash"},
|
||||||
{"DOGE", "Dogecoin"},
|
{"DOGE", "Dogecoin"},
|
||||||
{"DOT", "Polkadot"},
|
{"DOT", "Polkadot"},
|
||||||
{"EOS", "EOS"},
|
{"EOS", "EOS"},
|
||||||
{"ETC", "Ethereum Classic"},
|
|
||||||
{"ETH", "Ethereum"},
|
{"ETH", "Ethereum"},
|
||||||
|
{"ETHARBITRUM", "Ethereum (Arbitrum)"},
|
||||||
|
{"ETHBASE", "Ethereum (Base)"},
|
||||||
|
{"ETHZKSYNC", "Ethereum (ZkSync)"},
|
||||||
|
{"WETHARBITRUM", "Wrapped ETH (Arbitrum)"},
|
||||||
|
{"WETHETH", "Wrapped ETH (ERC20)"},
|
||||||
{"FTM", "Fantom"},
|
{"FTM", "Fantom"},
|
||||||
|
{"KCS", "KuCoin Token"},
|
||||||
{"LINK", "Chainlink (ERC20)"},
|
{"LINK", "Chainlink (ERC20)"},
|
||||||
{"LTC", "Litecoin"},
|
{"LTC", "Litecoin"},
|
||||||
{"MANAETH", "Decentraland (ERC20)"},
|
{"MANAETH", "Decentraland (ERC20)"},
|
||||||
{"MATIC", "Polygon"},
|
|
||||||
{"MATICETH", "Polygon (ERC20)"},
|
|
||||||
{"MKR", "Maker (ERC20)"},
|
{"MKR", "Maker (ERC20)"},
|
||||||
|
{"PAXGETH", "PAX Gold (ERC20)"},
|
||||||
|
{"POL", "Polygon"},
|
||||||
|
{"POLETH", "Polygon (ERC20)"},
|
||||||
{"SHIB", "SHIBA INU (ERC20)"},
|
{"SHIB", "SHIBA INU (ERC20)"},
|
||||||
|
{"SHIBBSC", "SHIBA INU (BEP20)"},
|
||||||
{"SOL", "Solana"},
|
{"SOL", "Solana"},
|
||||||
|
{"WSOL", "Wrapped SOL (Solana)"},
|
||||||
{"TON", "Toncoin"},
|
{"TON", "Toncoin"},
|
||||||
{"TRX", "Tron"},
|
{"TRX", "Tron"},
|
||||||
{"TUSD", "TrueUSD (ERC20)"},
|
{"TUSD", "TrueUSD (ERC20)"},
|
||||||
{"TWT", "Trust Wallet Token (BEP2)"},
|
|
||||||
{"TWTBSC", "Trust Wallet Token (BEP20)"},
|
{"TWTBSC", "Trust Wallet Token (BEP20)"},
|
||||||
|
{"USDCARBITRUM", "USD Coin (Arbitrum)"},
|
||||||
|
{"USDCBSC", "USD Coin (BEP20)"},
|
||||||
{"USDCETH", "USD Coin (ERC20)"},
|
{"USDCETH", "USD Coin (ERC20)"},
|
||||||
|
{"USDCMATIC", "USD Coin (Polygon)"},
|
||||||
{"USDCSOL", "USD Coin (Solana)"},
|
{"USDCSOL", "USD Coin (Solana)"},
|
||||||
{"USDCTRC", "USD Coin (TRC20)"},
|
|
||||||
{"USDP", "Pax Dollar (ERC20)"},
|
{"USDP", "Pax Dollar (ERC20)"},
|
||||||
{"USDT", "Tether (ERC20)"},
|
{"USDT", "Tether (ERC20)"},
|
||||||
|
{"USDTBSC", "Tether (BEP20)"},
|
||||||
|
{"USDTMATIC", "Tether (Polygon)"},
|
||||||
{"USDTSOL", "Tether (Solana)"},
|
{"USDTSOL", "Tether (Solana)"},
|
||||||
{"USDTTRC", "Tether (TRC20)"},
|
{"USDTTRC", "Tether (TRC20)"},
|
||||||
{"VET", "VeChain"},
|
{"VET", "VeChain"},
|
||||||
|
{"XLM", "Stellar Lumens"},
|
||||||
{"XMR", "Monero"},
|
{"XMR", "Monero"},
|
||||||
{"XRP", "Ripple"},
|
{"XRP", "Ripple"},
|
||||||
{"XTZ", "Tezos"},
|
{"XTZ", "Tezos"},
|
||||||
@@ -68,8 +82,8 @@ namespace BTCPayServer.Plugins.FixedFloat
|
|||||||
{"ZRX", "0x (ERC20)"}
|
{"ZRX", "0x (ERC20)"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public static List<SelectListItem> AllowedSendingOptionsList => AllowedSendingOptions.Select(o => new SelectListItem(o.Value, o.Key)).ToList();
|
|
||||||
|
|
||||||
|
|
||||||
|
public static List<SelectListItem> AllowedSendingOptionsList =>
|
||||||
|
AllowedSendingOptions.Select(o => new SelectListItem(o.Value, o.Key)).ToList();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,15 +2,17 @@
|
|||||||
@using BTCPayServer.Abstractions.Extensions
|
@using BTCPayServer.Abstractions.Extensions
|
||||||
@using BTCPayServer.Data
|
@using BTCPayServer.Data
|
||||||
@using BTCPayServer.Plugins.FixedFloat
|
@using BTCPayServer.Plugins.FixedFloat
|
||||||
|
@using BTCPayServer.Services.Invoices
|
||||||
@using BTCPayServer.Services.Stores
|
@using BTCPayServer.Services.Stores
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@model BTCPayServer.Plugins.FixedFloat.FixedFloatSettings
|
@model BTCPayServer.Plugins.FixedFloat.FixedFloatSettings
|
||||||
@inject BTCPayNetworkProvider BTCPayNetworkProvider
|
@inject BTCPayNetworkProvider BTCPayNetworkProvider
|
||||||
|
@inject PaymentMethodHandlerDictionary PaymentMethodHandlerDictionary
|
||||||
@{
|
@{
|
||||||
ViewData.SetActivePage("FixedFloat", "FixedFloat", "FixedFloat");
|
ViewData.SetActivePage("FixedFloat", "FixedFloat", "FixedFloat");
|
||||||
var store = Context.GetStoreData();
|
var store = Context.GetStoreData();
|
||||||
var allowedPaymentMethods = store.GetEnabledPaymentIds(BTCPayNetworkProvider)
|
var allowedPaymentMethods = store.GetEnabledPaymentIds()
|
||||||
.Select(pmi => new SelectListItem(pmi.ToPrettyString(), pmi.ToString()))
|
.Select(pmi => new SelectListItem(pmi.ToString(), pmi.ToString()))
|
||||||
.Prepend(new SelectListItem("Any", ""));
|
.Prepend(new SelectListItem("Any", ""));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
@using BTCPayServer.Plugins.FixedFloat
|
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
|
||||||
@inject FixedFloatService FixedFloatService
|
|
||||||
@{
|
|
||||||
var storeId = Model.StoreId;
|
|
||||||
var settings = await FixedFloatService.GetFixedFloatForStore(storeId);
|
|
||||||
|
|
||||||
if (settings?.Enabled is true)
|
|
||||||
{
|
|
||||||
<div id="FixedFloat" class="bp-view payment manual-flow" style="padding:0" :class="{ active: currentTab == 'undefined' || currentTab == 'FixedFloat' }">
|
|
||||||
<fixed-float inline-template
|
|
||||||
:to-currency="srvModel.paymentMethodId"
|
|
||||||
:to-currency-due="srvModel.btcDue * (1 + (@settings.AmountMarkupPercentage / 100)) "
|
|
||||||
:to-currency-address="srvModel.btcAddress">
|
|
||||||
<iframe :src="url" style="min-height:600px;width:100%;border:none" allowtransparency="true"></iframe>
|
|
||||||
</fixed-float>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,12 +0,0 @@
|
|||||||
@using BTCPayServer.Plugins.FixedFloat
|
|
||||||
@using Newtonsoft.Json
|
|
||||||
@using Newtonsoft.Json.Linq
|
|
||||||
@inject FixedFloatService FixedFloatService
|
|
||||||
@{
|
|
||||||
var storeId = ((JObject)JObject.Parse(JsonConvert.SerializeObject(Model)))["StoreId"].Value<string>();
|
|
||||||
var settings = await FixedFloatService.GetFixedFloatForStore(storeId);
|
|
||||||
if (settings?.Enabled is true)
|
|
||||||
{
|
|
||||||
<script src="~/Resources/js/fixedFloatComponent.js"></script>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,15 @@
|
|||||||
|
@using BTCPayServer.Abstractions.TagHelpers
|
||||||
|
@using BTCPayServer.Payments
|
||||||
@using BTCPayServer.Plugins.FixedFloat
|
@using BTCPayServer.Plugins.FixedFloat
|
||||||
@inject FixedFloatService FixedFloatService
|
@inject FixedFloatService FixedFloatService
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||||
@{
|
@{
|
||||||
var storeId = Model.StoreId;
|
var storeId = Model.StoreId;
|
||||||
var settings = await FixedFloatService.GetFixedFloatForStore(storeId);
|
var settings = await FixedFloatService.GetFixedFloatForStore(storeId);
|
||||||
var preferredTargetPaymentMethodId = string.IsNullOrEmpty(settings?.PreferredTargetPaymentMethodId) ? null : Model.AvailableCryptos.Any(crypto => crypto.PaymentMethodId == settings.PreferredTargetPaymentMethodId) ? settings.PreferredTargetPaymentMethodId : null;
|
var preferredTargetPaymentMethodId =
|
||||||
|
string.IsNullOrEmpty(settings?.PreferredTargetPaymentMethodId) ? null :
|
||||||
|
Model.AvailablePaymentMethods.Any(crypto => crypto.PaymentMethodId.ToString() == PaymentMethodId.TryParse(settings.PreferredTargetPaymentMethodId)?.ToString()) ?
|
||||||
|
settings.PreferredTargetPaymentMethodId : null;
|
||||||
}
|
}
|
||||||
@if (settings?.Enabled is true)
|
@if (settings?.Enabled is true)
|
||||||
{
|
{
|
||||||
@@ -41,7 +46,7 @@
|
|||||||
const result = this.$parent.paymentMethodId === "FixedFloat";
|
const result = this.$parent.paymentMethodId === "FixedFloat";
|
||||||
|
|
||||||
if(this.preferredToCurrency && this.model.paymentMethodId !== this.preferredToCurrency){
|
if(this.preferredToCurrency && this.model.paymentMethodId !== this.preferredToCurrency){
|
||||||
if (this.model.onChainWithLnInvoiceFallback && this.model.paymentMethodId === "BTC"){
|
if (this.model.onChainWithLnInvoiceFallback && this.model.paymentMethodId === "BTC-CHAIN"){
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
this.$parent.paymentMethodId = this.preferredToCurrency;
|
this.$parent.paymentMethodId = this.preferredToCurrency;
|
||||||
@@ -53,7 +58,7 @@
|
|||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
lightning () {
|
lightning () {
|
||||||
if (!this.model.onChainWithLnInvoiceFallback || this.model.paymentMethodId !== "BTC"){
|
if (!this.model.onChainWithLnInvoiceFallback || this.model.paymentMethodId !== "BTC-CHAIN"){
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const index = this.model.invoiceBitcoinUrl.indexOf("lightning=");
|
const index = this.model.invoiceBitcoinUrl.indexOf("lightning=");
|
||||||
@@ -63,9 +68,9 @@
|
|||||||
return this.model.invoiceBitcoinUrl.slice(index + "lightning=".length);
|
return this.model.invoiceBitcoinUrl.slice(index + "lightning=".length);
|
||||||
},
|
},
|
||||||
url () {
|
url () {
|
||||||
|
debugger;
|
||||||
const address= this.lightning || this.model.btcAddress;
|
const address= this.lightning || this.model.address;
|
||||||
return "https://widget.fixedfloat.com/?" +
|
return "https://widget.ff.io/?" +
|
||||||
`to=${this.settleMethodId}` +
|
`to=${this.settleMethodId}` +
|
||||||
"&lockReceive=true&ref=fkbyt39c" +
|
"&lockReceive=true&ref=fkbyt39c" +
|
||||||
`&address=${address}` +
|
`&address=${address}` +
|
||||||
@@ -76,9 +81,9 @@
|
|||||||
return this.model.paymentMethodId;
|
return this.model.paymentMethodId;
|
||||||
},
|
},
|
||||||
settleMethodId () {
|
settleMethodId () {
|
||||||
return this.currency.endsWith('LightningLike') || this.currency.endsWith('LNURLPay') || this.lightning
|
return this.currency.endsWith('LN') || this.currency.endsWith('LNURL') || this.lightning
|
||||||
? 'BTCLN'
|
? 'BTCLN'
|
||||||
: this.currency.replace('_BTCLike', '').replace('_MoneroLike', '').replace('_ZcashLike', '').toUpperCase();
|
: this.currency.replace('-CHAIN', '').replace('_CHAIN', '').toUpperCase();
|
||||||
},
|
},
|
||||||
explicitQuery (){
|
explicitQuery (){
|
||||||
const isExplicit = !!this.explicitId;
|
const isExplicit = !!this.explicitId;
|
||||||
@@ -91,7 +96,7 @@
|
|||||||
: `&lockType=true&hideType=true&lockAmount=true&toAmount=${this.amountDue}`;
|
: `&lockType=true&hideType=true&lockAmount=true&toAmount=${this.amountDue}`;
|
||||||
},
|
},
|
||||||
amountDue () {
|
amountDue () {
|
||||||
return this.model.btcDue * (1 + (markupPercentage / 100));
|
return this.model.due * (1 + (markupPercentage / 100));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@using BTCPayServer.Plugins.FixedFloat
|
@using BTCPayServer.Plugins.FixedFloat
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||||
@inject FixedFloatService FixedFloatService
|
@inject FixedFloatService FixedFloatService
|
||||||
@{
|
@{
|
||||||
const string id = "FixedFloat";
|
const string id = "FixedFloat";
|
||||||
|
|||||||
@@ -1,13 +0,0 @@
|
|||||||
@using BTCPayServer.Plugins.FixedFloat
|
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
|
||||||
@inject FixedFloatService FixedFloatService
|
|
||||||
@{
|
|
||||||
var storeId = Model.StoreId;
|
|
||||||
var settings = await FixedFloatService.GetFixedFloatForStore(storeId);
|
|
||||||
if (settings?.Enabled is true)
|
|
||||||
{
|
|
||||||
<div class="payment-tabs__tab py-0" id="FixedFloat-tab" v-on:click="switchTab('FixedFloat')" v-bind:class="{ 'active': currentTab == 'FixedFloat'}">
|
|
||||||
<span>{{$t("Altcoins (FixedFloat)")}}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,43 +0,0 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Razor">
|
|
||||||
|
|
||||||
<PropertyGroup>
|
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
|
||||||
<LangVersion>10</LangVersion>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- Plugin specific properties -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<Product>LDK</Product>
|
|
||||||
<Description>The way lightning's meant to be</Description>
|
|
||||||
<Version>1.0.0</Version>
|
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
|
||||||
</PropertyGroup>
|
|
||||||
<!-- Plugin development properties -->
|
|
||||||
<PropertyGroup>
|
|
||||||
<AddRazorSupportForMvc>true</AddRazorSupportForMvc>
|
|
||||||
<PreserveCompilationContext>false</PreserveCompilationContext>
|
|
||||||
<GenerateEmbeddedFilesManifest>true</GenerateEmbeddedFilesManifest>
|
|
||||||
</PropertyGroup>
|
|
||||||
|
|
||||||
<!-- This will make sure that referencing BTCPayServer doesn't put any artifact in the published directory -->
|
|
||||||
<ItemDefinitionGroup>
|
|
||||||
<ProjectReference>
|
|
||||||
<Properties>StaticWebAssetsEnabled=false</Properties>
|
|
||||||
<Private>false</Private>
|
|
||||||
<ExcludeAssets>runtime;native;build;buildTransitive;contentFiles</ExcludeAssets>
|
|
||||||
</ProjectReference>
|
|
||||||
</ItemDefinitionGroup>
|
|
||||||
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<EmbeddedResource Include="Resources\**" />
|
|
||||||
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Resources" />
|
|
||||||
</ItemGroup>
|
|
||||||
<ItemGroup>
|
|
||||||
<PackageReference Include="org.ldk" Version="0.0.118-alpha1" />
|
|
||||||
</ItemGroup>
|
|
||||||
</Project>
|
|
||||||
|
|
||||||
@@ -1,232 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.IO;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Amazon.Runtime.Internal.Util;
|
|
||||||
using BTCPayServer;
|
|
||||||
using BTCPayServer.Abstractions.Models;
|
|
||||||
using BTCPayServer.Configuration;
|
|
||||||
using BTCPayServer.Services;
|
|
||||||
using Microsoft.Extensions.Hosting;
|
|
||||||
using Microsoft.Extensions.Logging;
|
|
||||||
using Microsoft.Extensions.Options;
|
|
||||||
using NBitcoin;
|
|
||||||
using NBXplorer;
|
|
||||||
using org.ldk.enums;
|
|
||||||
using org.ldk.structs;
|
|
||||||
using enums_Network = org.ldk.enums.Network;
|
|
||||||
using ILogger = Microsoft.Extensions.Logging.ILogger;
|
|
||||||
using Logger = org.ldk.structs.Logger;
|
|
||||||
using Network = NBitcoin.Network;
|
|
||||||
using OutPoint = org.ldk.structs.OutPoint;
|
|
||||||
using Path = System.IO.Path;
|
|
||||||
|
|
||||||
public class LDKService : IHostedService, PersistInterface, BroadcasterInterfaceInterface, FeeEstimatorInterface, EventHandlerInterface, LoggerInterface, FilterInterface
|
|
||||||
{
|
|
||||||
private readonly ILogger<LDKService> _logger;
|
|
||||||
private readonly IFeeProviderFactory _feeProviderFactory;
|
|
||||||
private readonly IOptions<DataDirectories> _dataDirectories;
|
|
||||||
private readonly BTCPayNetwork _network;
|
|
||||||
private readonly ExplorerClient _explorerClient;
|
|
||||||
private readonly string _workDir;
|
|
||||||
private readonly enums_Network _ldkNetwork;
|
|
||||||
private readonly Logger _ldklogger;
|
|
||||||
private readonly FeeEstimator _ldkfeeEstimator;
|
|
||||||
private readonly BroadcasterInterface _ldkbroadcaster;
|
|
||||||
private readonly Persist _ldkpersist;
|
|
||||||
private readonly Filter _ldkfilter;
|
|
||||||
private readonly NetworkGraph _ldkNetworkGraph;
|
|
||||||
private readonly ChainMonitor _ldkChainMonitor;
|
|
||||||
|
|
||||||
public LDKService(BTCPayNetworkProvider btcPayNetworkProvider,
|
|
||||||
ExplorerClientProvider explorerClientProvider,
|
|
||||||
ILogger<LDKService> logger,
|
|
||||||
IFeeProviderFactory feeProviderFactory,
|
|
||||||
IOptions<DataDirectories> dataDirectories)
|
|
||||||
{
|
|
||||||
_logger = logger;
|
|
||||||
_feeProviderFactory = feeProviderFactory;
|
|
||||||
_dataDirectories = dataDirectories;
|
|
||||||
|
|
||||||
_network = btcPayNetworkProvider.GetNetwork<BTCPayNetwork>("BTC");
|
|
||||||
_explorerClient = explorerClientProvider.GetExplorerClient(_network);
|
|
||||||
_workDir = GetWorkDir();
|
|
||||||
Directory.CreateDirectory(_workDir);
|
|
||||||
|
|
||||||
_ldkNetwork = GetLdkNetwork(_network.NBitcoinNetwork);
|
|
||||||
_ldklogger = Logger.new_impl(this);
|
|
||||||
_ldkfeeEstimator = FeeEstimator.new_impl(this);
|
|
||||||
_ldkbroadcaster = BroadcasterInterface.new_impl(this);
|
|
||||||
_ldkpersist = Persist.new_impl(this);
|
|
||||||
_ldkfilter = Filter.new_impl(this);
|
|
||||||
|
|
||||||
_ldkNetworkGraph = NetworkGraph.of(_ldkNetwork, _ldklogger);
|
|
||||||
_ldkChainMonitor = ChainMonitor.of( Option_FilterZ.Option_FilterZ_Some.some(_ldkfilter), _ldkbroadcaster, _ldklogger, _ldkfeeEstimator, _ldkpersist);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private static enums_Network GetLdkNetwork(Network network)
|
|
||||||
{
|
|
||||||
enums_Network? ldkNetwork = null;
|
|
||||||
if (network.ChainName == ChainName.Mainnet)
|
|
||||||
ldkNetwork = org.ldk.enums.Network.LDKNetwork_Bitcoin;
|
|
||||||
else if (network.ChainName == ChainName.Testnet)
|
|
||||||
ldkNetwork = org.ldk.enums.Network.LDKNetwork_Testnet;
|
|
||||||
else if (network.ChainName == ChainName.Regtest)
|
|
||||||
ldkNetwork = org.ldk.enums.Network.LDKNetwork_Regtest;
|
|
||||||
|
|
||||||
return ldkNetwork ?? throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private string GetWorkDir()
|
|
||||||
{
|
|
||||||
var dir = _dataDirectories.Value.DataDir;
|
|
||||||
return Path.Combine(dir, "Plugins", "LDK");
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StartAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
public async Task StopAsync(CancellationToken cancellationToken)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public int get_est_sat_per_1000_weight(ConfirmationTarget confirmation_target)
|
|
||||||
{
|
|
||||||
var feeProvider = _feeProviderFactory.CreateFeeProvider(_network);
|
|
||||||
var targetBlocks = confirmation_target switch
|
|
||||||
{
|
|
||||||
ConfirmationTarget.LDKConfirmationTarget_OnChainSweep => 30, // High priority (10-50 blocks)
|
|
||||||
ConfirmationTarget
|
|
||||||
.LDKConfirmationTarget_MaxAllowedNonAnchorChannelRemoteFee =>
|
|
||||||
20, // Moderate to high priority (small multiple of high-priority estimate)
|
|
||||||
ConfirmationTarget
|
|
||||||
.LDKConfirmationTarget_MinAllowedAnchorChannelRemoteFee =>
|
|
||||||
12, // Moderate priority (long-term mempool minimum or medium-priority)
|
|
||||||
ConfirmationTarget
|
|
||||||
.LDKConfirmationTarget_MinAllowedNonAnchorChannelRemoteFee =>
|
|
||||||
12, // Moderate priority (medium-priority feerate)
|
|
||||||
ConfirmationTarget.LDKConfirmationTarget_AnchorChannelFee => 6, // Lower priority (can be bumped later)
|
|
||||||
ConfirmationTarget
|
|
||||||
.LDKConfirmationTarget_NonAnchorChannelFee => 20, // Moderate to high priority (high-priority feerate)
|
|
||||||
ConfirmationTarget.LDKConfirmationTarget_ChannelCloseMinimum => 144, // Within a day or so (144-250 blocks)
|
|
||||||
_ => throw new ArgumentOutOfRangeException(nameof(confirmation_target), confirmation_target, null)
|
|
||||||
};
|
|
||||||
return (int) Math.Max(253, feeProvider.GetFeeRateAsync(targetBlocks).GetAwaiter().GetResult().FeePerK.Satoshi);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void log(Record record)
|
|
||||||
{
|
|
||||||
var level = record.get_level() switch
|
|
||||||
{
|
|
||||||
Level.LDKLevel_Trace => LogLevel.Trace,
|
|
||||||
Level.LDKLevel_Debug => LogLevel.Debug,
|
|
||||||
Level.LDKLevel_Info => LogLevel.Information,
|
|
||||||
Level.LDKLevel_Warn => LogLevel.Warning,
|
|
||||||
Level.LDKLevel_Error => LogLevel.Error,
|
|
||||||
Level.LDKLevel_Gossip => LogLevel.Trace,
|
|
||||||
};
|
|
||||||
_logger.Log(level, $"[{record.get_module_path()}] {record.get_args()}");
|
|
||||||
}
|
|
||||||
|
|
||||||
public void broadcast_transactions(byte[][] txs)
|
|
||||||
{
|
|
||||||
foreach (var tx in txs)
|
|
||||||
{
|
|
||||||
var loadedTx = Transaction.Load(tx, _explorerClient.Network.NBitcoinNetwork);
|
|
||||||
|
|
||||||
_explorerClient.Broadcast(loadedTx);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public ChannelMonitorUpdateStatus persist_new_channel(OutPoint channel_id, ChannelMonitor data,
|
|
||||||
MonitorUpdateId update_id)
|
|
||||||
{
|
|
||||||
var name = Convert.ToHexString(channel_id.write());
|
|
||||||
File.WriteAllBytes(Path.Combine(_workDir, name), data.write());
|
|
||||||
return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ChannelMonitorUpdateStatus update_persisted_channel(OutPoint channel_id, ChannelMonitorUpdate update,
|
|
||||||
ChannelMonitor data, MonitorUpdateId update_id)
|
|
||||||
{
|
|
||||||
var name = Convert.ToHexString(channel_id.write());
|
|
||||||
File.WriteAllBytes(Path.Combine(_workDir, name), data.write());
|
|
||||||
return ChannelMonitorUpdateStatus.LDKChannelMonitorUpdateStatus_Completed;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void handle_event(Event _event)
|
|
||||||
{
|
|
||||||
switch (_event)
|
|
||||||
{
|
|
||||||
case Event.Event_BumpTransaction eventBumpTransaction:
|
|
||||||
switch (eventBumpTransaction.bump_transaction)
|
|
||||||
{
|
|
||||||
case BumpTransactionEvent.BumpTransactionEvent_ChannelClose bumpTransactionEventChannelClose:
|
|
||||||
break;
|
|
||||||
case BumpTransactionEvent.BumpTransactionEvent_HTLCResolution bumpTransactionEventHtlcResolution:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException();
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
case Event.Event_ChannelClosed eventChannelClosed:
|
|
||||||
break;
|
|
||||||
case Event.Event_ChannelPending eventChannelPending:
|
|
||||||
break;
|
|
||||||
case Event.Event_ChannelReady eventChannelReady:
|
|
||||||
break;
|
|
||||||
case Event.Event_DiscardFunding eventDiscardFunding:
|
|
||||||
break;
|
|
||||||
case Event.Event_FundingGenerationReady eventFundingGenerationReady:
|
|
||||||
break;
|
|
||||||
case Event.Event_HTLCHandlingFailed eventHtlcHandlingFailed:
|
|
||||||
break;
|
|
||||||
case Event.Event_HTLCIntercepted eventHtlcIntercepted:
|
|
||||||
break;
|
|
||||||
case Event.Event_InvoiceRequestFailed eventInvoiceRequestFailed:
|
|
||||||
break;
|
|
||||||
case Event.Event_OpenChannelRequest eventOpenChannelRequest:
|
|
||||||
break;
|
|
||||||
case Event.Event_PaymentClaimable eventPaymentClaimable:
|
|
||||||
break;
|
|
||||||
case Event.Event_PaymentClaimed eventPaymentClaimed:
|
|
||||||
break;
|
|
||||||
case Event.Event_PaymentFailed eventPaymentFailed:
|
|
||||||
break;
|
|
||||||
case Event.Event_PaymentForwarded eventPaymentForwarded:
|
|
||||||
break;
|
|
||||||
case Event.Event_PaymentPathFailed eventPaymentPathFailed:
|
|
||||||
break;
|
|
||||||
case Event.Event_PaymentPathSuccessful eventPaymentPathSuccessful:
|
|
||||||
break;
|
|
||||||
case Event.Event_PaymentSent eventPaymentSent:
|
|
||||||
break;
|
|
||||||
case Event.Event_PendingHTLCsForwardable eventPendingHtlCsForwardable:
|
|
||||||
break;
|
|
||||||
case Event.Event_ProbeFailed eventProbeFailed:
|
|
||||||
break;
|
|
||||||
case Event.Event_ProbeSuccessful eventProbeSuccessful:
|
|
||||||
break;
|
|
||||||
case Event.Event_SpendableOutputs eventSpendableOutputs:
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw new ArgumentOutOfRangeException(nameof(_event));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register_tx(byte[] txid, byte[] script_pubkey)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void register_output(WatchedOutput output)
|
|
||||||
{
|
|
||||||
throw new NotImplementedException();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Liquid+</Product>
|
<Product>Liquid+</Product>
|
||||||
<Description>Enhanced support for the liquid network.</Description>
|
<Description>Enhanced support for the liquid network.</Description>
|
||||||
<Version>1.1.4</Version>
|
<Version>1.1.5</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,10 @@ using BTCPayServer.Abstractions.Extensions;
|
|||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Common;
|
using BTCPayServer.Common;
|
||||||
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Plugins.Altcoins;
|
using BTCPayServer.Plugins.Altcoins;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
using Microsoft.AspNetCore.Mvc.ViewFeatures;
|
||||||
@@ -25,20 +28,24 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
[AutoValidateAntiforgeryToken]
|
[AutoValidateAntiforgeryToken]
|
||||||
public class StoreLiquidController : Controller
|
public class StoreLiquidController : Controller
|
||||||
{
|
{
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
|
private readonly StoreRepository _storeRepository;
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
private readonly BTCPayServerClient _client;
|
|
||||||
private readonly IExplorerClientProvider _explorerClientProvider;
|
private readonly IExplorerClientProvider _explorerClientProvider;
|
||||||
|
|
||||||
public StoreLiquidController(BTCPayNetworkProvider btcPayNetworkProvider,
|
public StoreLiquidController(PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
BTCPayServerClient client, IExplorerClientProvider explorerClientProvider)
|
StoreRepository storeRepository, BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
|
IExplorerClientProvider explorerClientProvider)
|
||||||
{
|
{
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
|
_storeRepository = storeRepository;
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
_client = client;
|
|
||||||
_explorerClientProvider = explorerClientProvider;
|
_explorerClientProvider = explorerClientProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
[HttpGet("stores/{storeId}/liquid")]
|
[HttpGet("stores/{storeId}/liquid")]
|
||||||
public async Task<IActionResult> GenerateLiquidScript(string storeId, Dictionary<string, BitcoinExtKey> bitcoinExtKeys = null)
|
public async Task<IActionResult> GenerateLiquidScript(string storeId,
|
||||||
|
Dictionary<string, BitcoinExtKey> bitcoinExtKeys = null)
|
||||||
{
|
{
|
||||||
Dictionary<string, string> generated = new Dictionary<string, string>();
|
Dictionary<string, string> generated = new Dictionary<string, string>();
|
||||||
var allNetworks = _btcPayNetworkProvider.GetAll().OfType<ElementsBTCPayNetwork>()
|
var allNetworks = _btcPayNetworkProvider.GetAll().OfType<ElementsBTCPayNetwork>()
|
||||||
@@ -49,12 +56,19 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
.Distinct();
|
.Distinct();
|
||||||
Dictionary<string, BitcoinExtKey> privKeys = bitcoinExtKeys ?? new Dictionary<string, BitcoinExtKey>();
|
Dictionary<string, BitcoinExtKey> privKeys = bitcoinExtKeys ?? new Dictionary<string, BitcoinExtKey>();
|
||||||
|
|
||||||
|
var store = await _storeRepository.FindStore(storeId);
|
||||||
|
var pms = store
|
||||||
|
.GetPaymentMethodConfigs<DerivationSchemeSettings>(_paymentMethodHandlerDictionary)
|
||||||
|
.Select(pair => (PaymentMethodId: pair.Key, DerivationSchemeSettings: pair.Value,
|
||||||
|
CryptoCode: pair.Key.ToString().Split("-")[0])).ToArray();
|
||||||
|
|
||||||
var paymentMethods = (await _client.GetStoreOnChainPaymentMethods(storeId))
|
var paymentMethodsGroupedByNetworkCode =
|
||||||
|
pms
|
||||||
.Where(settings => allNetworkCodes.Contains(settings.CryptoCode))
|
.Where(settings => allNetworkCodes.Contains(settings.CryptoCode))
|
||||||
.GroupBy(data => _btcPayNetworkProvider.GetNetwork<ElementsBTCPayNetwork>(data.CryptoCode).NetworkCryptoCode);
|
.GroupBy(data =>
|
||||||
|
_btcPayNetworkProvider.GetNetwork<ElementsBTCPayNetwork>(data.CryptoCode).NetworkCryptoCode);
|
||||||
|
|
||||||
if (paymentMethods.Any() is false)
|
if (paymentMethodsGroupedByNetworkCode.Any() is false)
|
||||||
{
|
{
|
||||||
TempData.SetStatusMessageModel(new StatusMessageModel()
|
TempData.SetStatusMessageModel(new StatusMessageModel()
|
||||||
{
|
{
|
||||||
@@ -64,7 +78,7 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
return View(new GenerateLiquidImportScripts());
|
return View(new GenerateLiquidImportScripts());
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var der in paymentMethods)
|
foreach (var der in paymentMethodsGroupedByNetworkCode)
|
||||||
{
|
{
|
||||||
var network = _btcPayNetworkProvider.GetNetwork<ElementsBTCPayNetwork>(der.Key);
|
var network = _btcPayNetworkProvider.GetNetwork<ElementsBTCPayNetwork>(der.Key);
|
||||||
var nbxnet = network.NBXplorerNetwork;
|
var nbxnet = network.NBXplorerNetwork;
|
||||||
@@ -79,12 +93,12 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
generated.Add(der.Key, sb.ToString());
|
generated.Add(der.Key, sb.ToString());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
var derivationSchemesForNetwork = der.GroupBy(data => data.DerivationScheme);
|
|
||||||
|
var derivationSchemesForNetwork = der.GroupBy(data => data.DerivationSchemeSettings);
|
||||||
|
|
||||||
foreach (var paymentMethodDerivationScheme in derivationSchemesForNetwork)
|
foreach (var paymentMethodDerivationScheme in derivationSchemesForNetwork)
|
||||||
{
|
{
|
||||||
var derivatonScheme =
|
var derivatonScheme = paymentMethodDerivationScheme.Key.AccountDerivation;
|
||||||
nbxnet.DerivationStrategyFactory.Parse(paymentMethodDerivationScheme.Key);
|
|
||||||
var sameWalletCryptoCodes = paymentMethodDerivationScheme.Select(data => data.CryptoCode).ToArray();
|
var sameWalletCryptoCodes = paymentMethodDerivationScheme.Select(data => data.CryptoCode).ToArray();
|
||||||
var matchedExistingKey = privKeys.Where(pair => sameWalletCryptoCodes.Contains(pair.Key));
|
var matchedExistingKey = privKeys.Where(pair => sameWalletCryptoCodes.Contains(pair.Key));
|
||||||
BitcoinExtKey key = null;
|
BitcoinExtKey key = null;
|
||||||
@@ -94,14 +108,12 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
|
||||||
key = await explorerClient.GetMetadataAsync<BitcoinExtKey>(derivatonScheme,
|
key = await explorerClient.GetMetadataAsync<BitcoinExtKey>(derivatonScheme,
|
||||||
WellknownMetadataKeys.AccountHDKey);
|
WellknownMetadataKeys.AccountHDKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (key != null)
|
if (key != null)
|
||||||
{
|
{
|
||||||
|
|
||||||
foreach (var paymentMethodData in paymentMethodDerivationScheme)
|
foreach (var paymentMethodData in paymentMethodDerivationScheme)
|
||||||
{
|
{
|
||||||
privKeys.TryAdd(paymentMethodData.CryptoCode, key);
|
privKeys.TryAdd(paymentMethodData.CryptoCode, key);
|
||||||
@@ -139,14 +151,14 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
{
|
{
|
||||||
sb.AppendLine("elements-cli stop");
|
sb.AppendLine("elements-cli stop");
|
||||||
sb.AppendLine("elementsd -rescan");
|
sb.AppendLine("elementsd -rescan");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
generated.Add(der.Key, sb.ToString());
|
generated.Add(der.Key, sb.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
return View(new GenerateLiquidImportScripts()
|
return View(new GenerateLiquidImportScripts()
|
||||||
{
|
{
|
||||||
Wallets = paymentMethods.SelectMany(settings =>
|
Wallets = paymentMethodsGroupedByNetworkCode.SelectMany(settings =>
|
||||||
settings.Select(data =>
|
settings.Select(data =>
|
||||||
new GenerateLiquidImportScripts.GenerateLiquidImportScriptWalletKeyVm()
|
new GenerateLiquidImportScripts.GenerateLiquidImportScriptWalletKeyVm()
|
||||||
{
|
{
|
||||||
@@ -199,10 +211,9 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var der = HttpContext.GetStoreData()
|
||||||
|
.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, wallet.CryptoCode).AccountDerivation;
|
||||||
|
|
||||||
|
|
||||||
var der = n.NBXplorerNetwork.DerivationStrategyFactory.Parse(
|
|
||||||
(await _client.GetStoreOnChainPaymentMethod(storeId, wallet.CryptoCode)).DerivationScheme);
|
|
||||||
if (der.GetExtPubKeys().Count() > 1)
|
if (der.GetExtPubKeys().Count() > 1)
|
||||||
{
|
{
|
||||||
vm.AddModelError(scripts => scripts.Wallets[index].ManualKey, "cannot handle multsig", this);
|
vm.AddModelError(scripts => scripts.Wallets[index].ManualKey, "cannot handle multsig", this);
|
||||||
@@ -250,6 +261,7 @@ namespace BTCPayServer.Plugins.LiquidPlus.Controllers
|
|||||||
|
|
||||||
return await GenerateLiquidScript(storeId, privKeys);
|
return await GenerateLiquidScript(storeId, privKeys);
|
||||||
}
|
}
|
||||||
|
|
||||||
public class GenerateLiquidImportScripts
|
public class GenerateLiquidImportScripts
|
||||||
{
|
{
|
||||||
public class GenerateLiquidImportScriptWalletKeyVm
|
public class GenerateLiquidImportScriptWalletKeyVm
|
||||||
@@ -266,6 +278,7 @@ public class GenerateLiquidImportScripts
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace XX
|
namespace XX
|
||||||
{
|
{
|
||||||
public static class ModelStateExtensions
|
public static class ModelStateExtensions
|
||||||
@@ -275,7 +288,9 @@ namespace XX
|
|||||||
string message,
|
string message,
|
||||||
ControllerBase controller)
|
ControllerBase controller)
|
||||||
{
|
{
|
||||||
var provider = (ModelExpressionProvider)controller.HttpContext.RequestServices.GetService(typeof(ModelExpressionProvider));
|
var provider =
|
||||||
|
(ModelExpressionProvider) controller.HttpContext.RequestServices.GetService(
|
||||||
|
typeof(ModelExpressionProvider));
|
||||||
var key = provider.GetExpressionText(ex);
|
var key = provider.GetExpressionText(ex);
|
||||||
controller.ModelState.AddModelError(key, message);
|
controller.ModelState.AddModelError(key, message);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.12.0"}
|
new() {Identifier = nameof(BTCPayServer), Condition = ">=2.0.0"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
@@ -31,11 +31,11 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
|||||||
if (services.BootstrapServices.GetRequiredService<NBXplorerNetworkProvider>()
|
if (services.BootstrapServices.GetRequiredService<NBXplorerNetworkProvider>()
|
||||||
.GetFromCryptoCode("LBTC") is null || !services.BootstrapServices.GetRequiredService<SelectedChains>().Contains("LBTC"))
|
.GetFromCryptoCode("LBTC") is null || !services.BootstrapServices.GetRequiredService<SelectedChains>().Contains("LBTC"))
|
||||||
return;
|
return;
|
||||||
services.AddSingleton<IUIExtension>(new UIExtension("LiquidNav", "store-integrations-nav"));
|
services.AddUIExtension("store-integrations-nav", "LiquidNav");
|
||||||
services.AddSingleton<IUIExtension>(new UIExtension("OnChainWalletSetupLiquidExtension",
|
services.AddUIExtension("onchain-wallet-setup-post-body", "OnChainWalletSetupLiquidExtension");
|
||||||
"onchain-wallet-setup-post-body"));
|
services.AddUIExtension("server-nav", "CustomLiquidAssetsNavExtension");
|
||||||
services.AddSingleton<IUIExtension>(new UIExtension("CustomLiquidAssetsNavExtension", "server-nav"));
|
services.AddUIExtension("store-nav", "StoreNavLiquidExtension");
|
||||||
services.AddSingleton<IUIExtension>(new UIExtension("StoreNavLiquidExtension", "store-nav"));
|
|
||||||
services.AddSingleton<CustomLiquidAssetsRepository>();
|
services.AddSingleton<CustomLiquidAssetsRepository>();
|
||||||
|
|
||||||
|
|
||||||
@@ -53,12 +53,11 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
|||||||
CryptoCode: "LBTC"
|
CryptoCode: "LBTC"
|
||||||
})
|
})
|
||||||
.ImplementationInstance;
|
.ImplementationInstance;
|
||||||
|
|
||||||
|
var pmi = PaymentTypes.CHAIN.GetPaymentMethodId("LBTC");
|
||||||
var tlProvider = (TransactionLinkProviders.Entry) services.Single(descriptor =>
|
var tlProvider = (TransactionLinkProviders.Entry) services.Single(descriptor =>
|
||||||
descriptor.ServiceType == typeof(TransactionLinkProviders.Entry) &&
|
descriptor.ServiceType == typeof(TransactionLinkProviders.Entry) &&
|
||||||
descriptor.ImplementationInstance is TransactionLinkProviders.Entry
|
descriptor.ImplementationInstance is TransactionLinkProviders.Entry entry && entry.PaymentMethodId == pmi)
|
||||||
{
|
|
||||||
PaymentMethodId: {CryptoCode: "LBTC"}
|
|
||||||
})
|
|
||||||
.ImplementationInstance;
|
.ImplementationInstance;
|
||||||
settings.Items.ForEach(configuration =>
|
settings.Items.ForEach(configuration =>
|
||||||
|
|
||||||
@@ -80,7 +79,6 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
|||||||
NetworkCryptoCode = template.NetworkCryptoCode,
|
NetworkCryptoCode = template.NetworkCryptoCode,
|
||||||
DefaultSettings = template.DefaultSettings,
|
DefaultSettings = template.DefaultSettings,
|
||||||
ElectrumMapping = template.ElectrumMapping,
|
ElectrumMapping = template.ElectrumMapping,
|
||||||
BlockExplorerLink = template.BlockExplorerLink,
|
|
||||||
ReadonlyWallet = template.ReadonlyWallet,
|
ReadonlyWallet = template.ReadonlyWallet,
|
||||||
SupportLightning = false,
|
SupportLightning = false,
|
||||||
SupportPayJoin = false,
|
SupportPayJoin = false,
|
||||||
@@ -92,7 +90,7 @@ namespace BTCPayServer.Plugins.LiquidPlus
|
|||||||
VaultSupported = template.VaultSupported,
|
VaultSupported = template.VaultSupported,
|
||||||
MaxTrackedConfirmation = template.MaxTrackedConfirmation,
|
MaxTrackedConfirmation = template.MaxTrackedConfirmation,
|
||||||
SupportRBF = template.SupportRBF
|
SupportRBF = template.SupportRBF
|
||||||
}).AddTransactionLinkProvider(new PaymentMethodId(code, PaymentTypes.BTCLike), tlProvider.Provider);
|
}).AddTransactionLinkProvider(code, tlProvider.Provider);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,7 +34,7 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<EmbeddedResource Include="Resources\**" />
|
<EmbeddedResource Include="Resources\**" />
|
||||||
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
<ProjectReference Include="..\..\submodules\btcpayserver\BTCPayServer\BTCPayServer.csproj" />
|
||||||
<PackageReference Include="AsyncKeyedLock" Version="6.4.2" />
|
<PackageReference Include="AsyncKeyedLock" Version="7.0.1" />
|
||||||
<PackageReference Include="FlexLabs.EntityFrameworkCore.Upsert" Version="8.0.0" />
|
<PackageReference Include="FlexLabs.EntityFrameworkCore.Upsert" Version="8.0.0" />
|
||||||
<PackageReference Include="Laraue.EfCoreTriggers.PostgreSql" Version="8.0.3" />
|
<PackageReference Include="Laraue.EfCoreTriggers.PostgreSql" Version="8.0.3" />
|
||||||
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.10.0" />
|
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.10.0" />
|
||||||
|
|||||||
@@ -1,23 +1,29 @@
|
|||||||
using BTCPayServer.Abstractions.Contracts;
|
using System;
|
||||||
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using Laraue.EfCoreTriggers.PostgreSql.Extensions;
|
using BTCPayServer.Data;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using Microsoft.Extensions.Options;
|
using Microsoft.Extensions.Options;
|
||||||
|
using Npgsql.EntityFrameworkCore.PostgreSQL.Infrastructure;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.MicroNode;
|
namespace BTCPayServer.Plugins.MicroNode;
|
||||||
|
|
||||||
public class MicroNodeContextFactory : BaseDbContextFactory<MicroNodeContext>
|
public class MicroNodeContextFactory : BaseDbContextFactory<MicroNodeContext>
|
||||||
{
|
{
|
||||||
public MicroNodeContextFactory(IOptions<DatabaseOptions> options) : base(options, "BTCPayServer.Plugins.MicroNode")
|
private readonly ILoggerFactory _loggerFactory;
|
||||||
|
|
||||||
|
public MicroNodeContextFactory(IOptions<DatabaseOptions> options, ILoggerFactory loggerFactory) : base(options, "BTCPayServer.Plugins.MicroNode")
|
||||||
{
|
{
|
||||||
|
_loggerFactory = loggerFactory;
|
||||||
}
|
}
|
||||||
|
|
||||||
public override MicroNodeContext CreateContext()
|
public override MicroNodeContext CreateContext(Action<NpgsqlDbContextOptionsBuilder> npgsqlOptionsAction = null)
|
||||||
{
|
{
|
||||||
var builder = new DbContextOptionsBuilder<MicroNodeContext>();
|
var builder = new DbContextOptionsBuilder<MicroNodeContext>();
|
||||||
ConfigureBuilder(builder);
|
builder.UseLoggerFactory(_loggerFactory);
|
||||||
builder.UsePostgreSqlTriggers();
|
builder.AddInterceptors(MigrationInterceptor.Instance);
|
||||||
|
ConfigureBuilder(builder, npgsqlOptionsAction);
|
||||||
return new MicroNodeContext(builder.Options);
|
return new MicroNodeContext(builder.Options);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,6 +8,7 @@ using BTCPayServer.Client;
|
|||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@@ -17,14 +18,17 @@ namespace BTCPayServer.Plugins.MicroNode;
|
|||||||
[Route("plugins/micronode")]
|
[Route("plugins/micronode")]
|
||||||
public class MicroNodeController : Controller
|
public class MicroNodeController : Controller
|
||||||
{
|
{
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private readonly MicroNodeService _microNodeService;
|
private readonly MicroNodeService _microNodeService;
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
private readonly BTCPayNetworkProvider _networkProvider;
|
private readonly BTCPayNetworkProvider _networkProvider;
|
||||||
private readonly IAuthorizationService _authorizationService;
|
private readonly IAuthorizationService _authorizationService;
|
||||||
|
|
||||||
public MicroNodeController(MicroNodeService microNodeService, StoreRepository storeRepository,
|
public MicroNodeController(
|
||||||
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,MicroNodeService microNodeService, StoreRepository storeRepository,
|
||||||
BTCPayNetworkProvider networkProvider, IAuthorizationService authorizationService)
|
BTCPayNetworkProvider networkProvider, IAuthorizationService authorizationService)
|
||||||
{
|
{
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
_microNodeService = microNodeService;
|
_microNodeService = microNodeService;
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
_networkProvider = networkProvider;
|
_networkProvider = networkProvider;
|
||||||
@@ -66,11 +70,8 @@ public class MicroNodeController : Controller
|
|||||||
ModelState.AddModelError("masterStoreId", "Master cannot be the same as this store");
|
ModelState.AddModelError("masterStoreId", "Master cannot be the same as this store");
|
||||||
return View(settings);
|
return View(settings);
|
||||||
}
|
}
|
||||||
|
var pmi = PaymentTypes.LN.GetPaymentMethodId(network.CryptoCode);
|
||||||
var existing = store.GetSupportedPaymentMethods(_networkProvider).OfType<LightningSupportedPaymentMethod>()
|
var existing = store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary);
|
||||||
.FirstOrDefault(method =>
|
|
||||||
method.PaymentId.PaymentType == LightningPaymentType.Instance &&
|
|
||||||
method.PaymentId.CryptoCode == network.CryptoCode);
|
|
||||||
var isSet = settings?.Key is not null;
|
var isSet = settings?.Key is not null;
|
||||||
settings ??= new MicroNodeStoreSettings();
|
settings ??= new MicroNodeStoreSettings();
|
||||||
settings.Key ??= Guid.NewGuid().ToString();
|
settings.Key ??= Guid.NewGuid().ToString();
|
||||||
@@ -118,12 +119,10 @@ public class MicroNodeController : Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
existing ??= new LightningSupportedPaymentMethod()
|
existing ??= new();
|
||||||
{
|
|
||||||
CryptoCode = "BTC"
|
|
||||||
};
|
|
||||||
existing.SetLightningUrl(mlc);
|
existing.SetLightningUrl(mlc);
|
||||||
store.SetSupportedPaymentMethod(existing);
|
|
||||||
|
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], existing);
|
||||||
|
|
||||||
|
|
||||||
await _microNodeService.Set(storeId, settings, masterStoreId);
|
await _microNodeService.Set(storeId, settings, masterStoreId);
|
||||||
@@ -145,7 +144,7 @@ public class MicroNodeController : Controller
|
|||||||
|
|
||||||
if (isStoreSetToThisMicro)
|
if (isStoreSetToThisMicro)
|
||||||
{
|
{
|
||||||
store.SetSupportedPaymentMethod(existing.PaymentId, null);
|
store.SetPaymentMethodConfig(_paymentMethodHandlerDictionary[pmi], null);
|
||||||
await _storeRepository.UpdateStore(store);
|
await _storeRepository.UpdateStore(store);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class MicroNodePlugin:BaseBTCPayServerPlugin
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new () { Identifier = nameof(BTCPayServer), Condition = ">=1.12.0" }
|
new () { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,9 @@ using BTCPayServer.HostedServices;
|
|||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using Microsoft.EntityFrameworkCore;
|
using Microsoft.EntityFrameworkCore;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -34,6 +36,7 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
private readonly ILogger<MicroNodeService> _logger;
|
private readonly ILogger<MicroNodeService> _logger;
|
||||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||||
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private static readonly ConcurrentDictionary<string, long> ExpectedCounter = new();
|
private static readonly ConcurrentDictionary<string, long> ExpectedCounter = new();
|
||||||
private readonly TaskCompletionSource _init = new();
|
private readonly TaskCompletionSource _init = new();
|
||||||
private Dictionary<string, MicroNodeSettings> _ownerSettings;
|
private Dictionary<string, MicroNodeSettings> _ownerSettings;
|
||||||
@@ -53,6 +56,7 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
EventAggregator eventAggregator,
|
EventAggregator eventAggregator,
|
||||||
PullPaymentHostedService pullPaymentHostedService,
|
PullPaymentHostedService pullPaymentHostedService,
|
||||||
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
||||||
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
IServiceProvider serviceProvider) : base(eventAggregator, logger)
|
IServiceProvider serviceProvider) : base(eventAggregator, logger)
|
||||||
{
|
{
|
||||||
_network = btcPayNetworkProvider.BTC;
|
_network = btcPayNetworkProvider.BTC;
|
||||||
@@ -63,6 +67,7 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
_logger = logger;
|
_logger = logger;
|
||||||
_pullPaymentHostedService = pullPaymentHostedService;
|
_pullPaymentHostedService = pullPaymentHostedService;
|
||||||
_lightningNetworkOptions = lightningNetworkOptions;
|
_lightningNetworkOptions = lightningNetworkOptions;
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
_serviceProvider = serviceProvider;
|
_serviceProvider = serviceProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,17 +129,20 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
{
|
{
|
||||||
var b = payout.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
var b = payout.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
||||||
|
|
||||||
List<MicroTransaction> res = new();
|
List<MicroTransaction> res =
|
||||||
res.Add(new MicroTransaction()
|
[
|
||||||
|
new()
|
||||||
{
|
{
|
||||||
Id = payout.Id,
|
Id = payout.Id,
|
||||||
AccountId = key,
|
AccountId = key,
|
||||||
Amount = -LightMoney.Coins(b.CryptoAmount.Value).MilliSatoshi,
|
Amount = -LightMoney.Coins(payout.Amount!.Value).MilliSatoshi,
|
||||||
Accounted = payout.State != PayoutState.Cancelled,
|
Accounted = payout.State != PayoutState.Cancelled,
|
||||||
Active = payout.State is PayoutState.AwaitingApproval or PayoutState.AwaitingPayment
|
Active = payout.State is PayoutState.AwaitingApproval or PayoutState.AwaitingPayment
|
||||||
or PayoutState.InProgress,
|
or PayoutState.InProgress,
|
||||||
Type = "Payout"
|
Type = "Payout"
|
||||||
});
|
}
|
||||||
|
|
||||||
|
];
|
||||||
|
|
||||||
if (b.Metadata?.TryGetValue("Fee", out var microNode) is true && microNode.Value<decimal>() is { } payoutFee)
|
if (b.Metadata?.TryGetValue("Fee", out var microNode) is true && microNode.Value<decimal>() is { } payoutFee)
|
||||||
{
|
{
|
||||||
@@ -230,7 +238,7 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
await using var ctx = _microNodeContextFactory.CreateContext();
|
await using var ctx = _microNodeContextFactory.CreateContext();
|
||||||
for (int i = 0; i < 5; i++)
|
for (int i = 0; i < 5; i++)
|
||||||
{
|
{
|
||||||
var account = await ctx.MicroAccounts.FindAsync(key);
|
var account = await ctx.MicroAccounts.FindAsync(key, cancellation);
|
||||||
if (account is null)
|
if (account is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -336,9 +344,9 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var lightningConnectionString = store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
var pmi = PaymentTypes.LN.GetPaymentMethodId(_network.CryptoCode);
|
||||||
.OfType<LightningSupportedPaymentMethod>()
|
var lightningConnectionString = store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(pmi, _paymentMethodHandlerDictionary)
|
||||||
.FirstOrDefault(method => method.CryptoCode == _network.CryptoCode)?.CreateLightningClient(_network,
|
?.CreateLightningClient(_network,
|
||||||
_lightningNetworkOptions.Value, _serviceProvider.GetService<LightningClientFactoryService>());
|
_lightningNetworkOptions.Value, _serviceProvider.GetService<LightningClientFactoryService>());
|
||||||
return lightningConnectionString;
|
return lightningConnectionString;
|
||||||
}
|
}
|
||||||
@@ -616,7 +624,7 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
StoreId = masterClients.Key,
|
StoreId = masterClients.Key,
|
||||||
Destination = new LNURLPayClaimDestinaton(destination),
|
Destination = new LNURLPayClaimDestinaton(destination),
|
||||||
PreApprove = true,
|
PreApprove = true,
|
||||||
PaymentMethodId = new PaymentMethodId("BTC", LightningPaymentType.Instance),
|
PayoutMethodId = PayoutTypes.LN.GetPayoutMethodId("BTC"),
|
||||||
Metadata = JObject.FromObject(new
|
Metadata = JObject.FromObject(new
|
||||||
{
|
{
|
||||||
Source = $"MicroNode on store {storeId.Key}"
|
Source = $"MicroNode on store {storeId.Key}"
|
||||||
@@ -667,7 +675,7 @@ public class MicroNodeService : EventHostedServiceBase
|
|||||||
await base.StopAsync(cancellationToken);
|
await base.StopAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private ConcurrentDictionary<string, string> _keyToMasterStoreId = new();
|
private readonly ConcurrentDictionary<string, string> _keyToMasterStoreId = new();
|
||||||
|
|
||||||
public async Task Set(string storeId, MicroNodeStoreSettings? settings, string? masterStoreId = null)
|
public async Task Set(string storeId, MicroNodeStoreSettings? settings, string? masterStoreId = null)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Nostr</Product>
|
<Product>Nostr</Product>
|
||||||
<Description>NIP5 addresses, Zap support, Nostr Wallet Connect Lightning support</Description>
|
<Description>NIP5 addresses, Zap support, Nostr Wallet Connect Lightning support</Description>
|
||||||
<Version>1.1.13</Version>
|
<Version>1.1.14</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ namespace BTCPayServer.Plugins.NIP05
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.13.0"}
|
new() {Identifier = nameof(BTCPayServer), Condition = ">=2.0.0"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
<div class="col-xl-8 col-xxl-constrain">
|
<div class="col-xl-8 col-xxl-constrain">
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
<div class="form-group pt-2">
|
<div class="form-group pt-2">
|
||||||
<label asp-for="Name (does not need to be same as for a lightning address)" class="form-label"></label>
|
<label asp-for="Name" class="form-label">Name (does not need to be same as for a lightning address)</label>
|
||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<input asp-for="Name" class="form-control"/>
|
<input asp-for="Name" class="form-control"/>
|
||||||
<span class="input-group-text">@@@Context.Request.Host.ToUriComponent()@Context.Request.PathBase</span>
|
<span class="input-group-text">@@@Context.Request.Host.ToUriComponent()@Context.Request.PathBase</span>
|
||||||
|
|||||||
@@ -5,11 +5,9 @@ using System.Linq;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Events;
|
using BTCPayServer.Events;
|
||||||
using BTCPayServer.Models.InvoicingModels;
|
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
|
||||||
using Microsoft.Extensions.Caching.Memory;
|
using Microsoft.Extensions.Caching.Memory;
|
||||||
using Microsoft.Extensions.Hosting;
|
using Microsoft.Extensions.Hosting;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -24,6 +22,7 @@ public class Zapper : IHostedService
|
|||||||
{
|
{
|
||||||
record PendingZapEvent(string[] relays, NostrEvent nostrEvent);
|
record PendingZapEvent(string[] relays, NostrEvent nostrEvent);
|
||||||
|
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private readonly EventAggregator _eventAggregator;
|
private readonly EventAggregator _eventAggregator;
|
||||||
private readonly Nip5Controller _nip5Controller;
|
private readonly Nip5Controller _nip5Controller;
|
||||||
private readonly IMemoryCache _memoryCache;
|
private readonly IMemoryCache _memoryCache;
|
||||||
@@ -51,7 +50,9 @@ public class Zapper : IHostedService
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Zapper(EventAggregator eventAggregator,
|
public Zapper(
|
||||||
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
|
EventAggregator eventAggregator,
|
||||||
Nip5Controller nip5Controller,
|
Nip5Controller nip5Controller,
|
||||||
IMemoryCache memoryCache,
|
IMemoryCache memoryCache,
|
||||||
ILogger<Zapper> logger,
|
ILogger<Zapper> logger,
|
||||||
@@ -59,6 +60,7 @@ public class Zapper : IHostedService
|
|||||||
InvoiceRepository invoiceRepository,
|
InvoiceRepository invoiceRepository,
|
||||||
NostrClientPool nostrClientPool)
|
NostrClientPool nostrClientPool)
|
||||||
{
|
{
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
_eventAggregator = eventAggregator;
|
_eventAggregator = eventAggregator;
|
||||||
_nip5Controller = nip5Controller;
|
_nip5Controller = nip5Controller;
|
||||||
_memoryCache = memoryCache;
|
_memoryCache = memoryCache;
|
||||||
@@ -150,7 +152,8 @@ public class Zapper : IHostedService
|
|||||||
{
|
{
|
||||||
if (arg.EventCode != InvoiceEventCode.Completed && arg.EventCode != InvoiceEventCode.MarkedCompleted)
|
if (arg.EventCode != InvoiceEventCode.Completed && arg.EventCode != InvoiceEventCode.MarkedCompleted)
|
||||||
return;
|
return;
|
||||||
var pm = arg.Invoice.GetPaymentMethod(new PaymentMethodId("BTC", LNURLPayPaymentType.Instance));
|
var pmi = PaymentTypes.LNURL.GetPaymentMethodId("BTC");
|
||||||
|
var pm = arg.Invoice.GetPaymentPrompt(pmi);
|
||||||
if (pm is null)
|
if (pm is null)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
@@ -160,7 +163,6 @@ public class Zapper : IHostedService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pmd = (LNURLPayPaymentMethodDetails) pm.GetPaymentMethodDetails();
|
|
||||||
var settings = await GetSettings();
|
var settings = await GetSettings();
|
||||||
|
|
||||||
var zapRequestEvent = JsonSerializer.Deserialize<NostrEvent>(zapRequest);
|
var zapRequestEvent = JsonSerializer.Deserialize<NostrEvent>(zapRequest);
|
||||||
@@ -174,7 +176,7 @@ public class Zapper : IHostedService
|
|||||||
new NostrEventTag
|
new NostrEventTag
|
||||||
{
|
{
|
||||||
TagIdentifier = "bolt11",
|
TagIdentifier = "bolt11",
|
||||||
Data = new() {pmd.BOLT11}
|
Data = new() {pm.Destination}
|
||||||
},
|
},
|
||||||
|
|
||||||
new NostrEventTag()
|
new NostrEventTag()
|
||||||
|
|||||||
@@ -11,7 +11,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Prism</Product>
|
<Product>Prism</Product>
|
||||||
<Description>Automated value splits for Bitcoin.</Description>
|
<Description>Automated value splits for Bitcoin.</Description>
|
||||||
<Version>1.2.8</Version>
|
<Version>1.2.9</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
@using BTCPayServer.HostedServices
|
@using BTCPayServer.HostedServices
|
||||||
@using BTCPayServer.Payments
|
@using BTCPayServer.Payments
|
||||||
@using BTCPayServer.PayoutProcessors
|
@using BTCPayServer.PayoutProcessors
|
||||||
|
@using BTCPayServer.Payouts
|
||||||
@using Microsoft.AspNetCore.Http
|
@using Microsoft.AspNetCore.Http
|
||||||
@using Microsoft.AspNetCore.Routing
|
@using Microsoft.AspNetCore.Routing
|
||||||
@using Microsoft.Extensions.Logging
|
@using Microsoft.Extensions.Logging
|
||||||
@@ -28,7 +29,7 @@ else
|
|||||||
{
|
{
|
||||||
<datalist id="users">
|
<datalist id="users">
|
||||||
<option value="*">Catch-all lightning payments made against invoices in your store (excluding when other prisms are configured that capture those payments.)</option>
|
<option value="*">Catch-all lightning payments made against invoices in your store (excluding when other prisms are configured that capture those payments.)</option>
|
||||||
<option value="*@BitcoinPaymentType.Instance.ToStringNormalized()">Catch-all on-chain payments made against invoices in your store</option>
|
<option value="*@PaymentTypes.CHAIN.ToString()">Catch-all on-chain payments made against invoices in your store</option>
|
||||||
<option value="*All">Catch-all any payments made against invoices in your store</option>
|
<option value="*All">Catch-all any payments made against invoices in your store</option>
|
||||||
|
|
||||||
@foreach (var user in Users)
|
@foreach (var user in Users)
|
||||||
@@ -201,8 +202,8 @@ else
|
|||||||
|
|
||||||
public bool Loading { get; set; } = true;
|
public bool Loading { get; set; } = true;
|
||||||
public List<LightningAddressData> Users { get; set; } = new();
|
public List<LightningAddressData> Users { get; set; } = new();
|
||||||
public PaymentMethodId pmi { get; set; } = new("BTC", LightningPaymentType.Instance);
|
public PayoutMethodId pmi { get; set; } = PayoutTypes.LN.GetPayoutMethodId("BTC");
|
||||||
public PaymentMethodId pmichain { get; set; } = new("BTC", PaymentTypes.BTCLike);
|
public PayoutMethodId pmichain { get; set; } = PayoutTypes.CHAIN.GetPayoutMethodId("BTC");
|
||||||
public bool NoPayoutProcessors { get; set; }
|
public bool NoPayoutProcessors { get; set; }
|
||||||
|
|
||||||
private string PrismEditButtonsFilter { get; set; }
|
private string PrismEditButtonsFilter { get; set; }
|
||||||
@@ -224,7 +225,7 @@ else
|
|||||||
var fetchProcessors = PayoutProcessorService.GetProcessors(new PayoutProcessorService.PayoutProcessorQuery()
|
var fetchProcessors = PayoutProcessorService.GetProcessors(new PayoutProcessorService.PayoutProcessorQuery()
|
||||||
{
|
{
|
||||||
Stores = new[] {StoreId},
|
Stores = new[] {StoreId},
|
||||||
PaymentMethods = new[] {pmi.ToString(), pmichain.ToString()}
|
PayoutMethods = new[] {pmi, pmichain}
|
||||||
});
|
});
|
||||||
|
|
||||||
var tasks = new Task[]
|
var tasks = new Task[]
|
||||||
@@ -243,8 +244,8 @@ else
|
|||||||
EditContext.OnFieldChanged += FieldChanged;
|
EditContext.OnFieldChanged += FieldChanged;
|
||||||
SatBreaker.PrismUpdated += SatBreakerOnPrismUpdated;
|
SatBreaker.PrismUpdated += SatBreakerOnPrismUpdated;
|
||||||
//set NoPayoutProcessors to true if there are no configured payout processores for pmi and pmichain
|
//set NoPayoutProcessors to true if there are no configured payout processores for pmi and pmichain
|
||||||
NoPayoutProcessors = PayoutProcessorFactories.Any(factory => factory.GetSupportedPaymentMethods().Contains(pmi)) && (await fetchProcessors).All(data =>
|
NoPayoutProcessors = PayoutProcessorFactories.Any(factory => factory.GetSupportedPayoutMethods().Contains(pmi)) && (await fetchProcessors).All(data =>
|
||||||
!new[] {pmi, pmichain}.Contains(data.GetPaymentMethodId()));
|
!new[] {pmi, pmichain}.Contains(data.GetPayoutMethodId()));
|
||||||
|
|
||||||
Loading = false;
|
Loading = false;
|
||||||
await InvokeAsync(StateHasChanged);
|
await InvokeAsync(StateHasChanged);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Prism;
|
namespace BTCPayServer.Plugins.Prism;
|
||||||
|
|
||||||
@@ -19,7 +20,7 @@ public class LNURLPrismDestinationValidator : IPluginHookFilter
|
|||||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||||
{
|
{
|
||||||
Success = true,
|
Success = true,
|
||||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.LNURLPay)
|
PayoutMethodId = PayoutTypes.LN.GetPayoutMethodId("BTC")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -30,7 +31,7 @@ public class LNURLPrismDestinationValidator : IPluginHookFilter
|
|||||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||||
{
|
{
|
||||||
Success = true,
|
Success = true,
|
||||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.LNURLPay)
|
PayoutMethodId =PayoutTypes.LN.GetPayoutMethodId("BTC")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -45,5 +46,5 @@ public class LNURLPrismDestinationValidator : IPluginHookFilter
|
|||||||
public class PrismDestinationValidationResult
|
public class PrismDestinationValidationResult
|
||||||
{
|
{
|
||||||
public bool Success { get; set; }
|
public bool Success { get; set; }
|
||||||
public PaymentMethodId PaymentMethod { get; set; }
|
public PayoutMethodId PayoutMethodId { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,9 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections;
|
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payouts;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBXplorer.DerivationStrategy;
|
using NBXplorer.DerivationStrategy;
|
||||||
|
|
||||||
@@ -35,7 +34,7 @@ public class OnChainPrismClaimCreate : IPluginHookFilter
|
|||||||
{
|
{
|
||||||
claimRequest.Destination =
|
claimRequest.Destination =
|
||||||
new AddressClaimDestination(BitcoinAddress.Create(destStr, network.NBitcoinNetwork));
|
new AddressClaimDestination(BitcoinAddress.Create(destStr, network.NBitcoinNetwork));
|
||||||
claimRequest.PaymentMethodId = new PaymentMethodId("BTC", BitcoinPaymentType.Instance);
|
claimRequest.PayoutMethodId = PayoutTypes.CHAIN.GetPayoutMethodId("BTC");
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
@@ -48,7 +47,7 @@ public class OnChainPrismClaimCreate : IPluginHookFilter
|
|||||||
|
|
||||||
claimRequest.Destination =
|
claimRequest.Destination =
|
||||||
new AddressClaimDestination(add.Address);
|
new AddressClaimDestination(add.Address);
|
||||||
claimRequest.PaymentMethodId = new PaymentMethodId("BTC", BitcoinPaymentType.Instance);
|
claimRequest.PayoutMethodId = PayoutTypes.CHAIN.GetPayoutMethodId("BTC");
|
||||||
}
|
}
|
||||||
catch (Exception exception)
|
catch (Exception exception)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.Threading.Tasks;
|
|||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
using NBXplorer;
|
using NBXplorer;
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ public class OnChainPrismDestinationValidator : IPluginHookFilter
|
|||||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||||
{
|
{
|
||||||
Success = true,
|
Success = true,
|
||||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike)
|
PayoutMethodId = PayoutTypes.CHAIN.GetPayoutMethodId("BTC")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
@@ -46,7 +47,7 @@ public class OnChainPrismDestinationValidator : IPluginHookFilter
|
|||||||
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
return Task.FromResult<object>(new PrismDestinationValidationResult()
|
||||||
{
|
{
|
||||||
Success = true,
|
Success = true,
|
||||||
PaymentMethod = new PaymentMethodId("BTC", PaymentTypes.BTCLike)
|
PayoutMethodId =PayoutTypes.CHAIN.GetPayoutMethodId("BTC")
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
catch (Exception)
|
catch (Exception)
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Threading;
|
|||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
@@ -30,7 +31,7 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
|||||||
|
|
||||||
var parts = args1.ToLowerInvariant().Split(":", StringSplitOptions.RemoveEmptyEntries);
|
var parts = args1.ToLowerInvariant().Split(":", StringSplitOptions.RemoveEmptyEntries);
|
||||||
var project = "general_fund";
|
var project = "general_fund";
|
||||||
var paymentMethod = new PaymentMethodId("BTC", PaymentTypes.LightningLike);
|
var paymentMethod = PayoutTypes.LN.GetPayoutMethodId("BTC");
|
||||||
if (parts.Length > 1)
|
if (parts.Length > 1)
|
||||||
{
|
{
|
||||||
project = parts[1];
|
project = parts[1];
|
||||||
@@ -38,12 +39,11 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
|||||||
|
|
||||||
if (parts.Length > 2)
|
if (parts.Length > 2)
|
||||||
{
|
{
|
||||||
paymentMethod = PaymentMethodId.Parse(parts[2]);
|
paymentMethod = PayoutMethodId.Parse(parts[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var handler = _serviceProvider.GetServices<IPayoutHandler>().FindPayoutHandler(paymentMethod);
|
if (_serviceProvider.GetService<PayoutMethodHandlerDictionary>().TryGetValue(paymentMethod, out var handler))
|
||||||
if (handler is null)
|
|
||||||
{
|
{
|
||||||
result.Success = false;
|
result.Success = false;
|
||||||
}
|
}
|
||||||
@@ -63,7 +63,7 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
|||||||
var invoiceBtcpayModel = JObject.Parse(await httpClient.GetStringAsync(invoiceUrl).ConfigureAwait(false));
|
var invoiceBtcpayModel = JObject.Parse(await httpClient.GetStringAsync(invoiceUrl).ConfigureAwait(false));
|
||||||
var destination = invoiceBtcpayModel.Value<string>("btcAddress");
|
var destination = invoiceBtcpayModel.Value<string>("btcAddress");
|
||||||
|
|
||||||
var claimDestination = await handler.ParseClaimDestination(paymentMethod,destination, CancellationToken.None);
|
var claimDestination = await handler.ParseClaimDestination(destination, CancellationToken.None);
|
||||||
if (claimDestination.destination is null)
|
if (claimDestination.destination is null)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -72,7 +72,7 @@ public class OpenSatsDestinationValidator : IPluginHookFilter
|
|||||||
|
|
||||||
|
|
||||||
result.Success = true;
|
result.Success = true;
|
||||||
result.PaymentMethod = paymentMethod;
|
result.PayoutMethodId = paymentMethod;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
|
|||||||
@@ -1,18 +1,12 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Custodians;
|
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
|
||||||
using BTCPayServer.Data;
|
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payouts;
|
||||||
using Microsoft.EntityFrameworkCore;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using NBitcoin;
|
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Prism;
|
namespace BTCPayServer.Plugins.Prism;
|
||||||
@@ -41,7 +35,7 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
|||||||
|
|
||||||
var parts = args1.Split(":", StringSplitOptions.RemoveEmptyEntries);
|
var parts = args1.Split(":", StringSplitOptions.RemoveEmptyEntries);
|
||||||
var project = "opensats";
|
var project = "opensats";
|
||||||
var paymentMethod = new PaymentMethodId("BTC", PaymentTypes.LightningLike);
|
var paymentMethod = PayoutTypes.LN.GetPayoutMethodId("BTC");
|
||||||
if (parts.Length > 1)
|
if (parts.Length > 1)
|
||||||
{
|
{
|
||||||
project = parts[1];
|
project = parts[1];
|
||||||
@@ -49,11 +43,11 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
|||||||
|
|
||||||
if (parts.Length > 2)
|
if (parts.Length > 2)
|
||||||
{
|
{
|
||||||
paymentMethod = PaymentMethodId.Parse(parts[2]);
|
paymentMethod = PayoutMethodId.Parse(parts[2]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
var handler = _serviceProvider.GetServices<IPayoutHandler>().FindPayoutHandler(paymentMethod);
|
_serviceProvider.GetService<PayoutMethodHandlerDictionary>().TryGetValue(paymentMethod, out var handler);
|
||||||
if (handler is null)
|
if (handler is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
@@ -75,7 +69,7 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
|||||||
var destination = invoiceBtcpayModel.Value<string>("btcAddress");
|
var destination = invoiceBtcpayModel.Value<string>("btcAddress");
|
||||||
var receiptLink = invoiceBtcpayModel.Value<string>("receiptLink");
|
var receiptLink = invoiceBtcpayModel.Value<string>("receiptLink");
|
||||||
|
|
||||||
var claimDestination = await handler.ParseClaimDestination(paymentMethod,destination, CancellationToken.None);
|
var claimDestination = await handler.ParseClaimDestination(destination, CancellationToken.None);
|
||||||
if (claimDestination.destination is null)
|
if (claimDestination.destination is null)
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -88,7 +82,7 @@ public class OpenSatsPrismClaimCreate : IPluginHookFilter
|
|||||||
});
|
});
|
||||||
|
|
||||||
claimRequest.Destination = claimDestination.destination;
|
claimRequest.Destination = claimDestination.destination;
|
||||||
claimRequest.PaymentMethodId = paymentMethod;
|
claimRequest.PayoutMethodId = paymentMethod;
|
||||||
|
|
||||||
return claimRequest;
|
return claimRequest;
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,7 @@ public class PrismPlugin : BaseBTCPayServerPlugin
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.13.0"}
|
new() {Identifier = nameof(BTCPayServer), Condition = ">=2.0.0"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
|
|||||||
@@ -20,5 +20,5 @@ public class PrismDestination
|
|||||||
public string Destination { get; set; }
|
public string Destination { get; set; }
|
||||||
public decimal? Reserve { get; set; }
|
public decimal? Reserve { get; set; }
|
||||||
public long? SatThreshold { get; set; }
|
public long? SatThreshold { get; set; }
|
||||||
public string? PaymentMethodId { get; set; }
|
public string? PayoutMethodId { get; set; }
|
||||||
}
|
}
|
||||||
@@ -13,6 +13,7 @@ using BTCPayServer.HostedServices;
|
|||||||
using BTCPayServer.Lightning;
|
using BTCPayServer.Lightning;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.Lightning;
|
using BTCPayServer.Payments.Lightning;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
@@ -47,13 +48,13 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
{
|
{
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
private readonly ILogger<SatBreaker> _logger;
|
private readonly ILogger<SatBreaker> _logger;
|
||||||
private readonly LightningAddressService _lightningAddressService;
|
|
||||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||||
private readonly LightningLikePayoutHandler _lightningLikePayoutHandler;
|
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
private readonly LightningClientFactoryService _lightningClientFactoryService;
|
private readonly LightningClientFactoryService _lightningClientFactoryService;
|
||||||
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
private readonly IOptions<LightningNetworkOptions> _lightningNetworkOptions;
|
||||||
private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings;
|
private readonly BTCPayNetworkJsonSerializerSettings _btcPayNetworkJsonSerializerSettings;
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
|
private readonly PayoutMethodHandlerDictionary _payoutMethodHandlerDictionary;
|
||||||
private readonly IPluginHookService _pluginHookService;
|
private readonly IPluginHookService _pluginHookService;
|
||||||
private Dictionary<string, PrismSettings> _prismSettings;
|
private Dictionary<string, PrismSettings> _prismSettings;
|
||||||
|
|
||||||
@@ -62,24 +63,24 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
public SatBreaker(StoreRepository storeRepository,
|
public SatBreaker(StoreRepository storeRepository,
|
||||||
EventAggregator eventAggregator,
|
EventAggregator eventAggregator,
|
||||||
ILogger<SatBreaker> logger,
|
ILogger<SatBreaker> logger,
|
||||||
LightningAddressService lightningAddressService,
|
|
||||||
PullPaymentHostedService pullPaymentHostedService,
|
PullPaymentHostedService pullPaymentHostedService,
|
||||||
LightningLikePayoutHandler lightningLikePayoutHandler,
|
|
||||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
LightningClientFactoryService lightningClientFactoryService,
|
LightningClientFactoryService lightningClientFactoryService,
|
||||||
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
IOptions<LightningNetworkOptions> lightningNetworkOptions,
|
||||||
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
BTCPayNetworkJsonSerializerSettings btcPayNetworkJsonSerializerSettings,
|
||||||
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
|
PayoutMethodHandlerDictionary payoutMethodHandlerDictionary,
|
||||||
IPluginHookService pluginHookService) : base(eventAggregator, logger)
|
IPluginHookService pluginHookService) : base(eventAggregator, logger)
|
||||||
{
|
{
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
_logger = logger;
|
_logger = logger;
|
||||||
_lightningAddressService = lightningAddressService;
|
|
||||||
_pullPaymentHostedService = pullPaymentHostedService;
|
_pullPaymentHostedService = pullPaymentHostedService;
|
||||||
_lightningLikePayoutHandler = lightningLikePayoutHandler;
|
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
_lightningClientFactoryService = lightningClientFactoryService;
|
_lightningClientFactoryService = lightningClientFactoryService;
|
||||||
_lightningNetworkOptions = lightningNetworkOptions;
|
_lightningNetworkOptions = lightningNetworkOptions;
|
||||||
_btcPayNetworkJsonSerializerSettings = btcPayNetworkJsonSerializerSettings;
|
_btcPayNetworkJsonSerializerSettings = btcPayNetworkJsonSerializerSettings;
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
|
_payoutMethodHandlerDictionary = payoutMethodHandlerDictionary;
|
||||||
_pluginHookService = pluginHookService;
|
_pluginHookService = pluginHookService;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -148,17 +149,25 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
|
|
||||||
foreach (var payout in storePayouts)
|
foreach (var payout in storePayouts)
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!pendingPayouts.TryGetValue(payout.Id, out var pendingPayout))
|
if (!pendingPayouts.TryGetValue(payout.Id, out var pendingPayout))
|
||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(payout.GetPayoutMethodId() is not { } payoutMethodId)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!_payoutMethodHandlerDictionary.TryGetValue(payoutMethodId, out var handler))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
long toCredit = 0;
|
long toCredit = 0;
|
||||||
switch (payout.State)
|
switch (payout.State)
|
||||||
{
|
{
|
||||||
case PayoutState.Completed:
|
case PayoutState.Completed:
|
||||||
|
|
||||||
var proof = _lightningLikePayoutHandler.ParseProof(payout) as PayoutLightningBlob;
|
var proof = handler.ParseProof(payout) as PayoutLightningBlob;
|
||||||
|
|
||||||
long? feePaid = null;
|
long? feePaid = null;
|
||||||
if (!string.IsNullOrEmpty(proof?.PaymentHash))
|
if (!string.IsNullOrEmpty(proof?.PaymentHash))
|
||||||
@@ -168,10 +177,10 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
var store = await _storeRepository.FindStore(payout.StoreDataId);
|
var store = await _storeRepository.FindStore(payout.StoreDataId);
|
||||||
|
|
||||||
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>("BTC");
|
var network = _btcPayNetworkProvider.GetNetwork<BTCPayNetwork>("BTC");
|
||||||
var id = new PaymentMethodId("BTC", LightningPaymentType.Instance);
|
var id = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||||
var existing = store.GetSupportedPaymentMethods(_btcPayNetworkProvider)
|
var existing =
|
||||||
.OfType<LightningSupportedPaymentMethod>()
|
store.GetPaymentMethodConfig<LightningPaymentMethodConfig>(id,
|
||||||
.FirstOrDefault(d => d.PaymentId == id);
|
_paymentMethodHandlerDictionary);
|
||||||
if (existing?.GetExternalLightningUrl() is { } connectionString)
|
if (existing?.GetExternalLightningUrl() is { } connectionString)
|
||||||
{
|
{
|
||||||
lnClient = _lightningClientFactoryService.Create(connectionString,
|
lnClient = _lightningClientFactoryService.Create(connectionString,
|
||||||
@@ -313,12 +322,16 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
private (Split, LightMoney)[] DetermineMatches(PrismSettings prismSettings, InvoiceEntity entity)
|
private (Split, LightMoney)[] DetermineMatches(PrismSettings prismSettings, InvoiceEntity entity)
|
||||||
{
|
{
|
||||||
//first check the primary thing - ln address
|
//first check the primary thing - ln address
|
||||||
var explicitPMI = new PaymentMethodId("BTC", LNURLPayPaymentType.Instance);
|
var explicitPMI = PaymentTypes.LNURL.GetPaymentMethodId("BTC");
|
||||||
var pm = entity.GetPaymentMethod(explicitPMI);
|
var pm = entity.GetPaymentPrompt(explicitPMI);
|
||||||
var pmd = pm?.GetPaymentMethodDetails() as LNURLPayPaymentMethodDetails;
|
|
||||||
List<(Split, LightMoney)> result = new();
|
var payments = entity.GetPayments(true).GroupBy(paymentEntity => paymentEntity.PaymentMethodId).ToArray();
|
||||||
|
List<(Split, LightMoney)> result = new();
|
||||||
|
if(_paymentMethodHandlerDictionary.TryGetValue(explicitPMI, out var handler) && pm is not null)
|
||||||
|
{
|
||||||
|
var pmd = handler.ParsePaymentPromptDetails(pm.Details) as LNURLPayPaymentMethodDetails;
|
||||||
|
|
||||||
|
|
||||||
var payments = entity.GetPayments(true).GroupBy(paymentEntity => paymentEntity.GetPaymentMethodId()).ToArray();
|
|
||||||
if (pmd?.ConsumedLightningAddress is not null)
|
if (pmd?.ConsumedLightningAddress is not null)
|
||||||
{
|
{
|
||||||
var address = pmd.ConsumedLightningAddress.Split("@")[0];
|
var address = pmd.ConsumedLightningAddress.Split("@")[0];
|
||||||
@@ -337,6 +350,7 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var catchAlls = prismSettings.Splits.Where(split => split.Source.StartsWith("*")).Select(split =>
|
var catchAlls = prismSettings.Splits.Where(split => split.Source.StartsWith("*")).Select(split =>
|
||||||
{
|
{
|
||||||
@@ -346,20 +360,25 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
switch (split.Source)
|
switch (split.Source)
|
||||||
{
|
{
|
||||||
case "*":
|
case "*":
|
||||||
pmi = new PaymentMethodId("BTC", PaymentTypes.LightningLike);
|
pmi = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||||
break;
|
break;
|
||||||
case "*All":
|
case "*All":
|
||||||
break;
|
break;
|
||||||
case var s when PaymentTypes.TryParse(s.Substring(1), out var pType):
|
case var s when s.StartsWith("*") && s.Substring(1) ==PaymentTypes.CHAIN.ToString():
|
||||||
|
pmi = PaymentTypes.CHAIN.GetPaymentMethodId("BTC");
|
||||||
pmi = new PaymentMethodId("BTC", pType);
|
break;
|
||||||
|
case var s2 when s2.StartsWith("*") && s2.Substring(1) ==PaymentTypes.LN.ToString():
|
||||||
|
pmi = PaymentTypes.LN.GetPaymentMethodId("BTC");
|
||||||
|
break;
|
||||||
|
case var s3 when s3.StartsWith("*") && s3.Substring(1) ==PaymentTypes.LNURL.ToString():
|
||||||
|
pmi = PaymentTypes.LNURL.GetPaymentMethodId("BTC");
|
||||||
break;
|
break;
|
||||||
case var s when !PaymentMethodId.TryParse(s.Substring(1), out pmi):
|
case var s when !PaymentMethodId.TryParse(s.Substring(1), out pmi):
|
||||||
valid = false;
|
valid = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pmi is not null && pmi.CryptoCode != "BTC")
|
if (pmi is not null && !pmi.ToString().StartsWith("BTC-"))
|
||||||
{
|
{
|
||||||
valid = false;
|
valid = false;
|
||||||
}
|
}
|
||||||
@@ -367,6 +386,7 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
return (pmi, valid, split);
|
return (pmi, valid, split);
|
||||||
}).Where(tuple => tuple.valid).ToDictionary(split => split.pmi, split => split.split);
|
}).Where(tuple => tuple.valid).ToDictionary(split => split.pmi, split => split.split);
|
||||||
|
|
||||||
|
|
||||||
while(payments.Any() || catchAlls.Any())
|
while(payments.Any() || catchAlls.Any())
|
||||||
{
|
{
|
||||||
decimal paymentSum;
|
decimal paymentSum;
|
||||||
@@ -511,9 +531,9 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
var pmi = string.IsNullOrEmpty(destinationSettings?.PaymentMethodId) ||
|
var pmi = string.IsNullOrEmpty(destinationSettings?.PayoutMethodId) ||
|
||||||
!PaymentMethodId.TryParse(destinationSettings?.PaymentMethodId, out var pmi2)
|
!PayoutMethodId.TryParse(destinationSettings?.PayoutMethodId, out var pmi2)
|
||||||
? new PaymentMethodId("BTC", LightningPaymentType.Instance)
|
? PayoutTypes.LN.GetPayoutMethodId("BTC")
|
||||||
: pmi2;
|
: pmi2;
|
||||||
|
|
||||||
var source = "Prism";
|
var source = "Prism";
|
||||||
@@ -526,7 +546,7 @@ namespace BTCPayServer.Plugins.Prism
|
|||||||
Destination = new PrismPlaceholderClaimDestination(destinationSettings?.Destination ?? destination),
|
Destination = new PrismPlaceholderClaimDestination(destinationSettings?.Destination ?? destination),
|
||||||
PreApprove = true,
|
PreApprove = true,
|
||||||
StoreId = storeId,
|
StoreId = storeId,
|
||||||
PaymentMethodId = pmi,
|
PayoutMethodId = pmi,
|
||||||
Value = Money.Satoshis(payoutAmount).ToDecimal(MoneyUnit.BTC),
|
Value = Money.Satoshis(payoutAmount).ToDecimal(MoneyUnit.BTC),
|
||||||
Metadata = JObject.FromObject(new
|
Metadata = JObject.FromObject(new
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>SideShift</Product>
|
<Product>SideShift</Product>
|
||||||
<Description>Allows you to embed a SideShift conversion screen to allow customers to pay with altcoins.</Description>
|
<Description>Allows you to embed a SideShift conversion screen to allow customers to pay with altcoins.</Description>
|
||||||
<Version>1.1.13</Version>
|
<Version>1.1.14</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -1,84 +0,0 @@
|
|||||||
using System;
|
|
||||||
using System.Net.Http;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using BTCPayServer.Data.Payouts.LightningLike;
|
|
||||||
using BTCPayServer.HostedServices;
|
|
||||||
using BTCPayServer.Lightning;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.SideShift;
|
|
||||||
|
|
||||||
public class PrismClaimCreate : IPluginHookFilter
|
|
||||||
{
|
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
|
||||||
private readonly BTCPayNetworkProvider _networkProvider;
|
|
||||||
public string Hook => "prism-claim-create";
|
|
||||||
|
|
||||||
public PrismClaimCreate(IHttpClientFactory httpClientFactory, BTCPayNetworkProvider networkProvider)
|
|
||||||
{
|
|
||||||
_httpClientFactory = httpClientFactory;
|
|
||||||
_networkProvider = networkProvider;
|
|
||||||
}
|
|
||||||
public async Task<object> Execute(object args)
|
|
||||||
{
|
|
||||||
var network = _networkProvider.GetNetwork<BTCPayNetwork>("BTC");
|
|
||||||
if (args is not ClaimRequest claimRequest || network is null)
|
|
||||||
{
|
|
||||||
return args;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (claimRequest.Destination?.ToString() is not { } args1 || !args1.StartsWith("sideshift:")) return args;
|
|
||||||
var request = JObject.Parse(args1.Substring("sideshift:".Length)).ToObject<PrismSideshiftDestination>();
|
|
||||||
if (!request.Valid())
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var client = _httpClientFactory.CreateClient("sideshift");
|
|
||||||
|
|
||||||
|
|
||||||
var shiftResponse = await client.PostAsJsonAsync("https://sideshift.ai/api/v2/shifts/variable", new
|
|
||||||
{
|
|
||||||
settleAddress = request.ShiftDestination,
|
|
||||||
affiliateId = "qg0OrfHJV",
|
|
||||||
settleMemo = request.ShiftMemo,
|
|
||||||
depositCoin = "BTC",
|
|
||||||
depositNetwork = request.SourceNetwork?? "lightning",
|
|
||||||
settleCoin = request.ShiftCoin,
|
|
||||||
settleNetwork = request.ShiftNetwork,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
if (!shiftResponse.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
var shift = await shiftResponse.Content.ReadAsAsync<SideShiftController.ShiftResponse>();
|
|
||||||
try
|
|
||||||
{
|
|
||||||
LNURL.LNURL.Parse(shift.depositAddress, out _);
|
|
||||||
claimRequest.Destination = new LNURLPayClaimDestinaton(shift.depositAddress);
|
|
||||||
claimRequest.Metadata = JObject.FromObject(new
|
|
||||||
{
|
|
||||||
Source = $"Prism->Sideshift",
|
|
||||||
SourceLink = $"https://sideshift.ai/orders/{shift.id}?openSupport=true",
|
|
||||||
});
|
|
||||||
return claimRequest;
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
if (BOLT11PaymentRequest.TryParse(shift.depositAddress, out var bolt11, network.NBitcoinNetwork))
|
|
||||||
{
|
|
||||||
claimRequest.Destination = new BoltInvoiceClaimDestination(shift.depositAddress, bolt11);
|
|
||||||
claimRequest.Metadata = JObject.FromObject(new
|
|
||||||
{
|
|
||||||
Source = $"Prism->Sideshift",
|
|
||||||
SourceLink = $"https://sideshift.ai/orders/{shift.id}?openSupport=true",
|
|
||||||
});
|
|
||||||
return claimRequest;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
using Newtonsoft.Json.Linq;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.SideShift;
|
|
||||||
|
|
||||||
public class PrismDestinationValidate : IPluginHookFilter
|
|
||||||
{
|
|
||||||
public string Hook => "prism-destination-validate";
|
|
||||||
public async Task<object> Execute(object args)
|
|
||||||
{
|
|
||||||
if (args is not string args1 || !args1.StartsWith("sideshift:")) return args;
|
|
||||||
var json = JObject.Parse(args1.Substring("sideshift:".Length)).ToObject<PrismSideshiftDestination>();
|
|
||||||
return json.Valid();
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,15 +0,0 @@
|
|||||||
using System.Threading.Tasks;
|
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.SideShift;
|
|
||||||
|
|
||||||
public class PrismEditFilter : IPluginHookFilter
|
|
||||||
{
|
|
||||||
public string Hook => "prism-edit-buttons";
|
|
||||||
|
|
||||||
public Task<object> Execute(object args)
|
|
||||||
{
|
|
||||||
return Task.FromResult<object>(( args??"") + "<button type='button' class=\"btn btn-primary\" data-bs-toggle=\"modal\" data-bs-target=\"#sideshiftModal\">Generate SideShift destination</button>");
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
namespace BTCPayServer.Plugins.SideShift;
|
|
||||||
|
|
||||||
public class PrismSideshiftDestination
|
|
||||||
{
|
|
||||||
public string ShiftCoin { get; set; }
|
|
||||||
public string ShiftNetwork { get; set; }
|
|
||||||
public string ShiftDestination { get; set; }
|
|
||||||
public string ShiftMemo { get; set; }
|
|
||||||
public string SourceNetwork { get; set; }
|
|
||||||
|
|
||||||
public bool Valid()
|
|
||||||
{
|
|
||||||
return !string.IsNullOrEmpty(ShiftCoin) && !string.IsNullOrEmpty(ShiftNetwork) &&
|
|
||||||
!string.IsNullOrEmpty(ShiftDestination);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -9,6 +9,7 @@ using BTCPayServer.Client.Models;
|
|||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
using Microsoft.AspNetCore.Mvc;
|
using Microsoft.AspNetCore.Mvc;
|
||||||
@@ -26,7 +27,7 @@ namespace BTCPayServer.Plugins.SideShift
|
|||||||
{
|
{
|
||||||
private readonly SideShiftService _sideShiftService;
|
private readonly SideShiftService _sideShiftService;
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly IEnumerable<IPayoutHandler> _payoutHandlers;
|
private readonly PayoutMethodHandlerDictionary _payoutMethodHandlerDictionary;
|
||||||
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
private readonly PullPaymentHostedService _pullPaymentHostedService;
|
||||||
private readonly BTCPayNetworkJsonSerializerSettings _serializerSettings;
|
private readonly BTCPayNetworkJsonSerializerSettings _serializerSettings;
|
||||||
private readonly ApplicationDbContextFactory _dbContextFactory;
|
private readonly ApplicationDbContextFactory _dbContextFactory;
|
||||||
@@ -34,13 +35,13 @@ namespace BTCPayServer.Plugins.SideShift
|
|||||||
public SideShiftController(
|
public SideShiftController(
|
||||||
SideShiftService sideShiftService,
|
SideShiftService sideShiftService,
|
||||||
IHttpClientFactory httpClientFactory,
|
IHttpClientFactory httpClientFactory,
|
||||||
IEnumerable<IPayoutHandler> payoutHandlers,
|
PayoutMethodHandlerDictionary payoutMethodHandlerDictionary,
|
||||||
PullPaymentHostedService pullPaymentHostedService,
|
PullPaymentHostedService pullPaymentHostedService,
|
||||||
BTCPayNetworkJsonSerializerSettings serializerSettings, ApplicationDbContextFactory dbContextFactory)
|
BTCPayNetworkJsonSerializerSettings serializerSettings, ApplicationDbContextFactory dbContextFactory)
|
||||||
{
|
{
|
||||||
_sideShiftService = sideShiftService;
|
_sideShiftService = sideShiftService;
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_payoutHandlers = payoutHandlers;
|
_payoutMethodHandlerDictionary = payoutMethodHandlerDictionary;
|
||||||
_pullPaymentHostedService = pullPaymentHostedService;
|
_pullPaymentHostedService = pullPaymentHostedService;
|
||||||
_serializerSettings = serializerSettings;
|
_serializerSettings = serializerSettings;
|
||||||
_dbContextFactory = dbContextFactory;
|
_dbContextFactory = dbContextFactory;
|
||||||
@@ -111,19 +112,23 @@ namespace BTCPayServer.Plugins.SideShift
|
|||||||
ModelState.AddModelError(nameof(request.Amount), "Amount must be specified");
|
ModelState.AddModelError(nameof(request.Amount), "Amount must be specified");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!PaymentMethodId.TryParse(request.PaymentMethod, out var pmi))
|
if (!PayoutMethodId.TryParse(request.PayoutMethodId, out var pmi))
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(request.PaymentMethod), "Invalid payment method");
|
ModelState.AddModelError(nameof(request.PayoutMethodId), "Invalid payout method");
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
handler = _payoutHandlers.FindPayoutHandler(pmi);
|
if (!_payoutMethodHandlerDictionary.TryGetValue(pmi, out handler))
|
||||||
if (handler == null)
|
|
||||||
{
|
{
|
||||||
ModelState.AddModelError(nameof(request.PaymentMethod), "Invalid payment method");
|
ModelState.AddModelError(nameof(request.PayoutMethodId), "Invalid payment method");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var isLN = pmi.ToString().EndsWith("-" +PayoutTypes.LN.Id);
|
||||||
|
if (isLN)
|
||||||
|
{
|
||||||
|
|
||||||
|
ModelState.AddModelError(nameof(request.PayoutMethodId), "SideShift does not support Lightning payouts");
|
||||||
|
}
|
||||||
if (!ModelState.IsValid)
|
if (!ModelState.IsValid)
|
||||||
{
|
{
|
||||||
return this.CreateValidationError(ModelState);
|
return this.CreateValidationError(ModelState);
|
||||||
@@ -166,13 +171,13 @@ namespace BTCPayServer.Plugins.SideShift
|
|||||||
// shiftResponse.EnsureSuccessStatusCode();
|
// shiftResponse.EnsureSuccessStatusCode();
|
||||||
// var shift = await shiftResponse.Content.ReadAsAsync<ShiftResponse>();
|
// var shift = await shiftResponse.Content.ReadAsAsync<ShiftResponse>();
|
||||||
|
|
||||||
|
var cryptoCode = pmi.ToString().Split('-')[0];
|
||||||
var shiftResponse = await client.PostAsJsonAsync("https://sideshift.ai/api/v2/shifts/variable", new
|
var shiftResponse = await client.PostAsJsonAsync("https://sideshift.ai/api/v2/shifts/variable", new
|
||||||
{
|
{
|
||||||
settleAddress = request.Destination,
|
settleAddress = request.Destination,
|
||||||
affiliateId = "qg0OrfHJV",
|
affiliateId = "qg0OrfHJV",
|
||||||
settleMemo = request.Memo,
|
settleMemo = request.Memo,
|
||||||
depositCoin = pmi.CryptoCode,
|
depositCoin = cryptoCode,
|
||||||
depositNetwork = pmi.PaymentType == LightningPaymentType.Instance ? "lightning" : null,
|
|
||||||
settleCoin = request.ShiftCurrency,
|
settleCoin = request.ShiftCurrency,
|
||||||
settleNetwork = request.ShiftNetwork,
|
settleNetwork = request.ShiftNetwork,
|
||||||
}
|
}
|
||||||
@@ -188,20 +193,20 @@ namespace BTCPayServer.Plugins.SideShift
|
|||||||
|
|
||||||
|
|
||||||
var destination =
|
var destination =
|
||||||
await handler.ParseAndValidateClaimDestination(pmi, shift.depositAddress, ppBlob,
|
await handler.ParseAndValidateClaimDestination(shift.depositAddress, ppBlob,
|
||||||
CancellationToken.None);
|
CancellationToken.None);
|
||||||
|
|
||||||
var claim = await _pullPaymentHostedService.Claim(new ClaimRequest()
|
var claim = await _pullPaymentHostedService.Claim(new ClaimRequest()
|
||||||
{
|
{
|
||||||
PullPaymentId = pullPaymentId,
|
PullPaymentId = pullPaymentId,
|
||||||
Destination = destination.destination,
|
Destination = destination.destination,
|
||||||
PaymentMethodId = pmi,
|
PayoutMethodId = pmi,
|
||||||
Value = request.Amount
|
Value = request.Amount
|
||||||
});
|
});
|
||||||
if (claim.Result == ClaimRequest.ClaimResult.Ok)
|
if (claim.Result == ClaimRequest.ClaimResult.Ok)
|
||||||
{
|
{
|
||||||
await using var ctx = _dbContextFactory.CreateContext();
|
await using var ctx = _dbContextFactory.CreateContext();
|
||||||
ppBlob.Description += $"<br/>The payout of {claim.PayoutData.Destination} will be forwarded to SideShift.ai for further conversion. Please go to <a href=\"https://sideshift.ai/orders/{shift.id}?openSupport=true\">the order page</a> for support.";
|
ppBlob.Description += $"<br/>The payout of {destination.destination} will be forwarded to SideShift.ai for further conversion. Please go to <a href=\"https://sideshift.ai/orders/{shift.id}?openSupport=true\">the order page</a> for support.";
|
||||||
pp.SetBlob(ppBlob);
|
pp.SetBlob(ppBlob);
|
||||||
ctx.Attach(pp).State = EntityState.Modified;
|
ctx.Attach(pp).State = EntityState.Modified;
|
||||||
await ctx.SaveChangesAsync();
|
await ctx.SaveChangesAsync();
|
||||||
@@ -242,19 +247,21 @@ namespace BTCPayServer.Plugins.SideShift
|
|||||||
private Client.Models.PayoutData ToModel(Data.PayoutData p)
|
private Client.Models.PayoutData ToModel(Data.PayoutData p)
|
||||||
{
|
{
|
||||||
var blob = p.GetBlob(_serializerSettings);
|
var blob = p.GetBlob(_serializerSettings);
|
||||||
var model = new Client.Models.PayoutData
|
var model = new Client.Models.PayoutData()
|
||||||
{
|
{
|
||||||
Id = p.Id,
|
Id = p.Id,
|
||||||
PullPaymentId = p.PullPaymentDataId,
|
PullPaymentId = p.PullPaymentDataId,
|
||||||
Date = p.Date,
|
Date = p.Date,
|
||||||
Amount = blob.Amount,
|
OriginalCurrency = p.OriginalCurrency,
|
||||||
PaymentMethodAmount = blob.CryptoAmount,
|
OriginalAmount = p.OriginalAmount,
|
||||||
|
PayoutCurrency = p.Currency,
|
||||||
|
PayoutAmount = p.Amount,
|
||||||
Revision = blob.Revision,
|
Revision = blob.Revision,
|
||||||
State = p.State,
|
State = p.State,
|
||||||
|
PayoutMethodId = p.PayoutMethodId,
|
||||||
|
PaymentProof = p.GetProofBlobJson(),
|
||||||
Destination = blob.Destination,
|
Destination = blob.Destination,
|
||||||
PaymentMethod = p.PaymentMethodId,
|
Metadata = blob.Metadata?? new JObject(),
|
||||||
CryptoCode = p.GetPaymentMethodId().CryptoCode,
|
|
||||||
PaymentProof = p.GetProofBlobJson()
|
|
||||||
};
|
};
|
||||||
return model;
|
return model;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Abstractions.Services;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.SideShift
|
namespace BTCPayServer.Plugins.SideShift
|
||||||
@@ -8,41 +7,22 @@ namespace BTCPayServer.Plugins.SideShift
|
|||||||
public class SideShiftPlugin : BaseBTCPayServerPlugin
|
public class SideShiftPlugin : BaseBTCPayServerPlugin
|
||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{ new() { Identifier = nameof(BTCPayServer), Condition = ">=2.0.0" }
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.12.0"}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
applicationBuilder.AddSingleton<SideShiftService>();
|
applicationBuilder.AddSingleton<SideShiftService>();
|
||||||
applicationBuilder.AddHostedService(provider => provider.GetService<SideShiftService>());
|
applicationBuilder.AddHostedService(provider => provider.GetService<SideShiftService>());
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/SideShiftNav",
|
|
||||||
"store-integrations-nav"));
|
applicationBuilder.AddUIExtension("store-integrations-nav","SideShift/SideShiftNav");
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/PullPaymentViewInsert",
|
applicationBuilder.AddUIExtension("pullpayment-foot","SideShift/PullPaymentViewInsert");
|
||||||
"pullpayment-foot"));
|
applicationBuilder.AddUIExtension("store-integrations-list", "SideShift/StoreIntegrationSideShiftOption");
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/StoreIntegrationSideShiftOption",
|
|
||||||
"store-integrations-list"));
|
|
||||||
// Checkout v2
|
// Checkout v2
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutPaymentMethodExtension",
|
applicationBuilder.AddUIExtension("checkout-payment-method", "SideShift/CheckoutPaymentMethodExtension");
|
||||||
"checkout-payment-method"));
|
applicationBuilder.AddUIExtension("checkout-payment","SideShift/CheckoutPaymentExtension");
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutPaymentExtension",
|
|
||||||
"checkout-payment"));
|
|
||||||
// Checkout Classic
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutContentExtension",
|
|
||||||
"checkout-bitcoin-post-content"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutContentExtension",
|
|
||||||
"checkout-lightning-post-content"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutTabExtension",
|
|
||||||
"checkout-bitcoin-post-tabs"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutTabExtension",
|
|
||||||
"checkout-lightning-post-tabs"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/CheckoutEnd",
|
|
||||||
"checkout-end"));
|
|
||||||
applicationBuilder.AddSingleton<IUIExtension>(new UIExtension("SideShift/PrismEnhance",
|
|
||||||
"prism-edit"));
|
|
||||||
applicationBuilder.AddSingleton<IPluginHookFilter, PrismDestinationValidate>();
|
|
||||||
applicationBuilder.AddSingleton<IPluginHookFilter, PrismClaimCreate>();
|
|
||||||
applicationBuilder.AddSingleton<IPluginHookFilter, PrismEditFilter>();
|
|
||||||
base.Execute(applicationBuilder);
|
base.Execute(applicationBuilder);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
@using BTCPayServer.Plugins.SideShift
|
|
||||||
@inject SideShiftService SideShiftService
|
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
|
||||||
|
|
||||||
@{
|
|
||||||
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
|
||||||
|
|
||||||
if (settings?.Enabled is true)
|
|
||||||
{
|
|
||||||
<div id="sideshift" class="bp-view payment manual-flow" :class="{ active: currentTab == 'undefined' || currentTab == 'sideshift' }">
|
|
||||||
<div class="manual__step-two__instructions">
|
|
||||||
<span>
|
|
||||||
{{$t("ConversionTab_BodyTop", srvModel)}}
|
|
||||||
<br/><br/>
|
|
||||||
{{$t("ConversionTab_BodyDesc", srvModel)}}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
<side-shift inline-template
|
|
||||||
:to-currency="srvModel.paymentMethodId"
|
|
||||||
:to-currency-due="srvModel.btcDue * (1 + (@settings.AmountMarkupPercentage / 100)) "
|
|
||||||
:to-currency-address="srvModel.btcAddress">
|
|
||||||
<a v-on:click="openDialog($event)" href="#" class="action-button btn btn-secondary rounded-pill w-100 mt-4">{{$t("Pay with SideShift")}}</a>
|
|
||||||
</side-shift>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
@using BTCPayServer.Plugins.SideShift
|
|
||||||
@inject BTCPayServer.Security.ContentSecurityPolicies csp
|
|
||||||
@inject SideShiftService SideShiftService
|
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
|
||||||
@{
|
|
||||||
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
|
||||||
if (settings?.Enabled is true)
|
|
||||||
{
|
|
||||||
csp.Add("script-src", "https://sideshift.ai");
|
|
||||||
csp.Add("script-src", "*.sideshift.ai");
|
|
||||||
<script src="~/Resources/js/sideShiftComponent.js"></script>
|
|
||||||
<script src="https://sideshift.ai/static/js/main.js" defer></script>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -2,19 +2,18 @@
|
|||||||
@using BTCPayServer.Payments
|
@using BTCPayServer.Payments
|
||||||
@inject BTCPayServer.Security.ContentSecurityPolicies csp
|
@inject BTCPayServer.Security.ContentSecurityPolicies csp
|
||||||
@inject SideShiftService SideShiftService
|
@inject SideShiftService SideShiftService
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||||
@{
|
@{
|
||||||
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
||||||
var preferredTargetPaymentMethodId = "";
|
PaymentMethodId preferredTargetPaymentMethodId = null;
|
||||||
if(!PaymentMethodId.TryParse(settings?.PreferredTargetPaymentMethodId, out var preferredPMI))
|
if(!PaymentMethodId.TryParse(settings?.PreferredTargetPaymentMethodId, out var preferredPMI))
|
||||||
{
|
{
|
||||||
preferredTargetPaymentMethodId = null;
|
preferredTargetPaymentMethodId = null;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
preferredTargetPaymentMethodId = Model.AvailableCryptos.FirstOrDefault(crypto =>
|
preferredTargetPaymentMethodId = Model.AvailablePaymentMethods.FirstOrDefault(crypto =>
|
||||||
crypto.PaymentMethodId == settings.PreferredTargetPaymentMethodId ||
|
crypto.PaymentMethodId == preferredPMI )?.PaymentMethodId;
|
||||||
(crypto.CryptoCode == preferredPMI.CryptoCode && crypto.PaymentMethodId.EndsWith(LNURLPayPaymentType.Instance.GetId()) || crypto.PaymentMethodId.EndsWith(LightningPaymentType.Instance.GetId())))?.PaymentMethodId;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@if (settings?.Enabled is true)
|
@if (settings?.Enabled is true)
|
||||||
@@ -25,7 +24,8 @@
|
|||||||
<template id="side-shift-checkout-template">
|
<template id="side-shift-checkout-template">
|
||||||
<div class="payment-box">
|
<div class="payment-box">
|
||||||
<p v-html="content"></p>
|
<p v-html="content"></p>
|
||||||
<button type="button" v-on:click="openDialog" class="btn btn-primary rounded-pill w-100">{{$t("Pay with SideShift")}}</button>
|
<p v-if="!settleMethodId" class="text-danger">Lightning is not supported via Sideshift. Select another payment method first, then come back.</p>
|
||||||
|
<button v-if="settleMethodId" type="button" v-on:click="openDialog" class="btn btn-primary rounded-pill w-100">{{$t("Pay with SideShift", {crryptoCode: settleMethodId})}}</button>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<script>
|
<script>
|
||||||
@@ -48,7 +48,7 @@
|
|||||||
},200)
|
},200)
|
||||||
|
|
||||||
if(this.preferredToCurrency && this.model.paymentMethodId !== this.preferredToCurrency){
|
if(this.preferredToCurrency && this.model.paymentMethodId !== this.preferredToCurrency){
|
||||||
if (this.model.onChainWithLnInvoiceFallback && this.model.paymentMethodId === "BTC"){
|
if (this.model.onChainWithLnInvoiceFallback && this.model.paymentMethodId === "BTC-CHAIN"){
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
this.$parent.paymentMethodId = this.preferredToCurrency;
|
this.$parent.paymentMethodId = this.preferredToCurrency;
|
||||||
@@ -58,16 +58,7 @@
|
|||||||
|
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
lightning () {
|
|
||||||
if (!this.model.onChainWithLnInvoiceFallback || this.model.paymentMethodId !== "BTC"){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
const index = this.model.invoiceBitcoinUrl.indexOf("lightning=");
|
|
||||||
if (index === -1){
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
return this.model.invoiceBitcoinUrl.slice(index + "lightning=".length);
|
|
||||||
},
|
|
||||||
content () {
|
content () {
|
||||||
return this.$i18n.i18next.t("conversion_body", this.model).replace(/\n/ig, '<br>');
|
return this.$i18n.i18next.t("conversion_body", this.model).replace(/\n/ig, '<br>');
|
||||||
},
|
},
|
||||||
@@ -76,16 +67,16 @@
|
|||||||
},
|
},
|
||||||
settleMethodId () {
|
settleMethodId () {
|
||||||
|
|
||||||
const toCurrency = this.currency.toLowerCase();
|
const toCurrency = this.currency.toUpperCase();
|
||||||
|
|
||||||
if (toCurrency === "lbtc") {
|
if (toCurrency === "lbtc") {
|
||||||
return 'liquid';
|
return 'liquid';
|
||||||
} else if (toCurrency === "usdt") {
|
} else if (toCurrency === "usdt") {
|
||||||
return "usdtla";
|
return "usdtla";
|
||||||
} else if (toCurrency.endsWith('lightninglike') || toCurrency.endsWith('lnurlpay') || this.lightning) {
|
} else if (toCurrency.endsWith('LN') || toCurrency.endsWith('LNURL')) {
|
||||||
return "ln";
|
return null;
|
||||||
} else {
|
} else {
|
||||||
return toCurrency.replace('_btclike', '').replace('_monerolike', '').replace('_zcashlike', '').toLowerCase();
|
return toCurrency.replace('-CHAIN', '').replace('_CHAIN', '').toLowerCase();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
type () {
|
type () {
|
||||||
@@ -96,16 +87,19 @@
|
|||||||
amountDue () {
|
amountDue () {
|
||||||
return this.model.isUnsetTopUp
|
return this.model.isUnsetTopUp
|
||||||
? undefined
|
? undefined
|
||||||
: this.model.btcDue * (1 + (@settings.AmountMarkupPercentage / 100));
|
: this.model.due * (1 + (@settings.AmountMarkupPercentage / 100));
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
methods: {
|
methods: {
|
||||||
openDialog () {
|
openDialog () {
|
||||||
|
if (!this.settleMethodId){
|
||||||
|
return;
|
||||||
|
}
|
||||||
window.__SIDESHIFT__ = {
|
window.__SIDESHIFT__ = {
|
||||||
parentAffiliateId: "qg0OrfHJV",
|
parentAffiliateId: "qg0OrfHJV",
|
||||||
defaultDepositMethodId: this.explicitId || undefined,
|
defaultDepositMethodId: this.explicitId || undefined,
|
||||||
defaultSettleMethodId: this.settleMethodId,
|
defaultSettleMethodId: this.settleMethodId,
|
||||||
settleAddress: this.lightning || this.model.btcAddress,
|
settleAddress: this.model.address,
|
||||||
settleAmount: this.amountDue,
|
settleAmount: this.amountDue,
|
||||||
type: this.type
|
type: this.type
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
@using BTCPayServer.Plugins.SideShift
|
@using BTCPayServer.Plugins.SideShift
|
||||||
@inject SideShiftService SideShiftService
|
@inject SideShiftService SideShiftService
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
@model BTCPayServer.Models.InvoicingModels.CheckoutModel
|
||||||
@{
|
@{
|
||||||
const string id = "SideShift";
|
const string id = "SideShift";
|
||||||
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
||||||
|
|||||||
@@ -1,12 +0,0 @@
|
|||||||
@using BTCPayServer.Plugins.SideShift
|
|
||||||
@inject SideShiftService SideShiftService
|
|
||||||
@model BTCPayServer.Models.InvoicingModels.PaymentModel
|
|
||||||
@{
|
|
||||||
var settings = await SideShiftService.GetSideShiftForInvoice(Model.InvoiceId, Model.StoreId);
|
|
||||||
if (settings?.Enabled is true)
|
|
||||||
{
|
|
||||||
<div class="payment-tabs__tab py-0" id="sideshift-tab" v-on:click="switchTab('sideshift')" v-bind:class="{ 'active': currentTab == 'sideshift'}" v-if="!srvModel.paymentMethodId.endsWith('LNURLPAY')">
|
|
||||||
<span>{{$t("Altcoins (SideShift)")}}</span>
|
|
||||||
</div>
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,212 +0,0 @@
|
|||||||
@using BTCPayServer.Abstractions.TagHelpers
|
|
||||||
@using BTCPayServer.Plugins.SideShift
|
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
|
||||||
@inject SideShiftService SideShiftService
|
|
||||||
@{
|
|
||||||
|
|
||||||
var coins = await SideShiftService.GetSettleCoins();
|
|
||||||
coins = coins.Where(tuple => new[] {SideShiftService.CoinType.VariableOnly, SideShiftService.CoinType.Both}.Contains(tuple.Type)).ToList();
|
|
||||||
if(coins.Any() is not true)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
<script>
|
|
||||||
|
|
||||||
const ssAvailableCoins = @Json.Serialize(coins.ToDictionary(tuple=> $"{tuple.CryptoCode}_{tuple.Network}",tuple =>
|
|
||||||
new {
|
|
||||||
coin = tuple.DisplayName,
|
|
||||||
code = tuple.CryptoCode,
|
|
||||||
memo = tuple.HasMemo,
|
|
||||||
network = tuple.Network
|
|
||||||
}));
|
|
||||||
document.addEventListener('DOMContentLoaded', (event) => {
|
|
||||||
if (new URLSearchParams(window.location.search).has("hidejunk")) {
|
|
||||||
localStorage.setItem('hidejunk', 'true');
|
|
||||||
}
|
|
||||||
if(localStorage.getItem("hidejunk")) {
|
|
||||||
|
|
||||||
[...document.querySelectorAll("#sscoin option")].forEach(option => {
|
|
||||||
const text = option.innerText.toLowerCase();
|
|
||||||
|
|
||||||
// Check if the option matches the criteria
|
|
||||||
const isMatch = (text.includes("bitcoin") || text.includes("tether") || text.includes("usd")) &&
|
|
||||||
!text.includes("bitcoincash");
|
|
||||||
|
|
||||||
// If it matches, show it; otherwise, hide it
|
|
||||||
//remove it
|
|
||||||
if (!isMatch)
|
|
||||||
option.remove();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
// const sideshiftDestinationButton = document.createElement("button");
|
|
||||||
// sideshiftDestinationButton.type= "button";
|
|
||||||
// sideshiftDestinationButton.className = "btn btn-primary btn-sm";
|
|
||||||
// sideshiftDestinationButton.innerText = "Generate SideShift destination";
|
|
||||||
// document.getElementById("add-prism").insertAdjacentElement("afterend", sideshiftDestinationButton);
|
|
||||||
|
|
||||||
// const modal = new bootstrap.Modal('#sideshiftModal');
|
|
||||||
// sideshiftDestinationButton.addEventListener("click", ev => modal.show());
|
|
||||||
const selectedSideShiftCoin = document.getElementById("sscoin");
|
|
||||||
const specifiedSideShiftDestination = document.getElementById("ssdest");
|
|
||||||
const specifiedSideShiftDepositNetwork = document.getElementById("ssdepositNetwork");
|
|
||||||
const specifiedSideShiftMemo= document.getElementById("ssmemo");
|
|
||||||
const shiftButton = document.getElementById("ssshift");
|
|
||||||
let selectedCoin = null;
|
|
||||||
const destinationContainer = document.getElementById("ss-dest-info");
|
|
||||||
specifiedSideShiftDestination.addEventListener("input", ev1 => {
|
|
||||||
|
|
||||||
document.getElementById("ss-result").style.display = "none";
|
|
||||||
if (isValid()){
|
|
||||||
shiftButton.removeAttribute("disabled");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
specifiedSideShiftMemo.addEventListener("input", ev1 => {
|
|
||||||
if (isValid()){
|
|
||||||
shiftButton.removeAttribute("disabled");
|
|
||||||
}else{
|
|
||||||
shiftButton.setAttribute("disabled", "disabled");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
isValid = ()=>{
|
|
||||||
return selectedCoin && specifiedSideShiftDestination.value &&
|
|
||||||
(!selectedCoin.memo || specifiedSideShiftMemo.value);
|
|
||||||
};
|
|
||||||
handleSelectChanges = ()=>{
|
|
||||||
if (selectedSideShiftCoin.value){
|
|
||||||
selectedCoin = ssAvailableCoins[selectedSideShiftCoin.value];
|
|
||||||
destinationContainer.style.display = "block";
|
|
||||||
if (selectedCoin){
|
|
||||||
specifiedSideShiftMemo.parentElement.style.display = selectedCoin.memo ? "block" : "none";
|
|
||||||
specifiedSideShiftMemo.value = selectedCoin.memo ? specifiedSideShiftMemo.value : "";
|
|
||||||
}
|
|
||||||
}else{
|
|
||||||
destinationContainer.style.display = "none";
|
|
||||||
}
|
|
||||||
};
|
|
||||||
selectedSideShiftCoin.addEventListener("change", ev1 => {
|
|
||||||
handleSelectChanges();
|
|
||||||
});
|
|
||||||
shiftButton.addEventListener("click", ev1 => {
|
|
||||||
|
|
||||||
document.getElementById("ss-server-errors").innerHTML = "";
|
|
||||||
document.getElementById("ss-result-txt").value = "";
|
|
||||||
document.getElementById("ss-result-additional-info").value = "";
|
|
||||||
if (isValid()){
|
|
||||||
shiftButton.setAttribute("disabled", "disabled");
|
|
||||||
const type = "permanent";
|
|
||||||
|
|
||||||
if (type ==="permanent"){
|
|
||||||
fetch("https://sideshift.ai/api/v2/shifts/variable",{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json"
|
|
||||||
},
|
|
||||||
body: JSON.stringify({
|
|
||||||
settleAddress: specifiedSideShiftDestination.value,
|
|
||||||
settleMemo: specifiedSideShiftMemo.value,
|
|
||||||
affiliateId: "qg0OrfHJV",
|
|
||||||
depositCoin : "BTC",
|
|
||||||
depositNetwork : specifiedSideShiftDepositNetwork.value,
|
|
||||||
settleCoin: selectedCoin.code,
|
|
||||||
settleNetwork: selectedCoin.network,
|
|
||||||
permanent: true
|
|
||||||
})})
|
|
||||||
.then(async response => {
|
|
||||||
if (!response.ok){
|
|
||||||
try {
|
|
||||||
document.getElementById("ss-server-errors").innerHTML = (await response.json())["error"]["message"];
|
|
||||||
}catch{
|
|
||||||
document.getElementById("ss-server-errors").innerHTML = JSON.stringify((await response.json()));
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const shift = await response.json();
|
|
||||||
document.getElementById("ss-result").style.display = "block";
|
|
||||||
document.getElementById("ss-result-txt").value = shift.depositAddress;
|
|
||||||
const link = `https://sideshift.ai/orders/${shift.id}`;
|
|
||||||
document.getElementById("ss-result-additional-info").innerHTML = "<b>IMPORTANT:</b> You must keep this link to be able to recover your funds in case of a problem. <a href='"+link+"' target='_blank'>"+link+"</a> ";
|
|
||||||
|
|
||||||
})
|
|
||||||
.catch(error => document.getElementById("ss-server-errors").innerHTML = error)
|
|
||||||
.finally(() => shiftButton.removeAttribute("disabled"));
|
|
||||||
}else{
|
|
||||||
document.getElementById("ss-result").style.display = "block";
|
|
||||||
document.getElementById("ss-result-txt").value = "sideshift:"+JSON.stringify({
|
|
||||||
shiftCoin:selectedCoin.code,
|
|
||||||
shiftNetwork: selectedCoin.network,
|
|
||||||
shiftDestination: specifiedSideShiftDestination.value,
|
|
||||||
shiftMemo: specifiedSideShiftMemo.value,
|
|
||||||
shiftDepositNetwork: specifiedSideShiftDepositNetwork.value
|
|
||||||
});
|
|
||||||
shiftButton.removeAttribute("disabled");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
handleSelectChanges();
|
|
||||||
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div class="modal" tabindex="-1" id="sideshiftModal">
|
|
||||||
<div class="modal-dialog">
|
|
||||||
<div class="modal-content">
|
|
||||||
<div class="modal-header">
|
|
||||||
<h5 class="modal-title">Generate SideShift destination</h5>
|
|
||||||
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
|
|
||||||
</div>
|
|
||||||
<div class="modal-body">
|
|
||||||
|
|
||||||
<div id="ss-server-errors" class="text-danger"></div>
|
|
||||||
<p>This will generate a piece of code based on Sideshift configuration that can work as a valid destination in prism. Prism will then generate a "shift" on Sideshift and send the funds through LN to it, and Sideshift will send you the conversion. </p>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label">How do you want to send BTC to SideShift?</label>
|
|
||||||
<select id="ssdepositNetwork" class="form-select">
|
|
||||||
<option value="lightning">Lightning</option>
|
|
||||||
<option value="bitcoin">On-Chain</option>
|
|
||||||
</select>
|
|
||||||
</div><div class="form-group">
|
|
||||||
<label class="form-label">Which coin should Sideshift send you</label>
|
|
||||||
<select id="sscoin" class="form-select">
|
|
||||||
@foreach (var opt in coins)
|
|
||||||
{
|
|
||||||
<option value="@($"{opt.CryptoCode}_{opt.Network}")">@opt.ToString()</option>
|
|
||||||
}
|
|
||||||
</select>
|
|
||||||
</div>
|
|
||||||
<div id="ss-dest-info" style="display: none">
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label">Destination</label>
|
|
||||||
<input type="text" id="ssdest" class="form-control"/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label class="form-label">Memo</label>
|
|
||||||
<input type="text" id="ssmemo" class="form-control"/>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<button type="button" class="btn btn-primary" id="ssshift" disabled="disabled">Generate code</button>
|
|
||||||
|
|
||||||
<div id="ss-result" class="form-group mt-4" style="display: none;">
|
|
||||||
<label class="form-label">Generated code</label>
|
|
||||||
<div class="input-group">
|
|
||||||
<input type="text" id="ss-result-txt" class="form-control" readonly="readonly"/>
|
|
||||||
<button type="button" class="btn btn-secondary" data-clipboard-target="#ss-result-txt">
|
|
||||||
<vc:icon symbol="copy"/>
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
<p id="ss-result-additional-info"></p>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
@using BTCPayServer.Plugins.SideShift
|
@using BTCPayServer.Payouts
|
||||||
|
@using BTCPayServer.Plugins.SideShift
|
||||||
@model BTCPayServer.Models.ViewPullPaymentModel
|
@model BTCPayServer.Models.ViewPullPaymentModel
|
||||||
@inject SideShiftService SideShiftService
|
@inject SideShiftService SideShiftService
|
||||||
@{
|
@{
|
||||||
@@ -14,7 +15,8 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
var potentialPaymentMethods = Model.PaymentMethods;//.Where(id => id.CryptoCode.Equals(Model.Currency, StringComparison.OrdinalIgnoreCase)).ToList();
|
var potentialPaymentMethods = Model.PayoutMethodIds.ToList();//.Where(id => id.CryptoCode.Equals(Model.Currency, StringComparison.OrdinalIgnoreCase)).ToList();
|
||||||
|
potentialPaymentMethods.Remove(PayoutTypes.LN.GetPayoutMethodId("BTC"));
|
||||||
if (Model.IsPending && potentialPaymentMethods.Any())
|
if (Model.IsPending && potentialPaymentMethods.Any())
|
||||||
{
|
{
|
||||||
<script>
|
<script>
|
||||||
@@ -26,7 +28,7 @@
|
|||||||
memo = tuple.HasMemo,
|
memo = tuple.HasMemo,
|
||||||
network = tuple.Network
|
network = tuple.Network
|
||||||
}));
|
}));
|
||||||
const ssPaymentMethods = @Json.Serialize(potentialPaymentMethods.Select(id => new { id = id.ToString(), name= id.ToPrettyString()}));
|
const ssPaymentMethods = @Json.Serialize(potentialPaymentMethods.Select(id => new { id = id.ToString(), name= id.ToString()}));
|
||||||
document.addEventListener("DOMContentLoaded", ev => {
|
document.addEventListener("DOMContentLoaded", ev => {
|
||||||
const ssButton = document.createElement("button");
|
const ssButton = document.createElement("button");
|
||||||
ssButton.type= "button";
|
ssButton.type= "button";
|
||||||
@@ -142,7 +144,7 @@
|
|||||||
<select id="sspmi" class="form-select">
|
<select id="sspmi" class="form-select">
|
||||||
@foreach (var opt in potentialPaymentMethods)
|
@foreach (var opt in potentialPaymentMethods)
|
||||||
{
|
{
|
||||||
<option value="@opt.ToString()">@opt.ToPrettyString()</option>
|
<option value="@opt.ToString()">@opt.ToString()</option>
|
||||||
}
|
}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -4,13 +4,14 @@
|
|||||||
@using BTCPayServer.Plugins.SideShift
|
@using BTCPayServer.Plugins.SideShift
|
||||||
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
@using Microsoft.AspNetCore.Mvc.TagHelpers
|
||||||
@model BTCPayServer.Plugins.SideShift.SideShiftSettings
|
@model BTCPayServer.Plugins.SideShift.SideShiftSettings
|
||||||
@inject BTCPayNetworkProvider BTCPayNetworkProvider
|
|
||||||
@inject SideShiftService SideShiftService
|
@inject SideShiftService SideShiftService
|
||||||
@{
|
@{
|
||||||
ViewData.SetActivePage("SideShift", "SideShift", "SideShift");
|
ViewData.SetActivePage("SideShift", "SideShift", "SideShift");
|
||||||
var store = Context.GetStoreData();
|
var store = Context.GetStoreData();
|
||||||
var allowedPaymentMethods = store.GetEnabledPaymentIds(BTCPayNetworkProvider)
|
var allowedPaymentMethods = store.GetEnabledPaymentIds()
|
||||||
.Select(pmi => new SelectListItem(pmi.ToPrettyString(), pmi.ToString()))
|
.Where(id => !id.ToString().EndsWith("LN") && !id.ToString().EndsWith("LNURL"))
|
||||||
|
.Select(pmi => new SelectListItem(pmi.ToString(), pmi.ToString()))
|
||||||
|
|
||||||
.Prepend(new SelectListItem("Any", ""));
|
.Prepend(new SelectListItem("Any", ""));
|
||||||
var coins = await SideShiftService.GetDepositOptions();
|
var coins = await SideShiftService.GetDepositOptions();
|
||||||
var allowedCoins = coins.OrderBy(coin => coin.ToString()).Select(c => new SelectListItem(c.ToString(), $"{c.CryptoCode}_{c.Network}"));
|
var allowedCoins = coins.OrderBy(coin => coin.ToString()).Select(c => new SelectListItem(c.ToString(), $"{c.CryptoCode}_{c.Network}"));
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Subscriptions</Product>
|
<Product>Subscriptions</Product>
|
||||||
<Description>Offer and manage subscriptions through BTCPay Server</Description>
|
<Description>Offer and manage subscriptions through BTCPay Server</Description>
|
||||||
<Version>1.0.1</Version>
|
<Version>1.0.2</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -1,14 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer;
|
|
||||||
using BTCPayServer.Abstractions.Constants;
|
using BTCPayServer.Abstractions.Constants;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
using BTCPayServer.Abstractions.Extensions;
|
||||||
using BTCPayServer.Client;
|
using BTCPayServer.Client;
|
||||||
using BTCPayServer.Client.Models;
|
using BTCPayServer.Client.Models;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
using BTCPayServer.Plugins.Subscriptions;
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.PaymentRequests;
|
using BTCPayServer.Services.PaymentRequests;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@@ -23,13 +22,16 @@ namespace BTCPayServer.Plugins.Subscriptions;
|
|||||||
public class SubscriptionController : Controller
|
public class SubscriptionController : Controller
|
||||||
{
|
{
|
||||||
private readonly AppService _appService;
|
private readonly AppService _appService;
|
||||||
|
private readonly UriResolver _uriResolver;
|
||||||
private readonly PaymentRequestRepository _paymentRequestRepository;
|
private readonly PaymentRequestRepository _paymentRequestRepository;
|
||||||
private readonly SubscriptionService _subscriptionService;
|
private readonly SubscriptionService _subscriptionService;
|
||||||
|
|
||||||
public SubscriptionController(AppService appService,
|
public SubscriptionController(AppService appService,
|
||||||
|
UriResolver uriResolver,
|
||||||
PaymentRequestRepository paymentRequestRepository, SubscriptionService subscriptionService)
|
PaymentRequestRepository paymentRequestRepository, SubscriptionService subscriptionService)
|
||||||
{
|
{
|
||||||
_appService = appService;
|
_appService = appService;
|
||||||
|
_uriResolver = uriResolver;
|
||||||
_paymentRequestRepository = paymentRequestRepository;
|
_paymentRequestRepository = paymentRequestRepository;
|
||||||
_subscriptionService = subscriptionService;
|
_subscriptionService = subscriptionService;
|
||||||
}
|
}
|
||||||
@@ -44,7 +46,7 @@ public class SubscriptionController : Controller
|
|||||||
return NotFound();
|
return NotFound();
|
||||||
var ss = app.GetSettings<SubscriptionAppSettings>();
|
var ss = app.GetSettings<SubscriptionAppSettings>();
|
||||||
ss.SubscriptionName = app.Name;
|
ss.SubscriptionName = app.Name;
|
||||||
ViewData["StoreBranding"] = new StoreBrandingViewModel(app.StoreData.GetStoreBlob());
|
ViewData["StoreBranding"] =await StoreBrandingViewModel.CreateAsync(Request, _uriResolver, app.StoreData.GetStoreBlob());
|
||||||
return View(ss);
|
return View(ss);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,8 +64,7 @@ public class SubscriptionController : Controller
|
|||||||
{
|
{
|
||||||
return NotFound();
|
return NotFound();
|
||||||
}
|
}
|
||||||
|
ViewData["StoreBranding"] =await StoreBrandingViewModel.CreateAsync(Request, _uriResolver, app.StoreData.GetStoreBlob());
|
||||||
ViewData["StoreBranding"] = new StoreBrandingViewModel(app.StoreData.GetStoreBlob());
|
|
||||||
|
|
||||||
return View(ss);
|
return View(ss);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,9 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using BTCPayServer.Abstractions.Contracts;
|
using BTCPayServer.Abstractions.Contracts;
|
||||||
using BTCPayServer.Abstractions.Extensions;
|
|
||||||
using BTCPayServer.Abstractions.Models;
|
using BTCPayServer.Abstractions.Models;
|
||||||
using BTCPayServer.Abstractions.Services;
|
using BTCPayServer.Abstractions.Services;
|
||||||
using BTCPayServer.HostedServices.Webhooks;
|
using BTCPayServer.HostedServices.Webhooks;
|
||||||
using BTCPayServer.Services;
|
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -18,12 +16,11 @@ namespace BTCPayServer.Plugins.Subscriptions
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
[
|
[
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.13.0"}
|
new() {Identifier = nameof(BTCPayServer), Condition = ">=2.0.0"}
|
||||||
];
|
];
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
{
|
{
|
||||||
|
|
||||||
applicationBuilder.AddSingleton<ISwaggerProvider, SubscriptionsSwaggerProvider>();
|
applicationBuilder.AddSingleton<ISwaggerProvider, SubscriptionsSwaggerProvider>();
|
||||||
applicationBuilder.AddSingleton<SubscriptionService>();
|
applicationBuilder.AddSingleton<SubscriptionService>();
|
||||||
applicationBuilder.AddSingleton<IWebhookProvider>(o => o.GetRequiredService<SubscriptionService>());
|
applicationBuilder.AddSingleton<IWebhookProvider>(o => o.GetRequiredService<SubscriptionService>());
|
||||||
@@ -41,13 +38,11 @@ namespace BTCPayServer.Plugins.Subscriptions
|
|||||||
|
|
||||||
public SubscriptionsSwaggerProvider(IWebHostEnvironment webHostEnvironment)
|
public SubscriptionsSwaggerProvider(IWebHostEnvironment webHostEnvironment)
|
||||||
{
|
{
|
||||||
|
|
||||||
_fileProvider = webHostEnvironment.WebRootFileProvider;
|
_fileProvider = webHostEnvironment.WebRootFileProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async Task<JObject> Fetch()
|
public async Task<JObject> Fetch()
|
||||||
{
|
{
|
||||||
|
|
||||||
var file = _fileProvider.GetFileInfo("Resources/swagger.subscriptions.json");
|
var file = _fileProvider.GetFileInfo("Resources/swagger.subscriptions.json");
|
||||||
using var reader = new StreamReader(file.CreateReadStream());
|
using var reader = new StreamReader(file.CreateReadStream());
|
||||||
return JObject.Parse(await reader.ReadToEndAsync());
|
return JObject.Parse(await reader.ReadToEndAsync());
|
||||||
|
|||||||
@@ -48,10 +48,10 @@ public class AppMigrate : IStartupTask
|
|||||||
await using var ctx = _contextFactory.CreateContext();
|
await using var ctx = _contextFactory.CreateContext();
|
||||||
var invoices = await ctx.Invoices
|
var invoices = await ctx.Invoices
|
||||||
.Include(data => data.InvoiceSearchData)
|
.Include(data => data.InvoiceSearchData)
|
||||||
.Where(data => data.StoreDataId == setting.Key && data.OrderId == "tickettailor").ToListAsync(cancellationToken: cancellationToken);
|
.Where(data => data.StoreDataId == setting.Key && data.InvoiceSearchData.Any(searchData => searchData.Value == "tickettailor")).ToListAsync(cancellationToken: cancellationToken);
|
||||||
foreach (var invoice in invoices)
|
foreach (var invoice in invoices)
|
||||||
{
|
{
|
||||||
var entity = invoice.GetBlob(_btcPayNetworkProvider);
|
var entity = invoice.GetBlob();
|
||||||
entity.Metadata.SetAdditionalData("appId", app.Id);
|
entity.Metadata.SetAdditionalData("appId", app.Id);
|
||||||
entity.InternalTags.Add(AppService.GetAppInternalTag(app.Id));
|
entity.InternalTags.Add(AppService.GetAppInternalTag(app.Id));
|
||||||
InvoiceRepository.AddToTextSearch(ctx, invoice, AppService.GetAppSearchTerm(app) );
|
InvoiceRepository.AddToTextSearch(ctx, invoice, AppService.GetAppSearchTerm(app) );
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>TicketTailor</Product>
|
<Product>TicketTailor</Product>
|
||||||
<Description>Allows you to integrate with TicketTailor.com to sell tickets for Bitcoin</Description>
|
<Description>Allows you to integrate with TicketTailor.com to sell tickets for Bitcoin</Description>
|
||||||
<Version>2.0.3</Version>
|
<Version>2.0.4</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<!-- Plugin development properties -->
|
<!-- Plugin development properties -->
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ using BTCPayServer.Client.Models;
|
|||||||
using BTCPayServer.Controllers;
|
using BTCPayServer.Controllers;
|
||||||
using BTCPayServer.Data;
|
using BTCPayServer.Data;
|
||||||
using BTCPayServer.Models;
|
using BTCPayServer.Models;
|
||||||
|
using BTCPayServer.Services;
|
||||||
using BTCPayServer.Services.Apps;
|
using BTCPayServer.Services.Apps;
|
||||||
using BTCPayServer.Services.Invoices;
|
using BTCPayServer.Services.Invoices;
|
||||||
using Microsoft.AspNetCore.Authorization;
|
using Microsoft.AspNetCore.Authorization;
|
||||||
@@ -28,6 +29,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
{
|
{
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly TicketTailorService _ticketTailorService;
|
private readonly TicketTailorService _ticketTailorService;
|
||||||
|
private readonly UriResolver _uriResolver;
|
||||||
private readonly AppService _appService;
|
private readonly AppService _appService;
|
||||||
private readonly ApplicationDbContextFactory _contextFactory;
|
private readonly ApplicationDbContextFactory _contextFactory;
|
||||||
private readonly InvoiceRepository _invoiceRepository;
|
private readonly InvoiceRepository _invoiceRepository;
|
||||||
@@ -35,6 +37,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
|
|
||||||
public TicketTailorController(IHttpClientFactory httpClientFactory,
|
public TicketTailorController(IHttpClientFactory httpClientFactory,
|
||||||
TicketTailorService ticketTailorService,
|
TicketTailorService ticketTailorService,
|
||||||
|
UriResolver uriResolver,
|
||||||
AppService appService,
|
AppService appService,
|
||||||
ApplicationDbContextFactory contextFactory,
|
ApplicationDbContextFactory contextFactory,
|
||||||
InvoiceRepository invoiceRepository,
|
InvoiceRepository invoiceRepository,
|
||||||
@@ -42,6 +45,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
{
|
{
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_ticketTailorService = ticketTailorService;
|
_ticketTailorService = ticketTailorService;
|
||||||
|
_uriResolver = uriResolver;
|
||||||
_appService = appService;
|
_appService = appService;
|
||||||
_contextFactory = contextFactory;
|
_contextFactory = contextFactory;
|
||||||
_invoiceRepository = invoiceRepository;
|
_invoiceRepository = invoiceRepository;
|
||||||
@@ -87,7 +91,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
return View(new TicketTailorViewModel()
|
return View(new TicketTailorViewModel()
|
||||||
{
|
{
|
||||||
Event = evt, Settings = config,
|
Event = evt, Settings = config,
|
||||||
StoreBranding = new StoreBrandingViewModel(app.StoreData.GetStoreBlob())
|
StoreBranding = await StoreBrandingViewModel.CreateAsync(Request, _uriResolver, app.StoreData.GetStoreBlob())
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -270,7 +274,6 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
AdditionalSearchTerms = new[] {"tickettailor", hold.Value.Item1.Id, evt.Id, AppService.GetAppSearchTerm(app)},
|
AdditionalSearchTerms = new[] {"tickettailor", hold.Value.Item1.Id, evt.Id, AppService.GetAppSearchTerm(app)},
|
||||||
Checkout =
|
Checkout =
|
||||||
{
|
{
|
||||||
RequiresRefundEmail = true,
|
|
||||||
RedirectAutomatically = price > 0,
|
RedirectAutomatically = price > 0,
|
||||||
RedirectURL = redirectUrl,
|
RedirectURL = redirectUrl,
|
||||||
},
|
},
|
||||||
@@ -292,13 +295,13 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
|
|
||||||
}, app.StoreData, HttpContext.Request.GetAbsoluteRoot(),new List<string> { AppService.GetAppInternalTag(appId) }, CancellationToken.None);
|
}, app.StoreData, HttpContext.Request.GetAbsoluteRoot(),new List<string> { AppService.GetAppInternalTag(appId) }, CancellationToken.None);
|
||||||
|
|
||||||
while (inv.Price == 0 && inv.Status == InvoiceStatusLegacy.New)
|
while (inv.Price == 0 && inv.Status == InvoiceStatus.New)
|
||||||
{
|
{
|
||||||
if (inv.Status == InvoiceStatusLegacy.New)
|
if (inv.Status == InvoiceStatus.New)
|
||||||
inv = await _invoiceRepository.GetInvoice(inv.Id);
|
inv = await _invoiceRepository.GetInvoice(inv.Id);
|
||||||
}
|
}
|
||||||
|
|
||||||
return inv.Status.ToModernStatus() == InvoiceStatus.Settled
|
return inv.Status == InvoiceStatus.Settled
|
||||||
? RedirectToAction("Receipt", new {invoiceId = inv.Id})
|
? RedirectToAction("Receipt", new {invoiceId = inv.Id})
|
||||||
: RedirectToAction("Checkout", "UIInvoice", new {invoiceId = inv.Id});
|
: RedirectToAction("Checkout", "UIInvoice", new {invoiceId = inv.Id});
|
||||||
}
|
}
|
||||||
@@ -342,13 +345,13 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
var appId = AppService.GetAppInternalTags(inv).First();
|
var appId = AppService.GetAppInternalTags(inv).First();
|
||||||
|
|
||||||
var result = new TicketReceiptPage() {InvoiceId = invoiceId};
|
var result = new TicketReceiptPage() {InvoiceId = invoiceId};
|
||||||
result.Status = inv.Status.ToModernStatus();
|
result.Status = inv.Status;
|
||||||
if (result.Status == InvoiceStatus.Settled &&
|
if (result.Status == InvoiceStatus.Settled &&
|
||||||
inv.Metadata.AdditionalData.TryGetValue("ticketIds", out var ticketIds))
|
inv.Metadata.AdditionalData.TryGetValue("ticketIds", out var ticketIds))
|
||||||
{
|
{
|
||||||
await SetTicketTailorTicketResult(appId, result, ticketIds.Values<string>());
|
await SetTicketTailorTicketResult(appId, result, ticketIds.Values<string>());
|
||||||
}
|
}
|
||||||
else if (inv.Status.ToModernStatus() == InvoiceStatus.Settled)
|
else if (inv.Status == InvoiceStatus.Settled)
|
||||||
{
|
{
|
||||||
await _ticketTailorService.CheckAndIssueTicket(inv.Id);
|
await _ticketTailorService.CheckAndIssueTicket(inv.Id);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ namespace BTCPayServer.Plugins.TicketTailor
|
|||||||
{
|
{
|
||||||
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
public override IBTCPayServerPlugin.PluginDependency[] Dependencies { get; } =
|
||||||
{
|
{
|
||||||
new() {Identifier = nameof(BTCPayServer), Condition = ">=1.12.0"}
|
new() {Identifier = nameof(BTCPayServer), Condition = ">=2.0.0"}
|
||||||
};
|
};
|
||||||
|
|
||||||
public override void Execute(IServiceCollection applicationBuilder)
|
public override void Execute(IServiceCollection applicationBuilder)
|
||||||
|
|||||||
@@ -101,8 +101,7 @@ public class TicketTailorService : EventHostedServiceBase, IWebhookProvider
|
|||||||
!new[]
|
!new[]
|
||||||
{
|
{
|
||||||
InvoiceStatus.Settled, InvoiceStatus.Expired, InvoiceStatus.Invalid
|
InvoiceStatus.Settled, InvoiceStatus.Expired, InvoiceStatus.Invalid
|
||||||
}.Contains(invoiceEvent.Invoice.GetInvoiceState().Status
|
}.Contains(invoiceEvent.Invoice.GetInvoiceState().Status):
|
||||||
.ToModernStatus()):
|
|
||||||
return;
|
return;
|
||||||
case InvoiceEvent invoiceEvent:
|
case InvoiceEvent invoiceEvent:
|
||||||
|
|
||||||
@@ -157,7 +156,7 @@ public class TicketTailorService : EventHostedServiceBase, IWebhookProvider
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (new[] {InvoiceStatus.Invalid, InvoiceStatus.Expired}.Contains(invoice.Status.ToModernStatus()))
|
if (new[] {InvoiceStatus.Invalid, InvoiceStatus.Expired}.Contains(invoice.Status))
|
||||||
{
|
{
|
||||||
|
|
||||||
if (invoice.Metadata.AdditionalData.TryGetValue("holdId", out var jHoldIdx) &&
|
if (invoice.Metadata.AdditionalData.TryGetValue("holdId", out var jHoldIdx) &&
|
||||||
@@ -178,7 +177,7 @@ public class TicketTailorService : EventHostedServiceBase, IWebhookProvider
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (invoice.Status.ToModernStatus() != InvoiceStatus.Settled)
|
if (invoice.Status != InvoiceStatus.Settled)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Product>Coinjoin</Product>
|
<Product>Coinjoin</Product>
|
||||||
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
|
<Description>Allows you to integrate your btcpayserver store with coinjoins.</Description>
|
||||||
<Version>1.0.100</Version>
|
<Version>1.0.101</Version>
|
||||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ using BTCPayServer.Data;
|
|||||||
using BTCPayServer.HostedServices;
|
using BTCPayServer.HostedServices;
|
||||||
using BTCPayServer.Payments;
|
using BTCPayServer.Payments;
|
||||||
using BTCPayServer.Payments.PayJoin;
|
using BTCPayServer.Payments.PayJoin;
|
||||||
|
using BTCPayServer.Payouts;
|
||||||
using BTCPayServer.Services;
|
using BTCPayServer.Services;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
using LinqKit;
|
using LinqKit;
|
||||||
@@ -37,12 +39,14 @@ using WalletWasabi.WabiSabi.Backend.Rounds;
|
|||||||
using WalletWasabi.WabiSabi.Client;
|
using WalletWasabi.WabiSabi.Client;
|
||||||
using WalletWasabi.Wallets;
|
using WalletWasabi.Wallets;
|
||||||
using LogLevel = WalletWasabi.Logging.LogLevel;
|
using LogLevel = WalletWasabi.Logging.LogLevel;
|
||||||
|
using SecureRandom = WalletWasabi.Crypto.Randomness.SecureRandom;
|
||||||
|
|
||||||
namespace BTCPayServer.Plugins.Wabisabi;
|
namespace BTCPayServer.Plugins.Wabisabi;
|
||||||
|
|
||||||
|
|
||||||
public class BTCPayWallet : IWallet, IDestinationProvider
|
public class BTCPayWallet : IWallet, IDestinationProvider
|
||||||
{
|
{
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private readonly WalletRepository _walletRepository;
|
private readonly WalletRepository _walletRepository;
|
||||||
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
private readonly BTCPayNetworkProvider _btcPayNetworkProvider;
|
||||||
private readonly BitcoinLikePayoutHandler _bitcoinLikePayoutHandler;
|
private readonly BitcoinLikePayoutHandler _bitcoinLikePayoutHandler;
|
||||||
@@ -56,6 +60,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
public static readonly BlockchainAnalyzer BlockchainAnalyzer = new();
|
public static readonly BlockchainAnalyzer BlockchainAnalyzer = new();
|
||||||
|
|
||||||
public BTCPayWallet(
|
public BTCPayWallet(
|
||||||
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
WalletRepository walletRepository,
|
WalletRepository walletRepository,
|
||||||
BTCPayNetworkProvider btcPayNetworkProvider,
|
BTCPayNetworkProvider btcPayNetworkProvider,
|
||||||
BitcoinLikePayoutHandler bitcoinLikePayoutHandler,
|
BitcoinLikePayoutHandler bitcoinLikePayoutHandler,
|
||||||
@@ -75,6 +80,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
WalletId = new WalletWasabi.Wallets.WalletId(new Guid(SHA256.HashData(Encoding.UTF8.GetBytes(storeId)).Take(16)
|
WalletId = new WalletWasabi.Wallets.WalletId(new Guid(SHA256.HashData(Encoding.UTF8.GetBytes(storeId)).Take(16)
|
||||||
.ToArray()));
|
.ToArray()));
|
||||||
KeyChain = keyChain;
|
KeyChain = keyChain;
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
_walletRepository = walletRepository;
|
_walletRepository = walletRepository;
|
||||||
_btcPayNetworkProvider = btcPayNetworkProvider;
|
_btcPayNetworkProvider = btcPayNetworkProvider;
|
||||||
_bitcoinLikePayoutHandler = bitcoinLikePayoutHandler;
|
_bitcoinLikePayoutHandler = bitcoinLikePayoutHandler;
|
||||||
@@ -495,7 +501,7 @@ public class BTCPayWallet : IWallet, IDestinationProvider
|
|||||||
if (storeIdForutxo != StoreId)
|
if (storeIdForutxo != StoreId)
|
||||||
{
|
{
|
||||||
var s = await _storeRepository.FindStore(storeIdForutxo);
|
var s = await _storeRepository.FindStore(storeIdForutxo);
|
||||||
var scheme = s.GetDerivationSchemeSettings(_btcPayNetworkProvider, "BTC");
|
var scheme = s.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, "BTC");
|
||||||
utxoDerivationScheme = scheme.AccountDerivation;
|
utxoDerivationScheme = scheme.AccountDerivation;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -689,7 +695,7 @@ public async Task<IEnumerable<IDestination>> GetNextDestinationsAsync(int count,
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var mixStore = await _storeRepository.FindStore(WabisabiStoreSettings.MixToOtherWallet);
|
var mixStore = await _storeRepository.FindStore(WabisabiStoreSettings.MixToOtherWallet);
|
||||||
var pm = mixStore.GetDerivationSchemeSettings(_btcPayNetworkProvider, "BTC");
|
var pm = mixStore.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, "BTC");
|
||||||
|
|
||||||
|
|
||||||
if (pm?.AccountDerivation?.ScriptPubKeyType() == DerivationScheme.ScriptPubKeyType())
|
if (pm?.AccountDerivation?.ScriptPubKeyType() == DerivationScheme.ScriptPubKeyType())
|
||||||
@@ -718,20 +724,19 @@ public async Task<IEnumerable<IDestination>> GetNextDestinationsAsync(int count,
|
|||||||
{
|
{
|
||||||
States = new [] {PayoutState.AwaitingPayment},
|
States = new [] {PayoutState.AwaitingPayment},
|
||||||
Stores = new []{StoreId},
|
Stores = new []{StoreId},
|
||||||
PaymentMethods = new []{"BTC"}
|
PayoutMethods = new []{ PayoutTypes.CHAIN.GetPayoutMethodId("BTC").ToString()}
|
||||||
})).Select(async data =>
|
})).Select(async data =>
|
||||||
{
|
{
|
||||||
|
|
||||||
var claim = await _bitcoinLikePayoutHandler.ParseClaimDestination(new PaymentMethodId("BTC", BitcoinPaymentType.Instance),
|
var payoutBlob = data.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
||||||
data.Destination, CancellationToken.None);
|
var claim = await _bitcoinLikePayoutHandler.ParseClaimDestination(payoutBlob.Destination, CancellationToken.None);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(claim.error) || claim.destination is not IBitcoinLikeClaimDestination bitcoinLikeClaimDestination )
|
if (!string.IsNullOrEmpty(claim.error) || claim.destination is not IBitcoinLikeClaimDestination bitcoinLikeClaimDestination || data.Amount is null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var payoutBlob = data.GetBlob(_btcPayNetworkJsonSerializerSettings);
|
var value = new Money(data.Amount.Value, MoneyUnit.BTC);
|
||||||
var value = new Money(payoutBlob.CryptoAmount.Value, MoneyUnit.BTC);
|
|
||||||
return new PendingPayment()
|
return new PendingPayment()
|
||||||
{
|
{
|
||||||
Identifier = data.Id,
|
Identifier = data.Id,
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ using System.Net.Http;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using BTCPayServer.Services.Invoices;
|
||||||
using BTCPayServer.Services.Stores;
|
using BTCPayServer.Services.Stores;
|
||||||
using BTCPayServer.Services.Wallets;
|
using BTCPayServer.Services.Wallets;
|
||||||
using NBitcoin;
|
using NBitcoin;
|
||||||
@@ -17,16 +18,19 @@ public class WabisabiScriptResolver: WabiSabiConfig.CoordinatorScriptResolver
|
|||||||
{
|
{
|
||||||
private readonly IHttpClientFactory _httpClientFactory;
|
private readonly IHttpClientFactory _httpClientFactory;
|
||||||
private readonly StoreRepository _storeRepository;
|
private readonly StoreRepository _storeRepository;
|
||||||
|
private readonly PaymentMethodHandlerDictionary _paymentMethodHandlerDictionary;
|
||||||
private readonly BTCPayNetworkProvider _networkProvider;
|
private readonly BTCPayNetworkProvider _networkProvider;
|
||||||
private readonly BTCPayWalletProvider _walletProvider;
|
private readonly BTCPayWalletProvider _walletProvider;
|
||||||
|
|
||||||
public WabisabiScriptResolver(IHttpClientFactory httpClientFactory,
|
public WabisabiScriptResolver(IHttpClientFactory httpClientFactory,
|
||||||
StoreRepository storeRepository,
|
StoreRepository storeRepository,
|
||||||
|
PaymentMethodHandlerDictionary paymentMethodHandlerDictionary,
|
||||||
BTCPayNetworkProvider networkProvider,
|
BTCPayNetworkProvider networkProvider,
|
||||||
BTCPayWalletProvider walletProvider)
|
BTCPayWalletProvider walletProvider)
|
||||||
{
|
{
|
||||||
_httpClientFactory = httpClientFactory;
|
_httpClientFactory = httpClientFactory;
|
||||||
_storeRepository = storeRepository;
|
_storeRepository = storeRepository;
|
||||||
|
_paymentMethodHandlerDictionary = paymentMethodHandlerDictionary;
|
||||||
_networkProvider = networkProvider;
|
_networkProvider = networkProvider;
|
||||||
_walletProvider = walletProvider;
|
_walletProvider = walletProvider;
|
||||||
}
|
}
|
||||||
@@ -61,7 +65,7 @@ public class WabisabiScriptResolver: WabiSabiConfig.CoordinatorScriptResolver
|
|||||||
var store = await _storeRepository.FindStore(value);
|
var store = await _storeRepository.FindStore(value);
|
||||||
var cryptoCode = _networkProvider.GetAll().OfType<BTCPayNetwork>()
|
var cryptoCode = _networkProvider.GetAll().OfType<BTCPayNetwork>()
|
||||||
.First(payNetwork => payNetwork.NBitcoinNetwork == network);
|
.First(payNetwork => payNetwork.NBitcoinNetwork == network);
|
||||||
var dss = store.GetDerivationSchemeSettings(_networkProvider, cryptoCode.CryptoCode);
|
var dss = store.GetDerivationSchemeSettings(_paymentMethodHandlerDictionary, cryptoCode.CryptoCode);
|
||||||
var w = _walletProvider.GetWallet(cryptoCode.CryptoCode);
|
var w = _walletProvider.GetWallet(cryptoCode.CryptoCode);
|
||||||
var kpi = await w.ReserveAddressAsync(store.Id, dss.AccountDerivation, "wabisabi coordinator");
|
var kpi = await w.ReserveAddressAsync(store.Id, dss.AccountDerivation, "wabisabi coordinator");
|
||||||
return kpi.ScriptPubKey;
|
return kpi.ScriptPubKey;
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user